diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index b9a7dae55f..ff58becb08 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -17,12 +17,13 @@ erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ if(!this.frm.doc.supplier && this.frm.doc.credit_to) { this.frm.set_df_property("credit_to", "print_hide", 0); } + } else { + this.frm.set_value("disable_rounded_total", frappe.sys_defaults.disable_rounded_total); } // formatter for material request item this.frm.set_indicator_formatter('item_code', function(doc) { return (doc.qty<=doc.received_qty) ? "green" : "orange" }) - }, refresh: function(doc) { diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json index 51a099e629..857f019bfb 100755 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.json @@ -2104,6 +2104,38 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.disable_rounded_total", + "fieldname": "base_rounded_total", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Rounded Total (Company Currency)", + "length": 0, + "no_copy": 1, + "options": "Company:company:default_currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -2229,6 +2261,38 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "eval:!doc.disable_rounded_total", + "fieldname": "rounded_total", + "fieldtype": "Currency", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Rounded Total", + "length": 0, + "no_copy": 1, + "options": "currency", + "permlevel": 0, + "precision": "", + "print_hide": 1, + "print_hide_if_no_value": 0, + "read_only": 1, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -2324,6 +2388,37 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "depends_on": "grand_total", + "fieldname": "disable_rounded_total", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Disable Rounded Total", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -3576,7 +3671,7 @@ "istable": 0, "max_attachments": 0, "menu_index": 0, - "modified": "2017-11-15 01:04:15.308603", + "modified": "2017-11-16 01:04:15.308603", "modified_by": "Administrator", "module": "Accounts", "name": "Purchase Invoice", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 78c5682ef8..626dd92827 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -77,8 +77,10 @@ class PurchaseInvoice(BuyingController): if not self.cash_bank_account and flt(self.paid_amount): frappe.throw(_("Cash or Bank Account is mandatory for making payment entry")) - if flt(self.paid_amount) + flt(self.write_off_amount) \ - - flt(self.grand_total) > 1/(10**(self.precision("base_grand_total") + 1)): + if (flt(self.paid_amount) + flt(self.write_off_amount) + - flt(self.get("rounded_total") or self.grand_total) + > 1/(10**(self.precision("base_grand_total") + 1))): + frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total""")) def create_remarks(self): @@ -359,9 +361,10 @@ class PurchaseInvoice(BuyingController): return gl_entries def make_supplier_gl_entry(self, gl_entries): - if self.grand_total: + grand_total = self.rounded_total or self.grand_total + if grand_total: # Didnot use base_grand_total to book rounding loss gle - grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate, + grand_total_in_company_currency = flt(grand_total * self.conversion_rate, self.precision("grand_total")) gl_entries.append( self.get_gl_dict({ @@ -371,7 +374,7 @@ class PurchaseInvoice(BuyingController): "against": self.against_expense_account, "credit": grand_total_in_company_currency, "credit_in_account_currency": grand_total_in_company_currency \ - if self.party_account_currency==self.company_currency else self.grand_total, + if self.party_account_currency==self.company_currency else grand_total, "against_voucher": self.return_against if cint(self.is_return) else self.name, "against_voucher_type": self.doctype, }, self.party_account_currency) diff --git a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py index 474329fc9a..baf016d596 100644 --- a/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/test_purchase_invoice.py @@ -35,7 +35,7 @@ class TestPurchaseInvoice(unittest.TestCase): dl = wrapper expected_gl_entries = { - "_Test Payable - _TC": [0, 1512.30], + "_Test Payable - _TC": [0, 1512.0], "_Test Account Cost for Goods Sold - _TC": [1250, 0], "_Test Account Shipping Charges - _TC": [100, 0], "_Test Account Excise Duty - _TC": [140, 0], @@ -44,6 +44,7 @@ class TestPurchaseInvoice(unittest.TestCase): "_Test Account CST - _TC": [29.88, 0], "_Test Account VAT - _TC": [156.25, 0], "_Test Account Discount - _TC": [0, 168.03], + "Round Off - _TC": [0, 0.3] } gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type = 'Purchase Invoice' and voucher_no = %s""", dl.name, as_dict=1) @@ -233,6 +234,7 @@ class TestPurchaseInvoice(unittest.TestCase): jv.submit() pi = frappe.copy_doc(test_records[0]) + pi.disable_rounded_total = 1 pi.append("advances", { "reference_type": "Journal Entry", "reference_name": jv.name, @@ -242,6 +244,13 @@ class TestPurchaseInvoice(unittest.TestCase): "remarks": jv.remark }) pi.insert() + + self.assertEqual(pi.outstanding_amount, 1212.30) + + pi.disable_rounded_total = 0 + pi.save() + self.assertEqual(pi.outstanding_amount, 1212.0) + pi.submit() pi.load_from_db() @@ -249,8 +258,6 @@ class TestPurchaseInvoice(unittest.TestCase): where reference_type='Purchase Invoice' and reference_name=%s and debit_in_account_currency=300""", pi.name)) - self.assertEqual(pi.outstanding_amount, 1212.30) - pi.cancel() self.assertFalse(frappe.db.sql("""select name from `tabJournal Entry Account` @@ -491,7 +498,7 @@ class TestPurchaseInvoice(unittest.TestCase): pi.load_from_db() #check outstanding after advance allocation - self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance)) + self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total - pi.total_advance)) #added to avoid Document has been modified exception jv = frappe.get_doc("Journal Entry", jv.name) @@ -499,7 +506,7 @@ class TestPurchaseInvoice(unittest.TestCase): pi.load_from_db() #check outstanding after advance cancellation - self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance)) + self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total + pi.total_advance)) def test_outstanding_amount_after_advance_payment_entry_cancelation(self): pe = frappe.get_doc({ @@ -521,7 +528,7 @@ class TestPurchaseInvoice(unittest.TestCase): }) pe.insert() pe.submit() - + pi = frappe.copy_doc(test_records[0]) pi.is_pos = 0 pi.append("advances", { @@ -534,19 +541,19 @@ class TestPurchaseInvoice(unittest.TestCase): }) pi.insert() pi.submit() - + pi.load_from_db() #check outstanding after advance allocation - self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total - pi.total_advance)) - + self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total - pi.total_advance)) + #added to avoid Document has been modified exception pe = frappe.get_doc("Payment Entry", pe.name) pe.cancel() - + pi.load_from_db() #check outstanding after advance cancellation - self.assertEqual(flt(pi.outstanding_amount), flt(pi.grand_total + pi.total_advance)) + self.assertEqual(flt(pi.outstanding_amount), flt(pi.rounded_total + pi.total_advance)) def unlink_payment_on_cancel_of_invoice(enable=1): accounts_settings = frappe.get_doc("Accounts Settings") diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index db9969d133..ee2b5542fb 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -632,9 +632,10 @@ class SalesInvoice(SellingController): return gl_entries def make_customer_gl_entry(self, gl_entries): - if self.grand_total: + grand_total = self.rounded_total or self.grand_total + if grand_total: # Didnot use base_grand_total to book rounding loss gle - grand_total_in_company_currency = flt(self.grand_total * self.conversion_rate, + grand_total_in_company_currency = flt(grand_total * self.conversion_rate, self.precision("grand_total")) gl_entries.append( @@ -645,7 +646,7 @@ class SalesInvoice(SellingController): "against": self.against_income_account, "debit": grand_total_in_company_currency, "debit_in_account_currency": grand_total_in_company_currency \ - if self.party_account_currency==self.company_currency else self.grand_total, + if self.party_account_currency==self.company_currency else grand_total, "against_voucher": self.return_against if cint(self.is_return) else self.name, "against_voucher_type": self.doctype }, self.party_account_currency) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 50d2ce810b..12b556b5b4 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -546,7 +546,7 @@ class TestSalesInvoice(unittest.TestCase): def test_outstanding(self): w = self.make() - self.assertEquals(w.outstanding_amount, w.base_grand_total) + self.assertEquals(w.outstanding_amount, w.base_rounded_total) def test_payment(self): w = self.make() @@ -560,7 +560,7 @@ class TestSalesInvoice(unittest.TestCase): jv.insert() jv.submit() - self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 161.8) + self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 162.0) link_data = get_dynamic_link_map().get('Sales Invoice', []) link_doctypes = [d.parent for d in link_data] @@ -569,7 +569,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertTrue(link_doctypes.index('GL Entry') > link_doctypes.index('Journal Entry Account')) jv.cancel() - self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 561.8) + self.assertEquals(frappe.db.get_value("Sales Invoice", w.name, "outstanding_amount"), 562.0) def test_sales_invoice_gl_entry_without_perpetual_inventory(self): si = frappe.copy_doc(test_records[1]) @@ -848,7 +848,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertTrue(frappe.db.sql("""select name from `tabJournal Entry Account` where reference_name=%s and credit_in_account_currency=300""", si.name)) - self.assertEqual(si.outstanding_amount, 261.8) + self.assertEqual(si.outstanding_amount, 262.0) si.cancel() @@ -1152,7 +1152,8 @@ class TestSalesInvoice(unittest.TestCase): si.load_from_db() #check outstanding after advance allocation - self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount"))) + self.assertEqual(flt(si.outstanding_amount), + flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount"))) #added to avoid Document has been modified exception jv = frappe.get_doc("Journal Entry", jv.name) @@ -1160,7 +1161,8 @@ class TestSalesInvoice(unittest.TestCase): si.load_from_db() #check outstanding after advance cancellation - self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount"))) + self.assertEqual(flt(si.outstanding_amount), + flt(si.rounded_total + si.total_advance, si.precision("outstanding_amount"))) def test_outstanding_amount_after_advance_payment_entry_cancelation(self): pe = frappe.get_doc({ @@ -1199,7 +1201,8 @@ class TestSalesInvoice(unittest.TestCase): si.load_from_db() #check outstanding after advance allocation - self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total - si.total_advance, si.precision("outstanding_amount"))) + self.assertEqual(flt(si.outstanding_amount), + flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount"))) #added to avoid Document has been modified exception pe = frappe.get_doc("Payment Entry", pe.name) @@ -1207,7 +1210,8 @@ class TestSalesInvoice(unittest.TestCase): si.load_from_db() #check outstanding after advance cancellation - self.assertEqual(flt(si.outstanding_amount), flt(si.grand_total + si.total_advance, si.precision("outstanding_amount"))) + self.assertEqual(flt(si.outstanding_amount), + flt(si.rounded_total + si.total_advance, si.precision("outstanding_amount"))) def test_multiple_uom_in_selling(self): frappe.db.sql("""delete from `tabItem Price` diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 74a90004c4..429d6eb425 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -66,9 +66,9 @@ class AccountsController(TransactionBase): if cint(is_paid) == 1: if flt(self.paid_amount) == 0 and flt(self.outstanding_amount) > 0: if self.cash_bank_account: - self.paid_amount = flt(flt(self.grand_total) - flt(self.write_off_amount), - self.precision("paid_amount")) - self.base_paid_amount = flt(self.paid_amount * self.conversion_rate, self.precision("base_paid_amount")) + self.paid_amount = flt(flt(self.outstanding_amount), self.precision("paid_amount")) + self.base_paid_amount = flt(self.paid_amount * self.conversion_rate, + self.precision("base_paid_amount")) else: # show message that the amount is not paid self.paid_amount = 0 @@ -598,6 +598,12 @@ class AccountsController(TransactionBase): for item in duplicate_list: self.remove(item) + def is_rounded_total_disabled(self): + if self.meta.get_field("disable_rounded_total"): + return self.disable_rounded_total + else: + return frappe.db.get_single_value("Global Defaults", "disable_rounded_total") + @frappe.whitelist() def get_tax_rate(account_head): return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index c1028a598d..0e15eee521 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -28,8 +28,7 @@ class SellingController(StockController): super(SellingController, self).onload() if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"): for item in self.get("items"): - item.update(get_bin_details(item.item_code, - item.warehouse)) + item.update(get_bin_details(item.item_code, item.warehouse)) def validate(self): super(SellingController, self).validate() @@ -114,14 +113,15 @@ class SellingController(StockController): def set_total_in_words(self): from frappe.utils import money_in_words - disable_rounded_total = cint(frappe.db.get_value("Global Defaults", None, "disable_rounded_total")) if self.meta.get_field("base_in_words"): - self.base_in_words = money_in_words(disable_rounded_total and - abs(self.base_grand_total) or abs(self.base_rounded_total), self.company_currency) + base_amount = abs(self.base_grand_total + if self.is_rounded_total_disabled() else self.base_rounded_total) + self.base_in_words = money_in_words(base_amount, self.company_currency) + if self.meta.get_field("in_words"): - self.in_words = money_in_words(disable_rounded_total and - abs(self.grand_total) or abs(self.rounded_total), self.currency) + amount = abs(self.grand_total if self.is_rounded_total_disabled() else self.rounded_total) + self.in_words = money_in_words(amount, self.currency) def calculate_commission(self): if self.meta.get_field("commission_rate"): diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index e9672df0df..2b2191c0d9 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -328,14 +328,18 @@ class calculate_taxes_and_totals(object): self.set_rounded_total() def set_rounded_total(self): - if frappe.db.get_single_value("Global Defaults", "disable_rounded_total"): - self.doc.rounded_total = self.doc.base_rounded_total = 0 - return - if self.doc.meta.get_field("rounded_total"): + if self.doc.is_rounded_total_disabled(): + self.doc.rounded_total = self.doc.base_rounded_total = 0 + return + self.doc.rounded_total = round_based_on_smallest_currency_fraction(self.doc.grand_total, self.doc.currency, self.doc.precision("rounded_total")) + #if print_in_rate is set, we would have already calculated rounding adjustment + self.doc.rounding_adjustment += flt(self.doc.rounded_total - self.doc.grand_total, + self.doc.precision("rounding_adjustment")) + if self.doc.meta.get_field("base_rounded_total"): company_currency = erpnext.get_company_currency(self.doc.company) @@ -343,6 +347,9 @@ class calculate_taxes_and_totals(object): round_based_on_smallest_currency_fraction(self.doc.base_grand_total, company_currency, self.doc.precision("base_rounded_total")) + self.doc.base_rounding_adjustment += flt(self.doc.base_rounded_total - self.doc.base_grand_total, + self.doc.precision("base_rounding_adjustment")) + def _cleanup(self): for tax in self.doc.get("taxes"): tax.item_wise_tax_detail = json.dumps(tax.item_wise_tax_detail, separators=(',', ':')) @@ -404,7 +411,8 @@ class calculate_taxes_and_totals(object): actual_tax_amount = flt(actual_taxes_dict.get(tax.row_id, 0)) * flt(tax.rate) / 100 actual_taxes_dict.setdefault(tax.idx, actual_tax_amount) - return flt(self.doc.grand_total - sum(actual_taxes_dict.values()), self.doc.precision("grand_total")) + return flt(self.doc.grand_total - sum(actual_taxes_dict.values()), + self.doc.precision("grand_total")) def calculate_total_advance(self): @@ -442,30 +450,31 @@ class calculate_taxes_and_totals(object): self.doc.round_floats_in(self.doc, ["grand_total", "total_advance", "write_off_amount"]) self._set_in_company_currency(self.doc, ['write_off_amount']) - if self.doc.party_account_currency == self.doc.currency: - total_amount_to_pay = flt(self.doc.grand_total - self.doc.total_advance - - flt(self.doc.write_off_amount), self.doc.precision("grand_total")) - else: - total_amount_to_pay = flt(flt(self.doc.grand_total * - self.doc.conversion_rate, self.doc.precision("grand_total")) - self.doc.total_advance - - flt(self.doc.base_write_off_amount), self.doc.precision("grand_total")) + if self.doc.doctype in ["Sales Invoice", "Purchase Invoice"]: + grand_total = self.doc.rounded_total or self.doc.grand_total + if self.doc.party_account_currency == self.doc.currency: + total_amount_to_pay = flt(grand_total - self.doc.total_advance + - flt(self.doc.write_off_amount), self.doc.precision("grand_total")) + else: + total_amount_to_pay = flt(flt(grand_total * + self.doc.conversion_rate, self.doc.precision("grand_total")) - self.doc.total_advance + - flt(self.doc.base_write_off_amount), self.doc.precision("grand_total")) - if self.doc.doctype == "Sales Invoice": self.doc.round_floats_in(self.doc, ["paid_amount"]) - self.calculate_write_off_amount() - self.calculate_change_amount() - + change_amount = 0 + + if self.doc.doctype == "Sales Invoice": + self.calculate_write_off_amount() + self.calculate_change_amount() + change_amount = self.doc.change_amount \ + if self.doc.party_account_currency == self.doc.currency else self.doc.base_change_amount + paid_amount = self.doc.paid_amount \ if self.doc.party_account_currency == self.doc.currency else self.doc.base_paid_amount - - change_amount = self.doc.change_amount \ - if self.doc.party_account_currency == self.doc.currency else self.doc.base_change_amount - self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + - flt(change_amount), self.doc.precision("outstanding_amount")) - elif self.doc.doctype == "Purchase Invoice": - self.doc.outstanding_amount = flt(total_amount_to_pay, self.doc.precision("outstanding_amount")) + self.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + flt(change_amount), + self.doc.precision("outstanding_amount")) def calculate_paid_amount(self): paid_amount = base_paid_amount = 0.0 @@ -485,7 +494,9 @@ class calculate_taxes_and_totals(object): def calculate_change_amount(self): self.doc.change_amount = 0.0 self.doc.base_change_amount = 0.0 - if self.doc.paid_amount > self.doc.grand_total and not self.doc.is_return \ + + if self.doc.doctype == "Sales Invoice" \ + and self.doc.paid_amount > self.doc.grand_total and not self.doc.is_return \ and any([d.type == "Cash" for d in self.doc.payments]): self.doc.change_amount = flt(self.doc.paid_amount - self.doc.grand_total + @@ -496,8 +507,8 @@ class calculate_taxes_and_totals(object): def calculate_write_off_amount(self): if flt(self.doc.change_amount) > 0: - self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount + self.doc.change_amount, - self.doc.precision("write_off_amount")) + self.doc.write_off_amount = flt(self.doc.grand_total - self.doc.paid_amount + + self.doc.change_amount, self.doc.precision("write_off_amount")) self.doc.base_write_off_amount = flt(self.doc.write_off_amount * self.doc.conversion_rate, self.doc.precision("base_write_off_amount")) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 05c323bdc6..afdc87392a 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -422,13 +422,27 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ frappe.model.round_floats_in(this.frm.doc, ["grand_total", "base_grand_total"]); // rounded totals - this.set_rounded_total() + this.set_rounded_total(); }, set_rounded_total: function() { + var disable_rounded_total = 0; + if(frappe.meta.get_docfield(this.frm.doc.doctype, "disable_rounded_total", this.frm.doc.name)) { + disable_rounded_total = this.frm.doc.disable_rounded_total; + } else if (frappe.sys_defaults.disable_rounded_total) { + disable_rounded_total = frappe.sys_defaults.disable_rounded_total; + } + if(disable_rounded_total) { + this.frm.doc.rounded_total = 0; + this.frm.doc.base_rounded_total = 0; + return; + } + if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) { this.frm.doc.rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.grand_total, this.frm.doc.currency, precision("rounded_total")); + this.frm.doc.rounding_adjustment += flt(this.frm.doc.rounded_total - this.frm.doc.grand_total, + precision("rounding_adjustment")); } if(frappe.meta.get_docfield(this.frm.doc.doctype, "base_rounded_total", this.frm.doc.name)) { var company_currency = this.get_company_currency(); @@ -436,6 +450,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.doc.base_rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.base_grand_total, company_currency, precision("base_rounded_total")); + + this.frm.doc.base_rounding_adjustment += flt(this.frm.doc.base_rounded_total - + this.frm.doc.base_grand_total, precision("rounding_adjustment")); } }, @@ -560,20 +577,22 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ 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"]); - if(this.frm.doc.party_account_currency == this.frm.doc.currency) { - 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")); - } else { - var total_amount_to_pay = flt( - (flt(this.frm.doc.grand_total*this.frm.doc.conversion_rate, precision("grand_total")) - - this.frm.doc.total_advance - this.frm.doc.base_write_off_amount), - precision("base_grand_total") - ); - } - if(this.frm.doc.doctype == "Sales Invoice" || this.frm.doc.doctype == "Purchase Invoice") { + if(in_list(["Sales Invoice", "Purchase Invoice"], this.frm.doc.doctype)) { + var grand_total = this.frm.doc.rounded_total || this.frm.doc.grand_total; + + if(this.frm.doc.party_account_currency == this.frm.doc.currency) { + var total_amount_to_pay = flt((grand_total - this.frm.doc.total_advance + - this.frm.doc.write_off_amount), precision("grand_total")); + } else { + var total_amount_to_pay = flt( + (flt(grand_total*this.frm.doc.conversion_rate, precision("grand_total")) + - this.frm.doc.total_advance - this.frm.doc.base_write_off_amount), + precision("base_grand_total") + ); + } + frappe.model.round_floats_in(this.frm.doc, ["paid_amount"]); - this.set_in_company_currency(this.frm.doc, ["paid_amount"]); if(this.frm.refresh_field){ @@ -581,11 +600,10 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.refresh_field("base_paid_amount"); } - if(this.frm.doc.doctype == "Sales Invoice"){ + if(this.frm.doc.doctype == "Sales Invoice") { this.set_default_payment(total_amount_to_pay, update_paid_amount); this.calculate_paid_amount(); } - this.calculate_change_amount(); var paid_amount = (this.frm.doc.party_account_currency == this.frm.doc.currency) ? @@ -593,9 +611,6 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.doc.outstanding_amount = flt(total_amount_to_pay - flt(paid_amount) + flt(this.frm.doc.change_amount * this.frm.doc.conversion_rate), precision("outstanding_amount")); - - } else if(this.frm.doc.doctype == "Purchase Invoice") { - this.frm.doc.outstanding_amount = flt(total_amount_to_pay, precision("outstanding_amount")); } }, @@ -636,7 +651,9 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ calculate_change_amount: function(){ this.frm.doc.change_amount = 0.0; this.frm.doc.base_change_amount = 0.0; - if(this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) { + if(this.frm.doc.doctype == "Sales Invoice" + && this.frm.doc.paid_amount > this.frm.doc.grand_total && !this.frm.doc.is_return) { + var payment_types = $.map(this.frm.doc.payments, function(d) { return d.type; }); if (in_list(payment_types, 'Cash')) { this.frm.doc.change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total + diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py index 9c6eb82def..a39e246c68 100644 --- a/erpnext/setup/doctype/global_defaults/global_defaults.py +++ b/erpnext/setup/doctype/global_defaults/global_defaults.py @@ -57,7 +57,8 @@ class GlobalDefaults(Document): self.disable_rounded_total = cint(self.disable_rounded_total) # Make property setters to hide rounded total fields - for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note"): + for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note", + "Supplier Quotation", "Purchase Order"): make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check") make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check") @@ -69,6 +70,6 @@ class GlobalDefaults(Document): # Make property setters to hide in words fields for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note", - "Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"): + "Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"): make_property_setter(doctype, "in_words", "hidden", self.disable_in_words, "Check") make_property_setter(doctype, "in_words", "print_hide", self.disable_in_words, "Check")