Merge pull request #42029 from ruthra-kumar/bug_in_advance_against_journal

fix: incorrect ledger entries on Advance payment against Journals for customer
This commit is contained in:
ruthra kumar
2024-06-30 05:37:51 +05:30
committed by GitHub
3 changed files with 241 additions and 2 deletions

View File

@@ -1312,13 +1312,21 @@ class PaymentEntry(AccountsController):
if reference.reference_doctype == "Sales Invoice":
return "credit", reference.account
if reference.reference_doctype == "Purchase Invoice":
return "debit", reference.account
if reference.reference_doctype == "Payment Entry":
# reference.account_type and reference.payment_type is only available for Reverse payments
if reference.account_type == "Receivable" and reference.payment_type == "Pay":
return "credit", self.party_account
else:
return "debit", self.party_account
return "debit", reference.account
if reference.reference_doctype == "Journal Entry":
if self.party_type == "Customer" and self.payment_type == "Receive":
return "credit", reference.account
else:
return "debit", reference.account
def add_advance_gl_for_reference(self, gl_entries, invoice):
args_dict = {

View File

@@ -109,6 +109,14 @@ class TestPaymentReconciliation(FrappeTestCase):
"account_currency": "INR",
"account_type": "Payable",
},
# 'Receivable' account for capturing advance received, under 'Liabilities' group
{
"attribute": "advance_receivable_account",
"account_name": "Advance Received",
"parent_account": "Current Liabilities - _PR",
"account_currency": "INR",
"account_type": "Receivable",
},
]
for x in accounts:
@@ -1574,6 +1582,229 @@ class TestPaymentReconciliation(FrappeTestCase):
)
self.assertEqual(len(pl_entries), 3)
def test_advance_payment_reconciliation_against_journal_for_customer(self):
frappe.db.set_value(
"Company",
self.company,
{
"book_advance_payments_in_separate_party_account": 1,
"default_advance_received_account": self.advance_receivable_account,
"reconcile_on_advance_payment_date": 0,
},
)
amount = 200.0
je = self.create_journal_entry(self.debit_to, self.bank, amount)
je.accounts[0].cost_center = self.main_cc.name
je.accounts[0].party_type = "Customer"
je.accounts[0].party = self.customer
je.accounts[1].cost_center = self.main_cc.name
je = je.save().submit()
pe = self.create_payment_entry(amount=amount).save().submit()
pr = self.create_payment_reconciliation()
pr.default_advance_account = self.advance_receivable_account
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 1)
self.assertEqual(len(pr.payments), 1)
invoices = [invoice.as_dict() for invoice in pr.invoices]
payments = [payment.as_dict() for payment in pr.payments]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
pr.reconcile()
# Assert Ledger Entries
gl_entries = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": pe.name, "is_cancelled": 0},
)
self.assertEqual(len(gl_entries), 4)
pl_entries = frappe.db.get_all(
"Payment Ledger Entry",
filters={"voucher_no": pe.name, "delinked": 0},
)
self.assertEqual(len(pl_entries), 3)
gl_entries = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": pe.name, "is_cancelled": 0},
fields=["account", "voucher_no", "against_voucher", "debit", "credit"],
order_by="account, against_voucher, debit",
)
expected_gle = [
{
"account": self.advance_receivable_account,
"voucher_no": pe.name,
"against_voucher": pe.name,
"debit": 0.0,
"credit": amount,
},
{
"account": self.advance_receivable_account,
"voucher_no": pe.name,
"against_voucher": pe.name,
"debit": amount,
"credit": 0.0,
},
{
"account": self.debit_to,
"voucher_no": pe.name,
"against_voucher": je.name,
"debit": 0.0,
"credit": amount,
},
{
"account": self.bank,
"voucher_no": pe.name,
"against_voucher": None,
"debit": amount,
"credit": 0.0,
},
]
self.assertEqual(gl_entries, expected_gle)
pl_entries = frappe.db.get_all(
"Payment Ledger Entry",
filters={"voucher_no": pe.name},
fields=["account", "voucher_no", "against_voucher_no", "amount"],
order_by="account, against_voucher_no, amount",
)
expected_ple = [
{
"account": self.advance_receivable_account,
"voucher_no": pe.name,
"against_voucher_no": pe.name,
"amount": -amount,
},
{
"account": self.advance_receivable_account,
"voucher_no": pe.name,
"against_voucher_no": pe.name,
"amount": amount,
},
{
"account": self.debit_to,
"voucher_no": pe.name,
"against_voucher_no": je.name,
"amount": -amount,
},
]
self.assertEqual(pl_entries, expected_ple)
def test_advance_payment_reconciliation_against_journal_for_supplier(self):
self.supplier = make_supplier("_Test Supplier")
frappe.db.set_value(
"Company",
self.company,
{
"book_advance_payments_in_separate_party_account": 1,
"default_advance_paid_account": self.advance_payable_account,
"reconcile_on_advance_payment_date": 0,
},
)
amount = 200.0
je = self.create_journal_entry(self.creditors, self.bank, -amount)
je.accounts[0].cost_center = self.main_cc.name
je.accounts[0].party_type = "Supplier"
je.accounts[0].party = self.supplier
je.accounts[1].cost_center = self.main_cc.name
je = je.save().submit()
pe = self.create_payment_entry(amount=amount)
pe.payment_type = "Pay"
pe.party_type = "Supplier"
pe.paid_from = self.bank
pe.paid_to = self.creditors
pe.party = self.supplier
pe.save().submit()
pr = self.create_payment_reconciliation(party_is_customer=False)
pr.default_advance_account = self.advance_payable_account
pr.get_unreconciled_entries()
self.assertEqual(len(pr.invoices), 1)
self.assertEqual(len(pr.payments), 1)
invoices = [invoice.as_dict() for invoice in pr.invoices]
payments = [payment.as_dict() for payment in pr.payments]
pr.allocate_entries(frappe._dict({"invoices": invoices, "payments": payments}))
pr.reconcile()
# Assert Ledger Entries
gl_entries = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": pe.name, "is_cancelled": 0},
)
self.assertEqual(len(gl_entries), 4)
pl_entries = frappe.db.get_all(
"Payment Ledger Entry",
filters={"voucher_no": pe.name, "delinked": 0},
)
self.assertEqual(len(pl_entries), 3)
gl_entries = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": pe.name, "is_cancelled": 0},
fields=["account", "voucher_no", "against_voucher", "debit", "credit"],
order_by="account, against_voucher, debit",
)
expected_gle = [
{
"account": self.advance_payable_account,
"voucher_no": pe.name,
"against_voucher": pe.name,
"debit": 0.0,
"credit": amount,
},
{
"account": self.advance_payable_account,
"voucher_no": pe.name,
"against_voucher": pe.name,
"debit": amount,
"credit": 0.0,
},
{
"account": self.creditors,
"voucher_no": pe.name,
"against_voucher": je.name,
"debit": amount,
"credit": 0.0,
},
{
"account": self.bank,
"voucher_no": pe.name,
"against_voucher": None,
"debit": 0.0,
"credit": amount,
},
]
self.assertEqual(gl_entries, expected_gle)
pl_entries = frappe.db.get_all(
"Payment Ledger Entry",
filters={"voucher_no": pe.name},
fields=["account", "voucher_no", "against_voucher_no", "amount"],
order_by="account, against_voucher_no, amount",
)
expected_ple = [
{
"account": self.advance_payable_account,
"voucher_no": pe.name,
"against_voucher_no": pe.name,
"amount": -amount,
},
{
"account": self.advance_payable_account,
"voucher_no": pe.name,
"against_voucher_no": pe.name,
"amount": amount,
},
{
"account": self.creditors,
"voucher_no": pe.name,
"against_voucher_no": je.name,
"amount": -amount,
},
]
self.assertEqual(pl_entries, expected_ple)
def make_customer(customer_name, currency=None):
if not frappe.db.exists("Customer", customer_name):

View File

@@ -107,7 +107,7 @@ class TestUnreconcilePayment(AccountsTestMixin, FrappeTestCase):
self.assertEqual(len(pe.references), 1)
self.assertEqual(pe.unallocated_amount, 100)
def test_02_unreconcile_one_payment_from_multi_payments(self):
def test_02_unreconcile_one_payment_among_multi_payments(self):
"""
Scenario: 2 payments, both split against 2 different invoices
Unreconcile only one payment from one invoice