From c4b0d17c087eaccfe1836274af7ed61e0150b4c7 Mon Sep 17 00:00:00 2001 From: tunde Date: Tue, 26 Sep 2017 00:48:30 +0100 Subject: [PATCH] fix bug: can't make PE for invoice with multi due date --- .../doctype/payment_entry/payment_entry.py | 19 ++++---- .../payment_entry/test_payment_entry.py | 19 ++++++-- erpnext/accounts/utils.py | 46 ++++++++++--------- 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index 406dfbc9d1..bbffc9a2b6 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -8,14 +8,16 @@ from frappe import _, scrub, ValidationError from frappe.utils import flt, comma_or, nowdate from erpnext.accounts.utils import get_outstanding_invoices, get_account_currency, get_balance_on from erpnext.accounts.party import get_party_account -from erpnext.accounts.doctype.journal_entry.journal_entry \ - import get_average_exchange_rate, get_default_bank_cash_account +from erpnext.accounts.doctype.journal_entry.journal_entry import get_default_bank_cash_account from erpnext.setup.utils import get_exchange_rate from erpnext.accounts.general_ledger import make_gl_entries from erpnext.hr.doctype.expense_claim.expense_claim import update_reimbursed_amount from erpnext.controllers.accounts_controller import AccountsController -class InvalidPaymentEntry(ValidationError): pass + +class InvalidPaymentEntry(ValidationError): + pass + class PaymentEntry(AccountsController): def setup_party_account_field(self): @@ -69,10 +71,9 @@ class PaymentEntry(AccountsController): def validate_duplicate_entry(self): reference_names = [] for d in self.get("references"): - if (d.reference_doctype, d.reference_name) in reference_names: + if (d.reference_doctype, d.reference_name, d.due_date) in reference_names: frappe.throw(_("Row #{0}: Duplicate entry in References {1} {2}").format(d.idx, d.reference_doctype, d.reference_name)) - reference_names.append((d.reference_doctype, d.reference_name)) - + reference_names.append((d.reference_doctype, d.reference_name, d.due_date)) def validate_allocated_amount(self): for d in self.get("references"): @@ -80,7 +81,6 @@ class PaymentEntry(AccountsController): if flt(d.allocated_amount) > flt(d.outstanding_amount): frappe.throw(_("Row #{0}: Allocated Amount cannot be greater than outstanding amount.").format(d.idx)) - def delink_advance_entry_references(self): for reference in self.references: if reference.reference_doctype in ("Sales Invoice", "Purchase Invoice"): @@ -128,7 +128,6 @@ class PaymentEntry(AccountsController): self.set_missing_ref_details() - def set_missing_ref_details(self): for d in self.get("references"): if d.allocated_amount: @@ -594,8 +593,8 @@ def get_negative_outstanding_invoices(party_type, party, party_account, total_fi "total_field": total_field, "voucher_type": voucher_type, "party_type": scrub(party_type), - "party_account": "debit_to" if party_type=="Customer" else "credit_to" - }), (party, party_account), as_dict = True) + "party_account": "debit_to" if party_type == "Customer" else "credit_to" + }), (party, party_account), as_dict=True) else: return [] diff --git a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py index 3264bbb5ee..a3a78a33e7 100644 --- a/erpnext/accounts/doctype/payment_entry/test_payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/test_payment_entry.py @@ -14,6 +14,7 @@ from erpnext.hr.doctype.expense_claim.test_expense_claim import make_expense_cla test_dependencies = ["Item"] + class TestPaymentEntry(unittest.TestCase): def test_payment_entry_against_order(self): so = make_sales_order() @@ -40,7 +41,7 @@ class TestPaymentEntry(unittest.TestCase): self.assertEqual(so_advance_paid, 0) def test_payment_entry_against_si_usd_to_usd(self): - si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC", + si = create_sales_invoice(customer="_Test Customer USD", debit_to="_Test Receivable USD - _TC", currency="USD", conversion_rate=50) pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank USD - _TC") pe.reference_no = "1" @@ -65,8 +66,20 @@ class TestPaymentEntry(unittest.TestCase): outstanding_amount = flt(frappe.db.get_value("Sales Invoice", si.name, "outstanding_amount")) self.assertEqual(outstanding_amount, 100) + def test_payment_entry_against_si_multi_due_dates(self): + si = create_sales_invoice(do_not_save=1) + si.payment_terms_template = '_Test Payment Term Template' + si.insert() + si.submit() + + pe = get_payment_entry(si.doctype, si.name) + pe.reference_no = "1" + pe.reference_date = "2016-01-01" + pe.insert() + pe.submit() + def test_payment_entry_against_pi(self): - pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC", + pi = make_purchase_invoice(supplier="_Test Supplier USD", debit_to="_Test Payable USD - _TC", currency="USD", conversion_rate=50) pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank USD - _TC") pe.reference_no = "1" @@ -88,7 +101,7 @@ class TestPaymentEntry(unittest.TestCase): def test_payment_entry_against_ec(self): payable = frappe.db.get_value('Company', "_Test Company", 'default_payable_account') - ec = make_expense_claim(payable, 300, 300, "_Test Company","Travel Expenses - _TC") + ec = make_expense_claim(payable, 300, 300, "_Test Company", "Travel Expenses - _TC") pe = get_payment_entry("Expense Claim", ec.name, bank_account="_Test Bank USD - _TC", bank_amount=300) pe.reference_no = "1" pe.reference_date = "2016-01-01" diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 6d6acedd3b..6a817887bd 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -569,11 +569,12 @@ def get_stock_rbnb_difference(posting_date, company): # Amount should be credited return flt(stock_rbnb) + flt(sys_bal) + def get_outstanding_invoices(party_type, party, account, condition=None): outstanding_invoices = [] precision = frappe.get_precision("Sales Invoice", "outstanding_amount") - if party_type=="Customer": + if party_type == "Customer": dr_or_cr = "debit_in_account_currency - credit_in_account_currency" payment_dr_or_cr = "payment_gl_entry.credit_in_account_currency - payment_gl_entry.debit_in_account_currency" else: @@ -584,11 +585,6 @@ def get_outstanding_invoices(party_type, party, account, condition=None): invoice_list = frappe.db.sql(""" select voucher_no, voucher_type, posting_date, ifnull(sum({dr_or_cr}), 0) as invoice_amount, due_date, - ( - case when (voucher_type = 'Sales Invoice' or voucher_type = 'Purchase Invoice') - then (select due_date from `tab{invoice}` where name = voucher_no) - else posting_date end - ) as due_date, ( select ifnull(sum({payment_dr_or_cr}), 0) from `tabGL Entry` payment_gl_entry @@ -612,10 +608,10 @@ def get_outstanding_invoices(party_type, party, account, condition=None): group by voucher_type, voucher_no, due_date having (invoice_amount - payment_amount) > 0.005 order by posting_date, name, due_date""".format( - dr_or_cr = dr_or_cr, - invoice = invoice, - payment_dr_or_cr = payment_dr_or_cr, - condition = condition or "" + dr_or_cr=dr_or_cr, + invoice=invoice, + payment_dr_or_cr=payment_dr_or_cr, + condition=condition or "" ), { "party_type": party_type, "party": party, @@ -623,18 +619,24 @@ def get_outstanding_invoices(party_type, party, account, condition=None): }, as_dict=True) for d in invoice_list: - due_date = d.due_date or (frappe.db.get_value(d.voucher_type, d.voucher_no, - "posting_date" if party_type=="Employee" else "due_date")) - outstanding_invoices.append(frappe._dict({ - 'voucher_no': d.voucher_no, - 'voucher_type': d.voucher_type, - 'due_date': d.due_date, - 'posting_date': d.posting_date, - 'invoice_amount': flt(d.invoice_amount), - 'payment_amount': flt(d.payment_amount), - 'outstanding_amount': flt(d.invoice_amount - d.payment_amount, precision), - 'due_date': due_date - })) + due_date = d.due_date or ( + frappe.db.get_value( + d.voucher_type, d.voucher_no, + "posting_date" if party_type == "Employee" else "due_date" + ) + ) + + outstanding_invoices.append( + frappe._dict({ + 'voucher_no': d.voucher_no, + 'voucher_type': d.voucher_type, + 'posting_date': d.posting_date, + 'invoice_amount': flt(d.invoice_amount), + 'payment_amount': flt(d.payment_amount), + 'outstanding_amount': flt(d.invoice_amount - d.payment_amount, precision), + 'due_date': due_date + }) + ) outstanding_invoices = sorted(outstanding_invoices, key=lambda k: k['due_date'] or getdate(nowdate()))