Merge pull request #38120 from frappe/mergify/bp/version-15-hotfix/pr-38071
fix: handle partial return against invoices in payment entries (#38071)
This commit is contained in:
commit
57dea69185
@ -1054,9 +1054,9 @@ class PaymentEntry(AccountsController):
|
|||||||
item=self,
|
item=self,
|
||||||
)
|
)
|
||||||
|
|
||||||
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
|
|
||||||
|
|
||||||
for d in self.get("references"):
|
for d in self.get("references"):
|
||||||
|
# re-defining dr_or_cr for every reference in order to avoid the last value affecting calculation of reverse
|
||||||
|
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
|
||||||
cost_center = self.cost_center
|
cost_center = self.cost_center
|
||||||
if d.reference_doctype == "Sales Invoice" and not cost_center:
|
if d.reference_doctype == "Sales Invoice" and not cost_center:
|
||||||
cost_center = frappe.db.get_value(d.reference_doctype, d.reference_name, "cost_center")
|
cost_center = frappe.db.get_value(d.reference_doctype, d.reference_name, "cost_center")
|
||||||
@ -1072,11 +1072,9 @@ class PaymentEntry(AccountsController):
|
|||||||
against_voucher_type = d.reference_doctype
|
against_voucher_type = d.reference_doctype
|
||||||
against_voucher = d.reference_name
|
against_voucher = d.reference_name
|
||||||
|
|
||||||
reverse_dr_or_cr, standalone_note = 0, 0
|
reverse_dr_or_cr = 0
|
||||||
if d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]:
|
if d.reference_doctype in ["Sales Invoice", "Purchase Invoice"]:
|
||||||
is_return, return_against = frappe.db.get_value(
|
is_return = frappe.db.get_value(d.reference_doctype, d.reference_name, "is_return")
|
||||||
d.reference_doctype, d.reference_name, ["is_return", "return_against"]
|
|
||||||
)
|
|
||||||
payable_party_types = get_party_types_from_account_type("Payable")
|
payable_party_types = get_party_types_from_account_type("Payable")
|
||||||
receivable_party_types = get_party_types_from_account_type("Receivable")
|
receivable_party_types = get_party_types_from_account_type("Receivable")
|
||||||
if is_return and self.party_type in receivable_party_types and (self.payment_type == "Pay"):
|
if is_return and self.party_type in receivable_party_types and (self.payment_type == "Pay"):
|
||||||
@ -1086,7 +1084,7 @@ class PaymentEntry(AccountsController):
|
|||||||
):
|
):
|
||||||
reverse_dr_or_cr = 1
|
reverse_dr_or_cr = 1
|
||||||
|
|
||||||
if is_return and not return_against and not reverse_dr_or_cr:
|
if is_return and not reverse_dr_or_cr:
|
||||||
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
|
dr_or_cr = "debit" if dr_or_cr == "credit" else "credit"
|
||||||
|
|
||||||
gle.update(
|
gle.update(
|
||||||
@ -1100,6 +1098,7 @@ class PaymentEntry(AccountsController):
|
|||||||
)
|
)
|
||||||
gl_entries.append(gle)
|
gl_entries.append(gle)
|
||||||
|
|
||||||
|
dr_or_cr = "credit" if self.payment_type == "Receive" else "debit"
|
||||||
if self.unallocated_amount:
|
if self.unallocated_amount:
|
||||||
exchange_rate = self.get_exchange_rate()
|
exchange_rate = self.get_exchange_rate()
|
||||||
base_unallocated_amount = self.unallocated_amount * exchange_rate
|
base_unallocated_amount = self.unallocated_amount * exchange_rate
|
||||||
|
@ -1250,6 +1250,9 @@ class TestPaymentEntry(FrappeTestCase):
|
|||||||
self.assertEqual(so.advance_paid, so.rounded_total)
|
self.assertEqual(so.advance_paid, so.rounded_total)
|
||||||
|
|
||||||
def test_receive_payment_from_payable_party_type(self):
|
def test_receive_payment_from_payable_party_type(self):
|
||||||
|
"""
|
||||||
|
Checks GL entries generated while receiving payments from a Payable Party Type.
|
||||||
|
"""
|
||||||
pe = create_payment_entry(
|
pe = create_payment_entry(
|
||||||
party_type="Supplier",
|
party_type="Supplier",
|
||||||
party="_Test Supplier",
|
party="_Test Supplier",
|
||||||
@ -1261,8 +1264,57 @@ class TestPaymentEntry(FrappeTestCase):
|
|||||||
)
|
)
|
||||||
self.voucher_no = pe.name
|
self.voucher_no = pe.name
|
||||||
self.expected_gle = [
|
self.expected_gle = [
|
||||||
{"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0},
|
|
||||||
{"account": "Creditors - _TC", "debit": 0.0, "credit": 1000.0},
|
{"account": "Creditors - _TC", "debit": 0.0, "credit": 1000.0},
|
||||||
|
{"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0},
|
||||||
|
]
|
||||||
|
self.check_gl_entries()
|
||||||
|
|
||||||
|
def test_payment_against_partial_return_invoice(self):
|
||||||
|
"""
|
||||||
|
Checks GL entries generated for partial return invoice payments.
|
||||||
|
"""
|
||||||
|
si = create_sales_invoice(qty=10, rate=10, customer="_Test Customer")
|
||||||
|
credit_note = create_sales_invoice(
|
||||||
|
qty=-4, rate=10, customer="_Test Customer", is_return=1, return_against=si.name
|
||||||
|
)
|
||||||
|
pe = create_payment_entry(
|
||||||
|
party_type="Customer",
|
||||||
|
party="_Test Customer",
|
||||||
|
payment_type="Receive",
|
||||||
|
paid_from="Debtors - _TC",
|
||||||
|
paid_to="_Test Cash - _TC",
|
||||||
|
)
|
||||||
|
pe.set(
|
||||||
|
"references",
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"reference_doctype": "Sales Invoice",
|
||||||
|
"reference_name": si.name,
|
||||||
|
"due_date": si.get("due_date"),
|
||||||
|
"total_amount": si.grand_total,
|
||||||
|
"outstanding_amount": si.outstanding_amount,
|
||||||
|
"allocated_amount": si.outstanding_amount,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"reference_doctype": "Sales Invoice",
|
||||||
|
"reference_name": credit_note.name,
|
||||||
|
"due_date": credit_note.get("due_date"),
|
||||||
|
"total_amount": credit_note.grand_total,
|
||||||
|
"outstanding_amount": credit_note.outstanding_amount,
|
||||||
|
"allocated_amount": credit_note.outstanding_amount,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
pe.save()
|
||||||
|
pe.submit()
|
||||||
|
self.assertEqual(pe.total_allocated_amount, 60)
|
||||||
|
self.assertEqual(pe.unallocated_amount, 940)
|
||||||
|
self.voucher_no = pe.name
|
||||||
|
self.expected_gle = [
|
||||||
|
{"account": "Debtors - _TC", "debit": 40.0, "credit": 0.0},
|
||||||
|
{"account": "Debtors - _TC", "debit": 0.0, "credit": 940.0},
|
||||||
|
{"account": "Debtors - _TC", "debit": 0.0, "credit": 100.0},
|
||||||
|
{"account": "_Test Cash - _TC", "debit": 1000.0, "credit": 0.0},
|
||||||
]
|
]
|
||||||
self.check_gl_entries()
|
self.check_gl_entries()
|
||||||
|
|
||||||
@ -1276,7 +1328,7 @@ class TestPaymentEntry(FrappeTestCase):
|
|||||||
gle.credit,
|
gle.credit,
|
||||||
)
|
)
|
||||||
.where((gle.voucher_no == self.voucher_no) & (gle.is_cancelled == 0))
|
.where((gle.voucher_no == self.voucher_no) & (gle.is_cancelled == 0))
|
||||||
.orderby(gle.account)
|
.orderby(gle.account, gle.debit, gle.credit, order=frappe.qb.desc)
|
||||||
).run(as_dict=True)
|
).run(as_dict=True)
|
||||||
for row in range(len(self.expected_gle)):
|
for row in range(len(self.expected_gle)):
|
||||||
for field in ["account", "debit", "credit"]:
|
for field in ["account", "debit", "credit"]:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user