From 70d5d2cb2bf593e94fe3c809d86693bf514a1477 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Fri, 23 Apr 2021 14:46:52 +0530 Subject: [PATCH] feat: base payment amount in payment schedule --- .../payment_schedule/payment_schedule.json | 104 +++++++++++++++++- .../purchase_invoice/test_purchase_invoice.py | 2 +- erpnext/controllers/accounts_controller.py | 60 ++++++---- erpnext/public/js/controllers/transaction.js | 5 +- 4 files changed, 145 insertions(+), 26 deletions(-) diff --git a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json index 0dde9fff050..f4f21744ce6 100644 --- a/erpnext/accounts/doctype/payment_schedule/payment_schedule.json +++ b/erpnext/accounts/doctype/payment_schedule/payment_schedule.json @@ -10,8 +10,13 @@ "due_date", "invoice_portion", "payment_amount", - "mode_of_payment", - "paid_amount" + "outstanding", + "paid_amount", + "discounted_amount", + "column_break_3", + "base_payment_amount", + "base_outstanding", + "base_paid_amount" ], "fields": [ { @@ -52,6 +57,7 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Payment Amount", + "options": "currency", "reqd": 1 }, { @@ -63,12 +69,102 @@ { "fieldname": "paid_amount", "fieldtype": "Currency", - "label": "Paid Amount" + "label": "Paid Amount", + "options": "currency" + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "default": "0", + "depends_on": "discounted_amount", + "fieldname": "discounted_amount", + "fieldtype": "Currency", + "label": "Discounted Amount", + "read_only": 1 + }, + { + "fetch_from": "payment_amount", + "fieldname": "outstanding", + "fieldtype": "Currency", + "label": "Outstanding", + "options": "currency", + "read_only": 1 + }, + { + "fieldname": "column_break_5", + "fieldtype": "Column Break" + }, + { + "depends_on": "discount", + "fieldname": "discount_date", + "fieldtype": "Date", + "label": "Discount Date", + "mandatory_depends_on": "discount" + }, + { + "default": "Percentage", + "fetch_from": "payment_term.discount_type", + "fieldname": "discount_type", + "fieldtype": "Select", + "label": "Discount Type", + "options": "Percentage\nAmount" + }, + { + "fetch_from": "payment_term.discount", + "fieldname": "discount", + "fieldtype": "Float", + "label": "Discount" + }, + { + "fieldname": "section_break_9", + "fieldtype": "Section Break" + }, + { + "collapsible": 1, + "fieldname": "section_break_15", + "fieldtype": "Section Break", + "label": "Description" + }, + { + "fieldname": "section_break_6", + "fieldtype": "Section Break" + }, + { + "fieldname": "column_break_9", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_4", + "fieldtype": "Section Break" + }, + { + "fieldname": "base_payment_amount", + "fieldtype": "Currency", + "label": "Payment Amount (Company Currency)", + "options": "Company:company:default_currency" + }, + { + "default": "0", + "fieldname": "base_outstanding", + "fieldtype": "Currency", + "label": "Outstanding (Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 + }, + { + "default": "0", + "fieldname": "base_paid_amount", + "fieldtype": "Currency", + "label": "Paid Amount (Company Currency)", + "options": "Company:company:default_currency", + "read_only": 1 } ], "istable": 1, "links": [], - "modified": "2021-04-12 15:39:47.363609", + "modified": "2021-04-23 13:55:59.548043", "modified_by": "Administrator", "module": "Accounts", "name": "Payment Schedule", diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index ded293b88d5..913288063fa 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -397,7 +397,7 @@ class TestPurchaseInvoice(unittest.TestCase): pi.update({ "payment_schedule": get_payment_terms("_Test Payment Term Template", - pi.posting_date, pi.grand_total) + pi.posting_date, pi.grand_total, pi.base_grand_total) }) pi.save() diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 829e0b160d4..add9e9946b9 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -884,20 +884,24 @@ class AccountsController(TransactionBase): date = self.get("due_date") due_date = date or posting_date - if party_account_currency == self.company_currency: - grand_total = self.get("base_rounded_total") or self.base_grand_total - else: - grand_total = self.get("rounded_total") or self.grand_total + base_grand_total = self.get("base_rounded_total") or self.base_grand_total + grand_total = self.get("rounded_total") or self.grand_total if self.doctype in ("Sales Invoice", "Purchase Invoice"): + base_grand_total = base_grand_total - flt(self.base_write_off_amount) grand_total = grand_total - flt(self.write_off_amount) if self.get("total_advance"): - grand_total -= self.get("total_advance") + if party_account_currency == self.company_currency: + base_grand_total -= self.get("total_advance") + grand_total = flt(base_grand_total / self.get("conversion_rate"), self.precision("grand_total")) + else: + grand_total -= self.get("total_advance") + base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total")) if not self.get("payment_schedule"): if self.get("payment_terms_template"): - data = get_payment_terms(self.payment_terms_template, posting_date, grand_total) + data = get_payment_terms(self.payment_terms_template, posting_date, grand_total, base_grand_total) for item in data: self.append("payment_schedule", item) else: @@ -906,7 +910,10 @@ class AccountsController(TransactionBase): else: for d in self.get("payment_schedule"): if d.invoice_portion: - d.payment_amount = flt(grand_total * flt(d.invoice_portion) / 100, d.precision('payment_amount')) + d.payment_amount = flt(grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount')) + d.base_payment_amount = flt(base_grand_total * flt(d.invoice_portion / 100), d.precision('payment_amount')) + d.outstanding = d.payment_amount + d.base_outstanding = d.base_payment_amount def set_due_date(self): due_dates = [d.due_date for d in self.get("payment_schedule") if d.due_date] @@ -942,22 +949,28 @@ class AccountsController(TransactionBase): if self.get("payment_schedule"): total = 0 + base_total = 0 for d in self.get("payment_schedule"): total += flt(d.payment_amount) + base_total += flt(d.base_payment_amount) - if party_account_currency == self.company_currency: - total = flt(total, self.precision("base_grand_total")) - grand_total = flt(self.get("base_rounded_total") or self.base_grand_total, self.precision('base_grand_total')) - else: - total = flt(total, self.precision("grand_total")) - grand_total = flt(self.get("rounded_total") or self.grand_total, self.precision('grand_total')) - - if self.get("total_advance"): - grand_total -= self.get("total_advance") + base_grand_total = self.get("base_rounded_total") or self.base_grand_total + grand_total = self.get("rounded_total") or self.grand_total if self.doctype in ("Sales Invoice", "Purchase Invoice"): + base_grand_total = base_grand_total - flt(self.base_write_off_amount) grand_total = grand_total - flt(self.write_off_amount) - if total != flt(grand_total, self.precision("grand_total")): + + if self.get("total_advance"): + if party_account_currency == self.company_currency: + base_grand_total -= self.get("total_advance") + grand_total = flt(base_grand_total / self.get("conversion_rate"), self.precision("grand_total")) + else: + grand_total -= self.get("total_advance") + base_grand_total = flt(grand_total * self.get("conversion_rate"), self.precision("base_grand_total")) + + if total != flt(grand_total, self.precision("grand_total")) or \ + base_total != flt(base_grand_total, self.precision("base_grand_total")): frappe.throw(_("Total Payment Amount in Payment Schedule must be equal to Grand / Rounded Total")) def is_rounded_total_disabled(self): @@ -1197,7 +1210,7 @@ def update_invoice_status(): @frappe.whitelist() -def get_payment_terms(terms_template, posting_date=None, grand_total=None, bill_date=None): +def get_payment_terms(terms_template, posting_date=None, grand_total=None, base_grand_total=None, bill_date=None): if not terms_template: return @@ -1205,14 +1218,14 @@ def get_payment_terms(terms_template, posting_date=None, grand_total=None, bill_ schedule = [] for d in terms_doc.get("terms"): - term_details = get_payment_term_details(d, posting_date, grand_total, bill_date) + term_details = get_payment_term_details(d, posting_date, grand_total, base_grand_total, bill_date) schedule.append(term_details) return schedule @frappe.whitelist() -def get_payment_term_details(term, posting_date=None, grand_total=None, bill_date=None): +def get_payment_term_details(term, posting_date=None, grand_total=None, base_grand_total=None, bill_date=None): term_details = frappe._dict() if isinstance(term, text_type): term = frappe.get_doc("Payment Term", term) @@ -1221,6 +1234,13 @@ def get_payment_term_details(term, posting_date=None, grand_total=None, bill_dat term_details.description = term.description term_details.invoice_portion = term.invoice_portion term_details.payment_amount = flt(term.invoice_portion) * flt(grand_total) / 100 + term_details.base_payment_amount = flt(term.invoice_portion) * flt(base_grand_total) / 100 + term_details.discount_type = term.discount_type + term_details.discount = term.discount + term_details.outstanding = term_details.payment_amount + term_details.base_outstanding = term_details.base_payment_amount + term_details.mode_of_payment = term.mode_of_payment + if bill_date: term_details.due_date = get_due_date(term, bill_date) elif posting_date: diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index fc1c669782a..97daca781ad 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1962,6 +1962,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ terms_template: doc.payment_terms_template, posting_date: posting_date, grand_total: doc.rounded_total || doc.grand_total, + base_grand_total: doc.base_rounded_total || doc.base_grand_total, bill_date: doc.bill_date }, callback: function(r) { @@ -1976,13 +1977,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ payment_term: function(doc, cdt, cdn) { var row = locals[cdt][cdn]; if(row.payment_term) { + debugger; frappe.call({ method: "erpnext.controllers.accounts_controller.get_payment_term_details", args: { term: row.payment_term, bill_date: this.frm.doc.bill_date, posting_date: this.frm.doc.posting_date || this.frm.doc.transaction_date, - grand_total: this.frm.doc.rounded_total || this.frm.doc.grand_total + grand_total: this.frm.doc.rounded_total || this.frm.doc.grand_total, + base_grand_total: this.frm.doc.base_rounded_total || this.frm.doc.base_grand_total }, callback: function(r) { if(r.message && !r.exc) {