From 613d081a60b33262073dd050571e24dc1b423f4f Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 23 Feb 2015 11:58:15 +0530 Subject: [PATCH] Validate taxes and charges input, commonified --- .../purchase_invoice/purchase_invoice.js | 1 - .../purchase_taxes_and_charges_master.py | 7 +- .../doctype/sales_invoice/sales_invoice.js | 1 - .../sales_taxes_and_charges_master.js | 2 - .../sales_taxes_and_charges_master.py | 7 +- .../purchase_common/purchase_common.js | 101 +-------- .../doctype/purchase_order/purchase_order.js | 1 - .../supplier_quotation/supplier_quotation.js | 1 - erpnext/controllers/accounts_controller.py | 33 ++- erpnext/controllers/taxes_and_totals.py | 36 +--- erpnext/public/js/controllers/accounts.js | 75 +++++-- .../public/js/controllers/taxes_and_totals.js | 7 +- erpnext/public/js/controllers/transaction.js | 194 +++++++++++------- .../selling/doctype/quotation/quotation.js | 1 - .../doctype/sales_order/sales_order.js | 1 - erpnext/selling/sales_common.js | 112 +--------- .../doctype/delivery_note/delivery_note.js | 1 - .../purchase_receipt/purchase_receipt.js | 1 - 18 files changed, 242 insertions(+), 340 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js index 6f16dcde46..8040c41ee5 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js @@ -3,7 +3,6 @@ frappe.provide("erpnext.accounts"); {% include 'buying/doctype/purchase_common/purchase_common.js' %}; -{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} erpnext.accounts.PurchaseInvoice = erpnext.buying.BuyingController.extend({ onload: function() { diff --git a/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py b/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py index e93c57263f..b004a2e148 100644 --- a/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py +++ b/erpnext/accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.py @@ -2,8 +2,11 @@ # License: GNU General Public License v3. See license.txt from __future__ import unicode_literals -import frappe from frappe.model.document import Document +from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax class PurchaseTaxesandChargesMaster(Document): - pass + def validate(self): + for tax in self.get("taxes"): + validate_taxes_and_charges(tax) + validate_inclusive_tax(tax, self) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js index bbc0dd21f1..4670303e2e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.js +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.js @@ -5,7 +5,6 @@ cur_frm.pformat.print_heading = 'Invoice'; {% include 'selling/sales_common.js' %}; -{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} frappe.provide("erpnext.accounts"); erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.extend({ diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js index 58a80a8314..b5dc38f803 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js @@ -1,8 +1,6 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt -cur_frm.cscript.tax_table = "Sales Taxes and Charges"; - {% include "public/js/controllers/accounts.js" %} cur_frm.cscript.onload = function(doc, cdt, cdn) { diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py index 6ab5ab2745..4317f2ab8c 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py +++ b/erpnext/accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint from frappe.model.document import Document +from erpnext.controllers.accounts_controller import validate_taxes_and_charges, validate_inclusive_tax class SalesTaxesandChargesMaster(Document): def validate(self): @@ -15,3 +15,8 @@ class SalesTaxesandChargesMaster(Document): # at least one territory self.validate_table_has_rows("territories") + + for tax in self.get("taxes"): + validate_taxes_and_charges(tax) + validate_inclusive_tax(tax, self) + diff --git a/erpnext/buying/doctype/purchase_common/purchase_common.js b/erpnext/buying/doctype/purchase_common/purchase_common.js index f98dab783d..dc3b3a32be 100644 --- a/erpnext/buying/doctype/purchase_common/purchase_common.js +++ b/erpnext/buying/doctype/purchase_common/purchase_common.js @@ -1,11 +1,12 @@ // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt +cur_frm.cscript.tax_table = "Purchase Taxes and Charges"; +{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} + frappe.provide("erpnext.buying"); frappe.require("assets/erpnext/js/controllers/transaction.js"); -{% include "public/js/controllers/accounts.js" %}; - cur_frm.email_field = "contact_email"; erpnext.buying.BuyingController = erpnext.TransactionController.extend({ @@ -166,97 +167,6 @@ erpnext.buying.BuyingController = erpnext.TransactionController.extend({ this.frm.doc.outstanding_amount = flt(this.frm.doc.total_amount_to_pay - this.frm.doc.total_advance, precision("outstanding_amount")); } - }, - - change_form_labels: function(company_currency) { - var me = this; - var field_label_map = {}; - - var setup_field_label_map = function(fields_list, currency) { - $.each(fields_list, function(i, fname) { - var docfield = frappe.meta.docfield_map[me.frm.doc.doctype][fname]; - if(docfield) { - var label = __(docfield.label || "").replace(/\([^\)]*\)/g, ""); - field_label_map[fname] = label.trim() + " (" + currency + ")"; - } - }); - }; - - - setup_field_label_map(["base_net_total", "base_total_taxes_and_charges", "base_grand_total", "base_in_words", - "base_taxes_and_charges_added", "base_taxes_and_charges_deducted", - "outstanding_amount", "total_advance", "total_amount_to_pay", "base_rounded_total"], - company_currency); - - setup_field_label_map(["net_total", "grand_total", "in_words", - "taxes_and_charges_added", "taxes_and_charges_deducted"], this.frm.doc.currency); - - cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency - + " = [?] " + company_currency); - - if(this.frm.doc.price_list_currency && this.frm.doc.price_list_currency!=company_currency) { - cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency - + " = [?] " + company_currency); - } - - // toggle fields - this.frm.toggle_display(["conversion_rate", "base_net_total", "base_grand_total", - "base_in_words", "base_taxes_and_charges_added", "base_taxes_and_charges_deducted"], - this.frm.doc.currency !== company_currency); - - this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"], - this.frm.doc.price_list_currency !== company_currency); - - // set labels - $.each(field_label_map, function(fname, label) { - me.frm.fields_dict[fname].set_label(label); - }); - - }, - - change_grid_labels: function(company_currency) { - var me = this; - var field_label_map = {}; - - var setup_field_label_map = function(fields_list, currency, parentfield) { - var grid_doctype = me.frm.fields_dict[parentfield].grid.doctype; - $.each(fields_list, function(i, fname) { - var docfield = frappe.meta.docfield_map[grid_doctype][fname]; - if(docfield) { - var label = __(docfield.label || "").replace(/\([^\)]*\)/g, ""); - field_label_map[grid_doctype + "-" + fname] = - label.trim() + " (" + currency + ")"; - } - }); - }; - - setup_field_label_map(["base_rate", "base_price_list_rate", "base_amount", "base_rate"], - company_currency, "items"); - - setup_field_label_map(["rate", "price_list_rate", "amount"], this.frm.doc.currency, "items"); - - if(this.frm.fields_dict["taxes"]) { - setup_field_label_map(["tax_amount", "total"], company_currency, "taxes"); - } - - if(this.frm.fields_dict["advances"]) { - setup_field_label_map(["advance_amount", "allocated_amount"], company_currency, - "advances"); - } - - // toggle columns - var item_grid = this.frm.fields_dict["items"].grid; - var fieldnames = $.map(["base_rate", "base_price_list_rate", "base_amount", "base_rate"], function(fname) { - return frappe.meta.get_docfield(item_grid.doctype, fname, me.frm.docname) ? fname : null; - }); - - item_grid.set_column_disp(fieldnames, this.frm.doc.currency != company_currency); - - // set labels - var $wrapper = $(this.frm.wrapper); - $.each(field_label_map, function(fname, label) { - $wrapper.find('[data-grid-fieldname="'+fname+'"]').text(label); - }); } }); cur_frm.add_fetch('project_name', 'cost_center', 'cost_center'); @@ -279,8 +189,3 @@ erpnext.buying.get_default_bom = function(frm) { } }); } - - -frappe.ui.form.on("Purchase Taxes and Charges", "rate", function(frm, cdt, cdn) { - cur_frm.cscript.calculate_taxes_and_totals(); -}) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index b1eee0ed99..27ea0d4dd2 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -4,7 +4,6 @@ frappe.provide("erpnext.buying"); {% include 'buying/doctype/purchase_common/purchase_common.js' %}; -{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend({ refresh: function(doc, cdt, cdn) { diff --git a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js index 9c2bbed2f8..ecd9185c0e 100644 --- a/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js +++ b/erpnext/buying/doctype/supplier_quotation/supplier_quotation.js @@ -3,7 +3,6 @@ // attach required files {% include 'buying/doctype/purchase_common/purchase_common.js' %}; -{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} erpnext.buying.SupplierQuotationController = erpnext.buying.BuyingController.extend({ refresh: function() { diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index c0a63cd9e9..1765fbf7f2 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe from frappe import _, throw -from frappe.utils import today, flt +from frappe.utils import today, flt, cint from erpnext.setup.utils import get_company_currency, get_exchange_rate from erpnext.accounts.utils import get_fiscal_year, validate_fiscal_year from erpnext.utilities.transaction_base import TransactionBase @@ -357,3 +357,34 @@ def validate_conversion_rate(currency, conversion_rate, conversion_rate_label, c if not conversion_rate: throw(_("{0} is mandatory. Maybe Currency Exchange record is not created for {1} to {2}.").format( conversion_rate_label, currency, company_currency)) + +def validate_taxes_and_charges(tax): + if not tax.charge_type and (tax.row_id or tax.rate or tax.tax_amount): + frappe.throw(_("Please select Charge Type first")) + elif tax.charge_type in ['Actual', 'On Net Total'] and tax.row_id: + frappe.throw(_("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'")) + elif tax.charge_type in ['On Previous Row Amount', 'On Previous Row Total'] and tax.row_id: + if cint(tax.idx) == 1: + frappe.throw(_("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row")) + elif not tax.row_id: + frappe.throw(_("Please specify a valid Row ID for row {0} in table {1}".format(tax.idx, _(tax.doctype)))) + elif tax.row_id and cint(tax.row_id) >= cint(tax.idx): + frappe.throw(_("Cannot refer row number greater than or equal to current row number for this Charge type")) + +def validate_inclusive_tax(tax, doc): + def _on_previous_row_error(row_range): + throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx, + row_range)) + + if cint(getattr(tax, "included_in_print_rate", None)): + if tax.charge_type == "Actual": + # inclusive tax cannot be of type Actual + throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate").format(tax.idx)) + elif tax.charge_type == "On Previous Row Amount" and \ + not cint(doc.get("taxes")[cint(tax.row_id) - 1].included_in_print_rate): + # referred row should also be inclusive + _on_previous_row_error(tax.row_id) + elif tax.charge_type == "On Previous Row Total" and \ + not all([cint(t.included_in_print_rate) for t in doc.get("taxes")[:cint(tax.row_id) - 1]]): + # all rows about the reffered tax should be inclusive + _on_previous_row_error("1 - %d" % (tax.row_id,)) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 0b32d47cd5..eb397f8c55 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -3,10 +3,10 @@ from __future__ import unicode_literals import json -from frappe import _, throw from frappe.utils import cint, flt, rounded from erpnext.setup.utils import get_company_currency -from erpnext.controllers.accounts_controller import validate_conversion_rate +from erpnext.controllers.accounts_controller import validate_conversion_rate, \ + validate_taxes_and_charges, validate_inclusive_tax class calculate_taxes_and_totals(object): def __init__(self, doc): @@ -71,6 +71,9 @@ class calculate_taxes_and_totals(object): def initialize_taxes(self): for tax in self.doc.get("taxes"): + validate_taxes_and_charges(tax) + validate_inclusive_tax(tax, self.doc) + tax.item_wise_tax_detail = {} tax_fields = ["total", "tax_amount_after_discount_amount", "tax_amount_for_current_item", "grand_total_for_current_item", @@ -83,37 +86,8 @@ class calculate_taxes_and_totals(object): for fieldname in tax_fields: tax.set(fieldname, 0.0) - self.validate_on_previous_row(tax) - self.validate_inclusive_tax(tax) self.doc.round_floats_in(tax) - def validate_on_previous_row(self, tax): - """ - validate if a valid row id is mentioned in case of - On Previous Row Amount and On Previous Row Total - """ - if tax.charge_type in ["On Previous Row Amount", "On Previous Row Total"] and \ - (not tax.row_id or cint(tax.row_id) >= tax.idx): - throw(_("Please specify a valid Row ID for {0} in row {1}").format(_(tax.doctype), tax.idx)) - - def validate_inclusive_tax(self, tax): - def _on_previous_row_error(row_range): - throw(_("To include tax in row {0} in Item rate, taxes in rows {1} must also be included").format(tax.idx, - row_range)) - - if cint(getattr(tax, "included_in_print_rate", None)): - if tax.charge_type == "Actual": - # inclusive tax cannot be of type Actual - throw(_("Charge of type 'Actual' in row {0} cannot be included in Item Rate").format(tax.idx)) - elif tax.charge_type == "On Previous Row Amount" and \ - not cint(self.doc.get("taxes")[cint(tax.row_id) - 1].included_in_print_rate): - # referred row should also be inclusive - _on_previous_row_error(tax.row_id) - elif tax.charge_type == "On Previous Row Total" and \ - not all([cint(t.included_in_print_rate) for t in self.doc.get("taxes")[:cint(tax.row_id) - 1]]): - # all rows about the reffered tax should be inclusive - _on_previous_row_error("1 - %d" % (tax.row_id,)) - def determine_exclusive_rate(self): if not any((cint(tax.included_in_print_rate) for tax in self.doc.get("taxes"))) or \ self.doc.doctype not in ["Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]: diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js index 8911832016..d0f27bcedf 100644 --- a/erpnext/public/js/controllers/accounts.js +++ b/erpnext/public/js/controllers/accounts.js @@ -19,45 +19,94 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) { } } - -var validate_taxes_and_charges = function(cdt, cdn) { +cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) { var d = locals[cdt][cdn]; + var msg = ""; if(!d.charge_type && (d.row_id || d.rate || d.tax_amount)) { - msgprint(__("Please select Charge Type first")); + msg = __("Please select Charge Type first"); d.row_id = ""; d.rate = d.tax_amount = 0.0; } else if((d.charge_type == 'Actual' || d.charge_type == 'On Net Total') && d.row_id) { - msgprint(__("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'")); + msg = __("Can refer row only if the charge type is 'On Previous Row Amount' or 'Previous Row Total'"); d.row_id = ""; } else if((d.charge_type == 'On Previous Row Amount' || d.charge_type == 'On Previous Row Total') && d.row_id) { if (d.idx == 1) { - msgprint(__("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row")); + msg = __("Cannot select charge type as 'On Previous Row Amount' or 'On Previous Row Total' for first row"); d.charge_type = ''; - } else if (d.row_i && d.row_id >= d.idx) { - msgprint(__("Cannot refer row number greater than or equal to current row number for this Charge type")); + } else if (!d.row_id) { + msg = __("Please specify a valid Row ID for row {0} in table {1}", [d.idx, __(d.doctype)]); + d.row_id = ""; + } else if(d.row_id && d.row_id >= d.idx) { + msg = __("Cannot refer row number greater than or equal to current row number for this Charge type"); d.row_id = ""; } } - validated = false; - refresh_field('row_id', d.name, 'taxes'); + if(msg) { + validated = false; + refresh_field("taxes"); + frappe.throw(msg); + } + +} + +cur_frm.cscript.validate_inclusive_tax = function(tax) { + var actual_type_error = function() { + var msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx]) + frappe.throw(msg); + }; + + var on_previous_row_error = function(row_range) { + var msg = __("For row {0} in {1}. To include {2} in Item rate, rows {3} must also be included", + [tax.idx, __(tax.doctype), tax.charge_type, row_range]) + frappe.throw(msg); + }; + + if(cint(tax.included_in_print_rate)) { + if(tax.charge_type == "Actual") { + // inclusive tax cannot be of type Actual + actual_type_error(); + } else if(tax.charge_type == "On Previous Row Amount" && + !cint(this.frm.doc["taxes"][tax.row_id - 1].included_in_print_rate)) { + // referred row should also be an inclusive tax + on_previous_row_error(tax.row_id); + } else if(tax.charge_type == "On Previous Row Total") { + var taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id), + function(t) { return cint(t.included_in_print_rate) ? null : t; }); + if(taxes_not_included.length > 0) { + // all rows above this tax should be inclusive + on_previous_row_error(tax.row_id == 1 ? "1" : "1 - " + tax.row_id); + } + } + } } frappe.ui.form.on(cur_frm.cscript.tax_table, "row_id", function(frm, cdt, cdn) { - validate_taxes_and_charges(cdt, cdn); + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); }); frappe.ui.form.on(cur_frm.cscript.tax_table, "rate", function(frm, cdt, cdn) { - validate_taxes_and_charges(cdt, cdn); + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); }); frappe.ui.form.on(cur_frm.cscript.tax_table, "tax_amount", function(frm, cdt, cdn) { - validate_taxes_and_charges(cdt, cdn); + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); }); frappe.ui.form.on(cur_frm.cscript.tax_table, "charge_type", function(frm, cdt, cdn) { - validate_taxes_and_charges(cdt, cdn); + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); }); +frappe.ui.form.on(cur_frm.cscript.tax_table, "included_in_print_rate", function(frm, cdt, cdn) { + var tax = frappe.get_doc(cdt, cdn); + try { + cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); + cur_frm.cscript.validate_inclusive_tax(tax); + } catch(e) { + tax.included_in_print_rate = 0; + refresh_field("included_in_print_rate", tax.name, tax.parentfield); + throw e; + } +}); cur_frm.set_query("account_head", "taxes", function(doc) { if(cur_frm.cscript.tax_table == "Sales Taxes and Charges") { diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 4018742c3d..466839869a 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -94,7 +94,7 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0 }); - me.validate_on_previous_row(tax); + cur_frm.cscript.validate_taxes_and_charges(tax.doctype, tax.name); me.validate_inclusive_tax(tax); frappe.model.round_floats_in(tax); }); @@ -129,10 +129,7 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ }); if(cumulated_tax_fraction && !me.discount_amount_applied) { - item.net_amount = flt( - (item.amount * me.frm.doc.conversion_rate) / (1 + cumulated_tax_fraction), - precision("net_amount", item)); - + item.net_amount = flt(item.amount / (1 + cumulated_tax_fraction), precision("net_amount", item)); item.net_rate = flt(item.net_amount / item.qty, precision("net_rate", item)); me.set_in_company_currency(item, ["net_rate", "net_amount"]); diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 519b04cb09..88b4ac4956 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -274,22 +274,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ this.apply_pricing_rule(frappe.get_doc(cdt, cdn), true); }, - tax_amount: function(doc, cdt, cdn) { - this.calculate_taxes_and_totals(); - }, - - row_id: function(doc, cdt, cdn) { - var tax = frappe.get_doc(cdt, cdn); - try { - this.validate_on_previous_row(tax); - this.calculate_taxes_and_totals(); - } catch(e) { - tax.row_id = null; - refresh_field("row_id", tax.name, tax.parentfield); - throw e; - } - }, - set_dynamic_labels: function() { // What TODO? should we make price list system non-mandatory? this.frm.toggle_reqd("plc_conversion_rate", @@ -301,6 +285,114 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ this.frm.refresh_fields(); }, + + change_form_labels: function(company_currency) { + var me = this; + var field_label_map = {}; + + var setup_field_label_map = function(fields_list, currency) { + $.each(fields_list, function(i, fname) { + var docfield = frappe.meta.docfield_map[me.frm.doc.doctype][fname]; + if(docfield) { + var label = __(docfield.label || "").replace(/\([^\)]*\)/g, ""); + field_label_map[fname] = label.trim() + " (" + currency + ")"; + } + }); + }; + 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); + + 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); + + cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency + + " = [?] " + company_currency) + + if(this.frm.doc.price_list_currency && this.frm.doc.price_list_currency!=company_currency) { + cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency + + " = [?] " + company_currency) + } + + // 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"], + this.frm.doc.currency != company_currency); + + this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"], + this.frm.doc.price_list_currency != company_currency); + + // set labels + $.each(field_label_map, function(fname, label) { + me.frm.fields_dict[fname].set_label(label); + }); + }, + + change_grid_labels: function(company_currency) { + var me = this; + var field_label_map = {}; + + var setup_field_label_map = function(fields_list, currency, parentfield) { + var grid_doctype = me.frm.fields_dict[parentfield].grid.doctype; + $.each(fields_list, function(i, fname) { + var docfield = frappe.meta.docfield_map[grid_doctype][fname]; + if(docfield) { + var label = __(docfield.label || "").replace(/\([^\)]*\)/g, ""); + field_label_map[grid_doctype + "-" + fname] = + label.trim() + " (" + currency + ")"; + } + }); + } + + setup_field_label_map(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount"], + company_currency, "items"); + + setup_field_label_map(["rate", "net_rate", "price_list_rate", "amount", "net_amount"], + this.frm.doc.currency, "items"); + + if(this.frm.fields_dict["taxes"]) { + setup_field_label_map(["tax_amount", "total", "tax_amount_after_discount"], this.frm.doc.currency, "taxes"); + + setup_field_label_map(["base_tax_amount", "base_total", "base_tax_amount_after_discount"], company_currency, "taxes"); + } + + if(this.frm.fields_dict["advances"]) { + setup_field_label_map(["advance_amount", "allocated_amount"], company_currency, "advances"); + } + + // toggle columns + var item_grid = this.frm.fields_dict["items"].grid; + $.each(["base_rate", "base_price_list_rate", "base_amount"], function(i, fname) { + if(frappe.meta.get_docfield(item_grid.doctype, fname)) + item_grid.set_column_disp(fname, me.frm.doc.currency != company_currency); + }); + + var show = (cint(cur_frm.doc.discount_amount)) || + ((cur_frm.doc.taxes || []).filter(function(d) {return d.included_in_print_rate===1}).length); + + $.each(["net_rate", "net_amount"], function(i, fname) { + if(frappe.meta.get_docfield(item_grid.doctype, fname)) + item_grid.set_column_disp(fname, show); + }); + + $.each(["base_net_rate", "base_net_amount"], function(i, fname) { + if(frappe.meta.get_docfield(item_grid.doctype, fname)) + item_grid.set_column_disp(fname, (show && (me.frm.doc.currency != company_currency))); + }); + + // set labels + var $wrapper = $(this.frm.wrapper); + $.each(field_label_map, function(fname, label) { + fname = fname.split("-"); + var df = frappe.meta.get_docfield(fname[0], fname[1], me.frm.doc.name); + if(df) df.label = label; + }); + }, + recalculate: function() { this.calculate_taxes_and_totals(); }, @@ -426,60 +518,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ }); }, - included_in_print_rate: function(doc, cdt, cdn) { - var tax = frappe.get_doc(cdt, cdn); - try { - this.validate_on_previous_row(tax); - this.validate_inclusive_tax(tax); - this.calculate_taxes_and_totals(); - } catch(e) { - tax.included_in_print_rate = 0; - refresh_field("included_in_print_rate", tax.name, tax.parentfield); - throw e; - } - }, - - validate_on_previous_row: function(tax) { - // validate if a valid row id is mentioned in case of - // On Previous Row Amount and On Previous Row Total - if((["On Previous Row Amount", "On Previous Row Total"].indexOf(tax.charge_type) != -1) && - (!tax.row_id || cint(tax.row_id) >= tax.idx)) { - var msg = __("Please specify a valid Row ID for row {0} in table {1}", [tax.idx, __(tax.doctype)]) - frappe.throw(msg); - } - }, - - validate_inclusive_tax: function(tax) { - var actual_type_error = function() { - var msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx]) - frappe.throw(msg); - }; - - var on_previous_row_error = function(row_range) { - var msg = __("For row {0} in {1}. To include {2} in Item rate, rows {3} must also be included", - [tax.idx, __(tax.doctype), tax.charge_type, row_range]) - frappe.throw(msg); - }; - - if(cint(tax.included_in_print_rate)) { - if(tax.charge_type == "Actual") { - // inclusive tax cannot be of type Actual - actual_type_error(); - } else if(tax.charge_type == "On Previous Row Amount" && - !cint(this.frm.doc["taxes"][tax.row_id - 1].included_in_print_rate)) { - // referred row should also be an inclusive tax - on_previous_row_error(tax.row_id); - } else if(tax.charge_type == "On Previous Row Total") { - var taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id), - function(t) { return cint(t.included_in_print_rate) ? null : t; }); - if(taxes_not_included.length > 0) { - // all rows above this tax should be inclusive - on_previous_row_error(tax.row_id == 1 ? "1" : "1 - " + tax.row_id); - } - } - } - }, - get_item_wise_taxes_html: function() { var item_tax = {}; var tax_accounts = []; @@ -650,3 +688,19 @@ frappe.ui.form.on(cur_frm.doctype + "Item", "rate", function(frm, cdt, cdn) { cur_frm.cscript.calculate_taxes_and_totals(); }) + +frappe.ui.form.on(cur_frm.cscript.tax_table, "rate", function(frm, cdt, cdn) { + cur_frm.cscript.calculate_taxes_and_totals(); +}) + +frappe.ui.form.on(cur_frm.cscript.tax_table, "tax_amount", function(frm, cdt, cdn) { + cur_frm.cscript.calculate_taxes_and_totals(); +}) + +frappe.ui.form.on(cur_frm.cscript.tax_table, "row_id", function(frm, cdt, cdn) { + cur_frm.cscript.calculate_taxes_and_totals(); +}) + +frappe.ui.form.on(cur_frm.cscript.tax_table, "included_in_print_rate", function(frm, cdt, cdn) { + cur_frm.cscript.calculate_taxes_and_totals(); +}) diff --git a/erpnext/selling/doctype/quotation/quotation.js b/erpnext/selling/doctype/quotation/quotation.js index c63939dbf9..4767f510eb 100644 --- a/erpnext/selling/doctype/quotation/quotation.js +++ b/erpnext/selling/doctype/quotation/quotation.js @@ -3,7 +3,6 @@ {% include 'selling/sales_common.js' %} -{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({ onload: function(doc, dt, dn) { diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 15b0e39740..bc9d0d119a 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -2,7 +2,6 @@ // License: GNU General Public License v3. See license.txt {% include 'selling/sales_common.js' %} -{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend({ refresh: function(doc, dt, dn) { diff --git a/erpnext/selling/sales_common.js b/erpnext/selling/sales_common.js index c153f94ab8..5d49e2f29d 100644 --- a/erpnext/selling/sales_common.js +++ b/erpnext/selling/sales_common.js @@ -2,11 +2,12 @@ // License: GNU General Public License v3. See license.txt +cur_frm.cscript.tax_table = "Sales Taxes and Charges"; +{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} + frappe.provide("erpnext.selling"); frappe.require("assets/erpnext/js/controllers/transaction.js"); -{% include "public/js/controllers/accounts.js" %}; - cur_frm.email_field = "contact_email"; erpnext.selling.SellingController = erpnext.TransactionController.extend({ @@ -311,109 +312,6 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({ } } refresh_field('sales_bom_help'); - }, - - change_form_labels: function(company_currency) { - var me = this; - var field_label_map = {}; - - var setup_field_label_map = function(fields_list, currency) { - $.each(fields_list, function(i, fname) { - var docfield = frappe.meta.docfield_map[me.frm.doc.doctype][fname]; - if(docfield) { - var label = __(docfield.label || "").replace(/\([^\)]*\)/g, ""); - field_label_map[fname] = label.trim() + " (" + currency + ")"; - } - }); - }; - 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", - "outstanding_amount", "total_advance", "paid_amount", "write_off_amount"], - company_currency); - - setup_field_label_map(["total", "net_total", "total_taxes_and_charges", "discount_amount", "grand_total", - "rounded_total", "in_words"], this.frm.doc.currency); - - cur_frm.set_df_property("conversion_rate", "description", "1 " + this.frm.doc.currency - + " = [?] " + company_currency) - - if(this.frm.doc.price_list_currency && this.frm.doc.price_list_currency!=company_currency) { - cur_frm.set_df_property("plc_conversion_rate", "description", "1 " + this.frm.doc.price_list_currency - + " = [?] " + company_currency) - } - - // toggle fields - this.frm.toggle_display(["conversion_rate", "base_total", "base_net_total", "base_total_taxes_and_charges", - "base_grand_total", "base_rounded_total", "base_in_words", "base_discount_amount"], - this.frm.doc.currency != company_currency); - - this.frm.toggle_display(["plc_conversion_rate", "price_list_currency"], - this.frm.doc.price_list_currency != company_currency); - - // set labels - $.each(field_label_map, function(fname, label) { - me.frm.fields_dict[fname].set_label(label); - }); - }, - - change_grid_labels: function(company_currency) { - var me = this; - var field_label_map = {}; - - var setup_field_label_map = function(fields_list, currency, parentfield) { - var grid_doctype = me.frm.fields_dict[parentfield].grid.doctype; - $.each(fields_list, function(i, fname) { - var docfield = frappe.meta.docfield_map[grid_doctype][fname]; - if(docfield) { - var label = __(docfield.label || "").replace(/\([^\)]*\)/g, ""); - field_label_map[grid_doctype + "-" + fname] = - label.trim() + " (" + currency + ")"; - } - }); - } - - setup_field_label_map(["base_rate", "base_net_rate", "base_price_list_rate", "base_amount", "base_net_amount"], - company_currency, "items"); - - setup_field_label_map(["rate", "net_rate", "price_list_rate", "amount", "net_amount"], - this.frm.doc.currency, "items"); - - setup_field_label_map(["tax_amount", "total", "tax_amount_after_discount"], this.frm.doc.currency, "taxes"); - - setup_field_label_map(["base_tax_amount", "base_total", "base_tax_amount_after_discount"], company_currency, "taxes"); - - if(this.frm.fields_dict["advances"]) { - setup_field_label_map(["advance_amount", "allocated_amount"], company_currency, - "advances"); - } - - // toggle columns - var item_grid = this.frm.fields_dict["items"].grid; - $.each(["base_rate", "base_price_list_rate", "base_amount"], function(i, fname) { - if(frappe.meta.get_docfield(item_grid.doctype, fname)) - item_grid.set_column_disp(fname, me.frm.doc.currency != company_currency); - }); - - var show = (cint(cur_frm.doc.discount_amount)) || - ((cur_frm.doc.taxes || []).filter(function(d) {return d.included_in_print_rate===1}).length); - - $.each(["net_rate", "net_amount"], function(i, fname) { - if(frappe.meta.get_docfield(item_grid.doctype, fname)) - item_grid.set_column_disp(fname, show); - }); - - $.each(["base_net_rate", "base_net_amount"], function(i, fname) { - if(frappe.meta.get_docfield(item_grid.doctype, fname)) - item_grid.set_column_disp(fname, (show && (me.frm.doc.currency != company_currency))); - }); - - // set labels - var $wrapper = $(this.frm.wrapper); - $.each(field_label_map, function(fname, label) { - fname = fname.split("-"); - var df = frappe.meta.get_docfield(fname[0], fname[1], me.frm.doc.name); - if(df) df.label = label; - }); } }); @@ -433,7 +331,3 @@ frappe.ui.form.on(cur_frm.doctype,"project_name", function(frm) { }) } }) - -frappe.ui.form.on("Sales Taxes and Charges", "rate", function(frm, cdt, cdn) { - cur_frm.cscript.calculate_taxes_and_totals(); -}) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index 51afa2c805..185c242eda 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -2,7 +2,6 @@ // License: GNU General Public License v3. See license.txt {% include 'selling/sales_common.js' %}; -{% include 'accounts/doctype/sales_taxes_and_charges_master/sales_taxes_and_charges_master.js' %} frappe.provide("erpnext.stock"); frappe.provide("erpnext.stock.delivery_note"); diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 50a1073dcf..a7e662055c 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -2,7 +2,6 @@ // License: GNU General Public License v3. See license.txt {% include 'buying/doctype/purchase_common/purchase_common.js' %}; -{% include 'accounts/doctype/purchase_taxes_and_charges_master/purchase_taxes_and_charges_master.js' %} frappe.provide("erpnext.stock"); erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend({