From 4ffd7f3d0576d2c2278c9157e8ac6d33ce24c446 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Thu, 27 Aug 2015 12:28:36 +0530 Subject: [PATCH] Outstanding, paid and write-off amount in Invoice --- .../purchase_common/purchase_common.js | 13 +----- erpnext/controllers/accounts_controller.py | 42 ++++++++++++------- erpnext/controllers/taxes_and_totals.py | 28 +++++++------ .../public/js/controllers/taxes_and_totals.js | 40 ++++++++++++++++++ erpnext/public/js/controllers/transaction.js | 10 +++-- erpnext/public/js/pos/pos.js | 8 ++-- erpnext/selling/sales_common.js | 24 ----------- 7 files changed, 94 insertions(+), 71 deletions(-) diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index 7693e08094..f372cd84d8 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -157,20 +157,9 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ }, add_deduct_tax: function(doc, cdt, cdn) { this.calculate_taxes_and_totals(); - }, - - calculate_outstanding_amount: function() { - if(this.frm.doc.doctype == "Purchase Invoice" && this.frm.doc.docstatus < 2) { - frappe.model.round_floats_in(this.frm.doc, ["base_grand_total", "total_advance", "write_off_amount"]); - this.frm.doc.total_amount_to_pay = flt(this.frm.doc.base_grand_total - this.frm.doc.write_off_amount, - precision("total_amount_to_pay")); - if (!this.frm.doc.is_return) { - this.frm.doc.outstanding_amount = flt(this.frm.doc.total_amount_to_pay - this.frm.doc.total_advance, - precision("outstanding_amount")); - } - } } }); + cur_frm.add_fetch('project_name', 'cost_center', 'cost_center'); erpnext.buying.get_default_bom = function(frm) { diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 7775cb311f..6ba954f7a3 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -18,8 +18,13 @@ class CustomerFrozen(frappe.ValidationError): pass class AccountsController(TransactionBase): def __init__(self, arg1, arg2=None): super(AccountsController, self).__init__(arg1, arg2) - if self.get("company"): - self.company_currency = get_company_currency(self.company) + + @property + def company_currency(self): + if not hasattr(self, "__company_currency"): + self.__company_currency = get_company_currency(self.company) + + return self.__company_currency def validate(self): if self.get("_action") and self._action != "update_after_submit": @@ -221,10 +226,10 @@ class AccountsController(TransactionBase): return gl_dict def validate_account_currency(self, account, account_currency=None): - valid_currency = list(set(self.currency, self.company_currency)) + valid_currency = list(set([self.currency, self.company_currency])) if account_currency not in valid_currency: - frappe.throw(_("Invalid Account {0}. Account Currency must be {1}") - .format(account, "or".join(valid_currency))) + frappe.throw(_("Account {0} is invalid. Account Currency must be {1}") + .format(account, " or ".join(valid_currency))) def set_balance_in_account_currency(self, gl_dict, account_currency=None): if not self.get("conversion_rate") and account_currency!=self.company_currency: @@ -397,22 +402,28 @@ class AccountsController(TransactionBase): if frozen_accounts_modifier in frappe.get_roles(): return + party_type, party = self.get_party() + + if party_type: + if frappe.db.get_value(party_type, party, "is_frozen"): + frappe.throw("{0} {1} is frozen".format(party_type, party), CustomerFrozen) + + def get_party(self): party_type = None if self.meta.get_field("customer"): party_type = 'Customer' elif self.meta.get_field("supplier"): party_type = 'Supplier' - - if party_type: - party = self.get(party_type.lower()) - if frappe.db.get_value(party_type, party, "is_frozen"): - frappe.throw("{0} {1} is frozen".format(party_type, party), CustomerFrozen) - - self.validate_currency(party_type, party) - - def validate_currency(self, party_type, party): + + party = self.get(party_type.lower()) if party_type else None + + return party_type, party + + def validate_currency(self): if self.get("currency") and self.currency != self.company_currency: + party_type, party = self.get_party() + existing_gle = frappe.db.get_value("GL Entry", {"party_type": party_type, "party": party, "company": self.company}, ["name", "currency"], as_dict=1) currency_in_existing_entries = existing_gle.currency or self.company_currency @@ -420,7 +431,8 @@ class AccountsController(TransactionBase): if existing_gle: if currency_in_existing_entries != self.company_currency \ and currency_in_existing_entries != self.currency: - frappe.throw(_("Currency must be {0}").format(currency_in_existing_entries)) + frappe.throw(_("Currency must be {0} for {1} {2}") + .format(currency_in_existing_entries, party_type, party)) else: party_currency = frappe.db.get_value(party_type, party, "default_currency") if party_currency != self.company_currency and self.currency != party_currency: diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index d526f66baf..0fbe22d7af 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -394,17 +394,21 @@ class calculate_taxes_and_totals(object): # NOTE: # write_off_amount is only for POS Invoice # total_advance is only for non POS Invoice - + if self.doc.is_return: + return + + self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"]) + total_amount_to_pay = flt(self.doc.grand_total - self.doc.total_advance - self.doc.write_off_amount, + self.doc.precision("grand_total")) + if self.doc.doctype == "Sales Invoice": - if not self.doc.is_return: - self.doc.round_floats_in(self.doc, ["base_grand_total", "total_advance", "write_off_amount", "paid_amount"]) - total_amount_to_pay = self.doc.base_grand_total - self.doc.write_off_amount - self.doc.outstanding_amount = flt(total_amount_to_pay - self.doc.total_advance - self.doc.paid_amount, - self.doc.precision("outstanding_amount")) + self.doc.round_floats_in(self.doc, ["paid_amount"]) + outstanding_amount = flt(total_amount_to_pay - self.doc.paid_amount, self.doc.precision("outstanding_amount")) + elif self.doc.doctype == "Purchase Invoice": + outstanding_amount = flt(total_amount_to_pay, self.doc.precision("outstanding_amount")) + + if self.doc.party_account_currency == self.doc.currency: + self.doc.outstanding_amount = outstanding_amount else: - self.doc.round_floats_in(self.doc, ["total_advance", "write_off_amount"]) - self.doc.total_amount_to_pay = flt(self.doc.base_grand_total - self.doc.write_off_amount, - self.doc.precision("total_amount_to_pay")) - if not self.doc.is_return: - self.doc.outstanding_amount = flt(self.doc.total_amount_to_pay - self.doc.total_advance, - self.doc.precision("outstanding_amount")) + self.doc.outstanding_amount = flt(outstanding_amount * self.doc.conversion_rate, + self.doc.precision("outstanding_amount")) \ No newline at end of file diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 0b3ca7f2a8..ad794d6e19 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -491,5 +491,45 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ this.frm.doc.total_advance = flt(total_allocated_amount, precision("total_advance")); this.calculate_outstanding_amount(update_paid_amount); + }, + + calculate_outstanding_amount: function(update_paid_amount) { + // NOTE: + // paid_amount and write_off_amount is only for POS Invoice + // total_advance is only for non POS Invoice + if(this.frm.doc.is_return || this.frm.doc.docstatus > 0) return; + + frappe.model.round_floats_in(this.frm.doc, ["grand_total", "total_advance", "write_off_amount"]); + + var total_amount_to_pay = flt((this.frm.doc.grand_total - this.frm.doc.total_advance + - this.frm.doc.write_off_amount), precision("grand_total")); + + if(this.frm.doc.doctype == "Sales Invoice") { + frappe.model.round_floats_in(this.frm.doc, ["paid_amount"]); + + if(this.frm.doc.is_pos) { + if(!this.frm.doc.paid_amount || update_paid_amount===undefined || update_paid_amount) { + this.frm.doc.paid_amount = flt(total_amount_to_pay); + } + } else { + this.frm.doc.paid_amount = 0 + } + this.set_in_company_currency(this.frm.doc, ["paid_amount"]); + this.frm.refresh_field("paid_amount"); + this.frm.refresh_field("base_paid_amount"); + + var outstanding_amount = flt(total_amount_to_pay - this.frm.doc.paid_amount, + precision("outstanding_amount")); + + } else if(this.frm.doc.doctype == "Purchase Invoice") { + var outstanding_amount = flt(total_amount_to_pay, precision("outstanding_amount")); + } + + if(this.frm.doc.party_account_currency == this.frm.doc.currency) { + this.frm.set_value("outstanding_amount", outstanding_amount); + } else { + this.frm.set_value("outstanding_amount", + flt(outstanding_amount * this.frm.doc.conversion_rate, precision("outstanding_amount"))); + } } }) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index ba10702bd9..5cc75b6a8a 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -415,11 +415,14 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ setup_field_label_map(["base_total", "base_net_total", "base_total_taxes_and_charges", "base_discount_amount", "base_grand_total", "base_rounded_total", "base_in_words", "base_taxes_and_charges_added", "base_taxes_and_charges_deducted", "total_amount_to_pay", - "outstanding_amount", "total_advance", "paid_amount", "write_off_amount"], company_currency); + "base_paid_amount", "base_write_off_amount" + ], company_currency); setup_field_label_map(["total", "net_total", "total_taxes_and_charges", "discount_amount", "grand_total", "taxes_and_charges_added", "taxes_and_charges_deducted", - "rounded_total", "in_words"], this.frm.doc.currency); + "rounded_total", "in_words", "paid_amount", "write_off_amount"], this.frm.doc.currency); + + setup_field_label_map(["outstanding_amount", "total_advance"], this.frm.doc.party_account_currency); cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency + " = [?] " + company_currency) @@ -432,7 +435,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ // toggle fields this.frm.toggle_display(["conversion_rate", "base_total", "base_net_total", "base_total_taxes_and_charges", "base_taxes_and_charges_added", "base_taxes_and_charges_deducted", - "base_grand_total", "base_rounded_total", "base_in_words", "base_discount_amount"], + "base_grand_total", "base_rounded_total", "base_in_words", "base_discount_amount", + "base_paid_amount", "base_write_off_amount"], this.frm.doc.currency != company_currency); this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"], diff --git a/erpnext/public/js/pos/pos.js b/erpnext/public/js/pos/pos.js index 5f827964f6..02eeab0837 100644 --- a/erpnext/public/js/pos/pos.js +++ b/erpnext/public/js/pos/pos.js @@ -473,13 +473,11 @@ erpnext.pos.PointOfSale = Class.extend({ } me.frm.set_value("mode_of_payment", values.mode_of_payment); - //me.frm.cscript.calculate_taxes_and_totals(); - - var paid_amount = flt((flt(values.paid_amount) - flt(values.change)) / me.frm.doc.conversion_rate, precision("paid_amount")); + var paid_amount = flt((flt(values.paid_amount) - flt(values.change)), precision("paid_amount")); me.frm.set_value("paid_amount", paid_amount); - + // specifying writeoff amount here itself, so as to avoid recursion issue - me.frm.set_value("write_off_amount", me.frm.doc.base_grand_total - paid_amount); + me.frm.set_value("write_off_amount", me.frm.doc.grand_total - paid_amount); me.frm.set_value("outstanding_amount", 0); me.frm.savesubmit(this); diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index 5404947e1d..6a8744a385 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -206,30 +206,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ } }, - calculate_outstanding_amount: function(update_paid_amount) { - // NOTE: - // paid_amount and write_off_amount is only for POS Invoice - // total_advance is only for non POS Invoice - if(this.frm.doc.doctype == "Sales Invoice" && this.frm.doc.docstatus==0 && !this.frm.doc.is_return) { - frappe.model.round_floats_in(this.frm.doc, ["base_grand_total", "total_advance", "write_off_amount", - "paid_amount"]); - var total_amount_to_pay = this.frm.doc.base_grand_total - this.frm.doc.write_off_amount - - this.frm.doc.total_advance; - if(this.frm.doc.is_pos) { - if(!this.frm.doc.paid_amount || update_paid_amount===undefined || update_paid_amount) { - this.frm.doc.paid_amount = flt(total_amount_to_pay); - this.frm.refresh_field("paid_amount"); - } - } else { - this.frm.doc.paid_amount = 0 - this.frm.refresh_field("paid_amount"); - } - - this.frm.set_value("outstanding_amount", flt(total_amount_to_pay - - this.frm.doc.paid_amount, precision("outstanding_amount"))); - } - }, - calculate_commission: function() { if(this.frm.fields_dict.commission_rate) { if(this.frm.doc.commission_rate > 100) {