From 46f3c65b003442ecfcdbcdc1d13422f872ea88bf Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 14 Dec 2020 23:09:19 +0530 Subject: [PATCH] feat: Multi currency in landed cost voucher --- .../landed_cost_taxes_and_charges.json | 32 +++++++++- .../landed_cost_voucher.js | 58 +++++++++++++++++-- .../landed_cost_voucher.json | 26 ++++++++- .../landed_cost_voucher.py | 31 ++++++---- 4 files changed, 129 insertions(+), 18 deletions(-) diff --git a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json index 0cc243d4cb..ae8747fc83 100644 --- a/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json +++ b/erpnext/stock/doctype/landed_cost_taxes_and_charges/landed_cost_taxes_and_charges.json @@ -1,12 +1,16 @@ { + "actions": [], "creation": "2014-07-11 11:51:00.453717", "doctype": "DocType", "editable_grid": 1, "engine": "InnoDB", "field_order": [ "expense_account", + "account_currency", + "exchange_rate", "description", "col_break3", + "base_amount", "amount" ], "fields": [ @@ -27,7 +31,7 @@ "fieldtype": "Currency", "in_list_view": 1, "label": "Amount", - "options": "Company:company:default_currency", + "options": "account_currency", "reqd": 1 }, { @@ -37,10 +41,34 @@ "label": "Expense Account", "options": "Account", "reqd": 1 + }, + { + "fieldname": "account_currency", + "fieldtype": "Link", + "label": "Account Currency", + "options": "Currency", + "read_only": 1, + "reqd": 1 + }, + { + "fieldname": "exchange_rate", + "fieldtype": "Float", + "label": "Exchange Rate", + "precision": "9" + }, + { + "fieldname": "base_amount", + "fieldtype": "Currency", + "label": "Base Amount", + "options": "Company:company:default_currency", + "read_only": 1, + "reqd": 1 } ], + "index_web_pages_for_search": 1, "istable": 1, - "modified": "2019-09-30 18:28:32.070655", + "links": [], + "modified": "2020-12-13 21:04:01.769989", "modified_by": "Administrator", "module": "Stock", "name": "Landed Cost Taxes and Charges", diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js index 5de1352518..a5ac60c4f5 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js @@ -32,9 +32,8 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({ this.frm.set_query("expense_account", "taxes", function() { return { - query: "erpnext.controllers.queries.tax_account_query", filters: { - "account_type": ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation", "Expenses Included In Asset Valuation"], + "account_type": ['in', ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation", "Expenses Included In Asset Valuation"]], "company": me.frm.doc.company } }; @@ -97,7 +96,7 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({ set_total_taxes_and_charges: function() { var total_taxes_and_charges = 0.0; $.each(this.frm.doc.taxes || [], function(i, d) { - total_taxes_and_charges += flt(d.amount) + total_taxes_and_charges += flt(d.base_amount) }); cur_frm.set_value("total_taxes_and_charges", total_taxes_and_charges); }, @@ -134,7 +133,58 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({ items_remove: () => { this.trigger('set_applicable_charges_for_item'); } - }); cur_frm.script_manager.make(erpnext.stock.LandedCostVoucher); + +frappe.ui.form.on('Landed Cost Voucher', { + set_account_currency: function(frm, cdt, cdn) { + let row = locals[cdt][cdn]; + if (row.expense_account) { + frappe.db.get_value('Account', row.expense_account, 'account_currency', function(value) { + frappe.model.set_value(cdt, cdn, "account_currency", value.account_currency); + frm.events.set_exchange_rate(frm, cdt, cdn); + }); + } + }, + + set_exchange_rate: function(frm, cdt, cdn) { + let row = locals[cdt][cdn]; + let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency; + + if(row.account_currency == company_currency) { + row.exchange_rate = 1; + } else if (!row.exchange_rate || row.exchange_rate == 1) { + frappe.call({ + method: "erpnext.accounts.doctype.journal_entry.journal_entry.get_exchange_rate", + args: { + posting_date: frm.doc.posting_date, + account: row.expense_account, + account_currency: row.account_currency, + company: frm.doc.company + }, + callback: function(r) { + if(r.message) { + frappe.model.set_value(cdt, cdn, "exchange_rate", r.message); + } + } + }) + } + }, + + set_base_amount: function(frm, cdt, cdn) { + let row = locals[cdt][cdn]; + frappe.model.set_value(cdt, cdn, "base_amount", + flt(flt(row.amount)*row.exchange_rate, precision("base_amount", row))); + } +}) + +frappe.ui.form.on('Landed Cost Taxes and Charges', { + expense_account: function(frm, cdt, cdn) { + frm.events.set_account_currency(frm, cdt, cdn); + }, + + amount: function(frm, cdt, cdn) { + frm.events.set_base_amount(frm, cdt, cdn); + } +}); diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.json b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.json index 01492807de..6a7994ba9e 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.json +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.json @@ -1,4 +1,5 @@ { + "actions": [], "autoname": "naming_series:", "creation": "2014-07-11 11:33:42.547339", "doctype": "DocType", @@ -7,6 +8,9 @@ "field_order": [ "naming_series", "company", + "column_break_2", + "posting_date", + "section_break_5", "purchase_receipts", "purchase_receipt_items", "get_items_from_purchase_receipts", @@ -86,7 +90,7 @@ { "fieldname": "total_taxes_and_charges", "fieldtype": "Currency", - "label": "Total Taxes and Charges", + "label": "Total Taxes and Charges (Company Currency)", "options": "Company:company:default_currency", "read_only": 1, "reqd": 1 @@ -119,11 +123,29 @@ "fieldname": "landed_cost_help", "fieldtype": "HTML", "label": "Landed Cost Help" + }, + { + "fieldname": "column_break_2", + "fieldtype": "Column Break" + }, + { + "default": "Today", + "fieldname": "posting_date", + "fieldtype": "Date", + "label": "Posting Date", + "reqd": 1 + }, + { + "fieldname": "section_break_5", + "fieldtype": "Section Break", + "hide_border": 1 } ], "icon": "icon-usd", + "index_web_pages_for_search": 1, "is_submittable": 1, - "modified": "2019-11-21 15:34:10.846093", + "links": [], + "modified": "2020-12-13 23:18:47.442466", "modified_by": "Administrator", "module": "Stock", "name": "Landed Cost Voucher", diff --git a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py index bc3d3266ad..e39208991b 100644 --- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py +++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py @@ -9,6 +9,7 @@ from frappe.model.meta import get_field_precision from frappe.model.document import Document from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos from erpnext.accounts.doctype.account.account import get_account_currency +from erpnext.accounts.doctype.journal_entry.journal_entry import get_exchange_rate class LandedCostVoucher(Document): def get_items_from_purchase_receipts(self): @@ -39,12 +40,13 @@ class LandedCostVoucher(Document): def validate(self): self.check_mandatory() + self.set_exchange_rate() + self.set_amounts_in_company_currency() if not self.get("items"): self.get_items_from_purchase_receipts() else: self.validate_applicable_charges_for_item() self.validate_purchase_receipts() - self.validate_expense_accounts() self.set_total_taxes_and_charges() def check_mandatory(self): @@ -73,16 +75,25 @@ class LandedCostVoucher(Document): frappe.throw(_("Row {0}: Cost center is required for an item {1}") .format(item.idx, item.item_code)) - def validate_expense_accounts(self): - company_currency = erpnext.get_company_currency(self.company) - for account in self.taxes: - if get_account_currency(account.expense_account) != company_currency: - frappe.throw(msg=_(""" Row {0}: Expense account currency should be same as company's default currency. - Please select expense account with account currency as {1}""") - .format(account.idx, frappe.bold(company_currency)), title=_("Invalid Account Currency")) - def set_total_taxes_and_charges(self): - self.total_taxes_and_charges = sum([flt(d.amount) for d in self.get("taxes")]) + self.total_taxes_and_charges = sum([flt(d.base_amount) for d in self.get("taxes")]) + + def set_exchange_rate(self): + company_currency = erpnext.get_company_currency(self.company) + for d in self.get('taxes'): + if d.account_currency == company_currency: + d.exchange_rate = 1 + elif not d.exchange_rate or d.exchange_rate == 1 or self.posting_date: + d.exchange_rate = get_exchange_rate(self.posting_date, account=d.expense_account, + account_currency=d.account_currency, company=self.company) + + if not d.exchange_rate: + frappe.throw(_("Row {0}: Exchange Rate is mandatory").format(d.idx)) + + def set_amounts_in_company_currency(self): + for d in self.get('taxes'): + d.amount = flt(d.amount, d.precision("amount")) + d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount")) def validate_applicable_charges_for_item(self): based_on = self.distribute_charges_based_on.lower()