From 20e9599fc1db3d09cb79c93d47de2e4369928908 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Sun, 21 Aug 2022 17:51:05 +0530 Subject: [PATCH 1/4] fix: Cash and non trade discount calculation (cherry picked from commit 3b15966cc9fb2cf91eca9105f767d8775845f7fa) --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 2 +- .../doctype/sales_invoice/sales_invoice.js | 4 ++ .../doctype/sales_invoice/sales_invoice.py | 16 ------- erpnext/controllers/accounts_controller.py | 46 ++++++++++--------- erpnext/controllers/taxes_and_totals.py | 16 ++++--- .../public/js/controllers/taxes_and_totals.js | 10 ++++ 6 files changed, 49 insertions(+), 45 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 1a574edfe86..8a3f9341182 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -358,7 +358,7 @@ def update_outstanding_amt( if against_voucher_type in ["Sales Invoice", "Purchase Invoice", "Fees"]: ref_doc = frappe.get_doc(against_voucher_type, against_voucher) - # Didn't use db_set for optimisation purpose + # Didn't use db_set for optimization purpose ref_doc.outstanding_amount = bal frappe.db.set_value(against_voucher_type, against_voucher, "outstanding_amount", bal) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index 8f7038df30e..c765e4f07ff 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -480,9 +480,13 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte is_cash_or_non_trade_discount() { this.frm.set_df_property("additional_discount_account", "hidden", 1 - this.frm.doc.is_cash_or_non_trade_discount); + this.frm.set_df_property("additional_discount_account", "reqd", this.frm.doc.is_cash_or_non_trade_discount); + if (!this.frm.doc.is_cash_or_non_trade_discount) { this.frm.set_value("additional_discount_account", ""); } + + this.calculate_taxes_and_totals(); } }); diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 29f3970d0dc..1badb809341 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1065,22 +1065,6 @@ class SalesInvoice(SellingController): ) ) - if self.apply_discount_on == "Grand Total" and self.get("is_cash_or_discount_account"): - gl_entries.append( - self.get_gl_dict( - { - "account": self.additional_discount_account, - "against": self.debit_to, - "debit": self.base_discount_amount, - "debit_in_account_currency": self.discount_amount, - "cost_center": self.cost_center, - "project": self.project, - }, - self.currency, - item=self, - ) - ) - def make_tax_gl_entries(self, gl_entries): for tax in self.get("taxes"): amount, base_amount = self.get_tax_amounts(tax, self.enable_discount_accounting) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 4eee74b2cbd..41788f86114 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1105,17 +1105,17 @@ class AccountsController(TransactionBase): frappe.db.get_single_value("Accounts Settings", "enable_discount_accounting") ) + if self.doctype == "Purchase Invoice": + dr_or_cr = "credit" + rev_dr_cr = "debit" + supplier_or_customer = self.supplier + + else: + dr_or_cr = "debit" + rev_dr_cr = "credit" + supplier_or_customer = self.customer + if enable_discount_accounting: - if self.doctype == "Purchase Invoice": - dr_or_cr = "credit" - rev_dr_cr = "debit" - supplier_or_customer = self.supplier - - else: - dr_or_cr = "debit" - rev_dr_cr = "credit" - supplier_or_customer = self.customer - for item in self.get("items"): if item.get("discount_amount") and item.get("discount_account"): discount_amount = item.discount_amount * item.qty @@ -1169,18 +1169,22 @@ class AccountsController(TransactionBase): ) ) - if self.get("discount_amount") and self.get("additional_discount_account"): - gl_entries.append( - self.get_gl_dict( - { - "account": self.additional_discount_account, - "against": supplier_or_customer, - dr_or_cr: self.discount_amount, - "cost_center": self.cost_center, - }, - item=self, - ) + if ( + (enable_discount_accounting or self.is_cash_or_non_trade_discount) + and self.get("additional_discount_account") + and self.get("discount_amount") + ): + gl_entries.append( + self.get_gl_dict( + { + "account": self.additional_discount_account, + "against": supplier_or_customer, + dr_or_cr: self.discount_amount, + "cost_center": self.cost_center, + }, + item=self, ) + ) def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield): from erpnext.controllers.status_updater import get_allowance_for diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 589c75783fe..a10798a8af0 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -37,6 +37,11 @@ class calculate_taxes_and_totals(object): self.set_discount_amount() self.apply_discount_amount() + # Update grand total as per cash and non trade discount + if self.doc.apply_discount_on == "Grand Total" and self.doc.get("is_cash_or_non_trade_discount"): + self.doc.grand_total -= self.doc.discount_amount + self.doc.base_grand_total -= self.doc.base_discount_amount + self.calculate_shipping_charges() if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]: @@ -500,9 +505,6 @@ class calculate_taxes_and_totals(object): else: self.doc.grand_total = flt(self.doc.net_total) - if self.doc.apply_discount_on == "Grand Total" and self.doc.get("is_cash_or_non_trade_discount"): - self.doc.grand_total -= self.doc.discount_amount - if self.doc.get("taxes"): self.doc.total_taxes_and_charges = flt( self.doc.grand_total - self.doc.net_total - flt(self.doc.rounding_adjustment), @@ -597,16 +599,16 @@ class calculate_taxes_and_totals(object): if not self.doc.apply_discount_on: frappe.throw(_("Please select Apply Discount On")) + self.doc.base_discount_amount = flt( + self.doc.discount_amount * self.doc.conversion_rate, self.doc.precision("base_discount_amount") + ) + if self.doc.apply_discount_on == "Grand Total" and self.doc.get( "is_cash_or_non_trade_discount" ): self.discount_amount_applied = True return - self.doc.base_discount_amount = flt( - self.doc.discount_amount * self.doc.conversion_rate, self.doc.precision("base_discount_amount") - ) - total_for_discount_amount = self.get_total_for_discount_amount() taxes = self.doc.get("taxes") net_total = 0 diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index fe23ff38126..8e6ae752f67 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -39,6 +39,12 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this._calculate_taxes_and_totals(); this.calculate_discount_amount(); + // # Update grand total as per cash and non trade discount + if (this.frm.doc.apply_discount_on == "Grand Total" && this.frm.doc.is_cash_or_non_trade_discount) { + this.frm.doc.grand_total -= this.frm.doc.discount_amount; + this.frm.doc.base_grand_total -= this.frm.doc.base_discount_amount; + } + await this.calculate_shipping_charges(); // Advance calculation applicable to Sales /Purchase Invoice @@ -611,6 +617,10 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.doc.base_discount_amount = flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate, precision("base_discount_amount")); + if (this.frm.doc.apply_discount_on == "Grand Total" && this.frm.doc.is_cash_or_non_trade_discount) { + return + } + var total_for_discount_amount = this.get_total_for_discount_amount(); var net_total = 0; // calculate item amount after Discount Amount From 7c85b487cd20521f8a44aac37c771139e3926a83 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 22 Aug 2022 08:57:58 +0530 Subject: [PATCH 2/4] fix: Test cases (cherry picked from commit ae3dce0cbdca40294739b547d85bfca9b1e28c0f) --- erpnext/controllers/accounts_controller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 41788f86114..527c9389d8a 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1170,7 +1170,7 @@ class AccountsController(TransactionBase): ) if ( - (enable_discount_accounting or self.is_cash_or_non_trade_discount) + (enable_discount_accounting or self.get("is_cash_or_non_trade_discount")) and self.get("additional_discount_account") and self.get("discount_amount") ): From 6a9d13ff282f0ce6f94024f112521265d7d4935f Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 23 Aug 2022 09:12:20 +0530 Subject: [PATCH 3/4] chore: Linting issues (cherry picked from commit 1cb7ae16ab156da2fd43ec915316947b0b8db964) --- erpnext/public/js/controllers/taxes_and_totals.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 8e6ae752f67..c75e7b77f70 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -618,7 +618,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ precision("base_discount_amount")); if (this.frm.doc.apply_discount_on == "Grand Total" && this.frm.doc.is_cash_or_non_trade_discount) { - return + return; } var total_for_discount_amount = this.get_total_for_discount_amount(); From 4793adfefd60f32044bb2f7a89780743a1d3da0b Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 29 Aug 2022 14:02:18 +0530 Subject: [PATCH 4/4] chore: rounded total for cash and non trade discounts --- erpnext/controllers/taxes_and_totals.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index a10798a8af0..548ef03c2fd 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -41,6 +41,7 @@ class calculate_taxes_and_totals(object): if self.doc.apply_discount_on == "Grand Total" and self.doc.get("is_cash_or_non_trade_discount"): self.doc.grand_total -= self.doc.discount_amount self.doc.base_grand_total -= self.doc.base_discount_amount + self.set_rounded_total() self.calculate_shipping_charges()