diff --git a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json index c3017eba70..d1513fe862 100644 --- a/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json +++ b/erpnext/accounts/doctype/sales_taxes_and_charges/sales_taxes_and_charges.json @@ -3,6 +3,7 @@ "allow_import": 0, "allow_rename": 0, "autoname": "INVTD.######", + "beta": 0, "creation": "2013-04-24 11:39:32", "custom": 0, "docstatus": 0, @@ -508,18 +509,22 @@ "hide_heading": 1, "hide_toolbar": 0, "idx": 1, + "image_view": 0, "in_create": 0, "in_dialog": 0, "is_submittable": 0, "issingle": 0, "istable": 1, "max_attachments": 0, - "modified": "2016-02-22 09:35:25.423372", + "modified": "2016-06-15 14:49:31.101752", "modified_by": "Administrator", "module": "Accounts", "name": "Sales Taxes and Charges", "owner": "Administrator", "permissions": [], + "quick_entry": 0, "read_only": 0, - "read_only_onload": 0 + "read_only_onload": 0, + "sort_order": "ASC", + "track_seen": 0 } \ No newline at end of file diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 34f098e6de..e3a66a4b11 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -48,7 +48,7 @@ class AccountsController(TransactionBase): self.validate_party() self.validate_currency() - + if self.meta.get_field("is_recurring"): if self.amended_from and self.recurring_id: self.recurring_id = None @@ -65,7 +65,7 @@ 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.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")) else: @@ -227,13 +227,13 @@ class AccountsController(TransactionBase): def get_gl_dict(self, args, account_currency=None): """this method populates the common properties of a gl entry record""" - + fiscal_years = get_fiscal_years(self.posting_date, company=self.company) if len(fiscal_years) > 1: frappe.throw(_("Multiple fiscal years exist for the date {0}. Please set company in Fiscal Year").format(formatdate(self.posting_date))) else: fiscal_year = fiscal_years[0][0] - + gl_dict = frappe._dict({ 'company': self.company, 'posting_date': self.posting_date, @@ -471,31 +471,31 @@ class AccountsController(TransactionBase): # Note: not validating with gle account because we don't have the account # at quotation / sales order level and we shouldn't stop someone # from creating a sales invoice if sales order is already created - + def validate_fixed_asset(self): for d in self.get("items"): if d.is_fixed_asset: if d.qty > 1: frappe.throw(_("Row #{0}: Qty must be 1, as item is a fixed asset. Please use separate row for multiple qty.").format(d.idx)) - + if d.meta.get_field("asset"): if not d.asset: frappe.throw(_("Row #{0}: Asset is mandatory for fixed asset purchase/sale") .format(d.idx)) else: asset = frappe.get_doc("Asset", d.asset) - + if asset.company != self.company: frappe.throw(_("Row #{0}: Asset {1} does not belong to company {2}") .format(d.idx, d.asset, self.company)) - + elif asset.item_code != d.item_code: frappe.throw(_("Row #{0}: Asset {1} does not linked to Item {2}") .format(d.idx, d.asset, d.item_code)) - + elif asset.docstatus != 1: frappe.throw(_("Row #{0}: Asset {1} must be submitted").format(d.idx, d.asset)) - + elif self.doctype == "Purchase Invoice": if asset.status != "Submitted": frappe.throw(_("Row #{0}: Asset {1} is already {2}") @@ -504,18 +504,18 @@ class AccountsController(TransactionBase): frappe.throw(_("Row #{0}: Posting Date must be same as purchase date {1} of asset {2}").format(d.idx, asset.purchase_date, d.asset)) elif asset.is_existing_asset: frappe.throw(_("Row #{0}: Purchase Invoice cannot be made against an existing asset {1}").format(d.idx, d.asset)) - + elif self.docstatus=="Sales Invoice" and self.docstatus == 1: if self.update_stock: frappe.throw(_("'Update Stock' cannot be checked for fixed asset sale")) - + elif asset.status in ("Scrapped", "Cancelled", "Sold"): frappe.throw(_("Row #{0}: Asset {1} cannot be submitted, it is already {2}") .format(d.idx, d.asset, asset.status)) @frappe.whitelist() def get_tax_rate(account_head): - return frappe.db.get_value("Account", account_head, "tax_rate") + return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True) @frappe.whitelist() def get_default_taxes_and_charges(master_doctype): diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js index e19919d261..202000fbe2 100644 --- a/erpnext/public/js/controllers/accounts.js +++ b/erpnext/public/js/controllers/accounts.js @@ -6,6 +6,14 @@ frappe.provide("erpnext.taxes"); frappe.provide("erpnext.taxes.flags"); frappe.ui.form.on(cur_frm.doctype, { + setup: function(frm) { + // set conditional display for rate column in taxes + $(frm.wrapper).on('grid-row-render', function(e, grid_row) { + if(in_list(['Sales Taxes and Charges', 'Purchase Taxes and Charges'], grid_row.doc.doctype)) { + erpnext.taxes.set_conditional_mandatory_rate_or_amount(grid_row); + } + }); + }, onload: function(frm) { if(frm.get_field("taxes")) { frm.set_query("account_head", "taxes", function(doc) { @@ -40,10 +48,10 @@ frappe.ui.form.on(cur_frm.doctype, { frm.get_docfield("taxes", "rate").reqd = 0; frm.get_docfield("taxes", "tax_amount").reqd = 0; } - + }, taxes_on_form_rendered: function(frm) { - erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm); + erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.open_grid_row()); } }); @@ -58,7 +66,8 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) { method: "erpnext.controllers.accounts_controller.get_tax_rate", args: {"account_head":d.account_head}, callback: function(r) { - frappe.model.set_value(cdt, cdn, "rate", r.message || 0); + frappe.model.set_value(cdt, cdn, "rate", r.message.tax_rate || 0); + frappe.model.set_value(cdt, cdn, "description", r.message.account_name); } }) } @@ -67,6 +76,12 @@ cur_frm.cscript.account_head = function(doc, cdt, cdn) { cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) { var d = locals[cdt][cdn]; var msg = ""; + + if(d.account_head && !d.description) { + // set description from account head + d.description = d.account_head.split(' - ').slice(0, -1).join(' - '); + } + if(!d.charge_type && (d.row_id || d.rate || d.tax_amount)) { msg = __("Please select Charge Type first"); d.row_id = ""; @@ -143,8 +158,14 @@ if(!erpnext.taxes.flags[cur_frm.cscript.tax_table]) { }); frappe.ui.form.on(cur_frm.cscript.tax_table, "charge_type", function(frm, cdt, cdn) { - cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); - erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm); + frm.cscript.validate_taxes_and_charges(cdt, cdn); + var open_form = frm.open_grid_row(); + if(open_form) { + erpnext.taxes.set_conditional_mandatory_rate_or_amount(open_form); + } else { + // apply in current row + erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.get_field('taxes').grid.get_grid_row(cdn)); + } }); frappe.ui.form.on(cur_frm.cscript.tax_table, "included_in_print_rate", function(frm, cdt, cdn) { @@ -160,18 +181,19 @@ if(!erpnext.taxes.flags[cur_frm.cscript.tax_table]) { }); } -erpnext.taxes.set_conditional_mandatory_rate_or_amount = function(frm) { - var grid_row = frm.open_grid_row(); - if(grid_row.doc.charge_type==="Actual") { - grid_row.toggle_display("tax_amount", true); - grid_row.toggle_reqd("tax_amount", true); - grid_row.toggle_display("rate", false); - grid_row.toggle_reqd("rate", false); - } else { - grid_row.toggle_display("rate", true); - grid_row.toggle_reqd("rate", true); - grid_row.toggle_display("tax_amount", false); - grid_row.toggle_reqd("tax_amount", false); +erpnext.taxes.set_conditional_mandatory_rate_or_amount = function(grid_row) { + if(grid_row) { + if(grid_row.doc.charge_type==="Actual") { + grid_row.toggle_editable("tax_amount", true); + grid_row.toggle_reqd("tax_amount", true); + grid_row.toggle_editable("rate", false); + grid_row.toggle_reqd("rate", false); + } else { + grid_row.toggle_editable("rate", true); + grid_row.toggle_reqd("rate", true); + grid_row.toggle_editable("tax_amount", false); + grid_row.toggle_reqd("tax_amount", false); + } } } diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index cf66501c4f..a0507ef69f 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -2,6 +2,18 @@ // License: GNU General Public License v3. See license.txt erpnext.taxes_and_totals = erpnext.payments.extend({ + setup: function() { + if(this.frm.get_field('taxes')) { + this.frm.get_field('taxes').grid.editable_fields = [ + {fieldname: 'charge_type', columns: 2}, + {fieldname: 'account_head', columns: 3}, + {fieldname: 'rate', columns: 2}, + {fieldname: 'tax_amount', columns: 2}, + {fieldname: 'total', columns: 2} + ]; + } + + }, apply_pricing_rule_on_item: function(item){ if(!item.margin_type){ item.margin_rate_or_amount = 0.0; @@ -460,8 +472,8 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ if (this.frm.doc.discount_amount) { if(!this.frm.doc.apply_discount_on) frappe.throw(__("Please select Apply Discount On")); - - this.frm.doc.base_discount_amount = flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate, + + this.frm.doc.base_discount_amount = flt(this.frm.doc.discount_amount * this.frm.doc.conversion_rate, precision("base_discount_amount")); var total_for_discount_amount = this.get_total_for_discount_amount(); @@ -550,11 +562,11 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.refresh_field("paid_amount"); this.frm.refresh_field("base_paid_amount"); } - + if(this.frm.doc.doctype == "Sales Invoice"){ this.calculate_paid_amount() } - + var outstanding_amount = 0.0 var paid_amount = (this.frm.doc.party_account_currency == this.frm.doc.currency) ? @@ -572,7 +584,7 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ this.frm.doc.outstanding_amount = outstanding_amount; this.calculate_change_amount() }, - + calculate_paid_amount: function(){ var me = this; var paid_amount = base_paid_amount = 0.0; @@ -580,24 +592,24 @@ erpnext.taxes_and_totals = erpnext.payments.extend({ if(data.amount > -1){ data.base_amount = flt(data.amount * me.frm.doc.conversion_rate); paid_amount += data.amount; - base_paid_amount += data.base_amount; + base_paid_amount += data.base_amount; } }) - + this.frm.doc.paid_amount = flt(paid_amount, precision("paid_amount")); this.frm.doc.base_paid_amount = flt(base_paid_amount, precision("base_paid_amount")); }, - + calculate_change_amount: function(){ var change_amount = 0.0; if(this.frm.doc.paid_amount > this.frm.doc.grand_total){ - change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total, + change_amount = flt(this.frm.doc.paid_amount - this.frm.doc.grand_total, precision("change_amount")) } - - this.frm.doc.change_amount = flt(change_amount, + + this.frm.doc.change_amount = flt(change_amount, precision("change_amount")) - this.frm.doc.base_change_amount = flt(change_amount * this.frm.doc.conversion_rate, + this.frm.doc.base_change_amount = flt(change_amount * this.frm.doc.conversion_rate, precision("base_change_amount")) }, }) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index ac0287d05a..ce11c8a80b 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -3,6 +3,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ setup: function() { + this._super(); frappe.ui.form.on(this.frm.doctype + " Item", "rate", function(frm, cdt, cdn) { var item = frappe.get_doc(cdt, cdn); frappe.model.round_floats_in(item, ["rate", "price_list_rate"]); @@ -978,7 +979,4 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ this.item_selector = new erpnext.ItemSelector({frm: this.frm}); } } - - - }); \ No newline at end of file