fix: Commonify code for Stock Entry
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 49c9f8c..6f68848 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -442,7 +442,7 @@
account_currency = get_account_currency(gl_dict.account)
if gl_dict.account and self.doctype not in ["Journal Entry",
- "Period Closing Voucher", "Payment Entry", "Purchase Receipt", "Purchase Invoice"]:
+ "Period Closing Voucher", "Payment Entry", "Purchase Receipt", "Purchase Invoice", "Stock Entry"]:
self.validate_account_currency(gl_dict.account, account_currency)
set_balance_in_account_currency(gl_dict, account_currency, self.get("conversion_rate"),
self.company_currency)
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 8dd2e5b..76309f8 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -10,6 +10,7 @@
validate_taxes_and_charges, validate_inclusive_tax
from erpnext.stock.get_item_details import _get_item_tax_template
from erpnext.accounts.doctype.pricing_rule.utils import get_applied_pricing_rules
+from erpnext.accounts.doctype.journal_entry.journal_entry import get_exchange_rate
class calculate_taxes_and_totals(object):
def __init__(self, doc):
@@ -758,3 +759,35 @@
for taxes in itemised_tax.values():
for tax_account in taxes:
taxes[tax_account]["tax_amount"] = flt(taxes[tax_account]["tax_amount"], precision)
+
+class init_landed_taxes_and_totals(object):
+ def __init__(self, doc):
+ self.doc = doc
+ self.tax_field = 'taxes' if self.doc.doctype == 'Landed Cost Voucher' else 'additional_costs'
+ self.set_account_currency()
+ self.set_exchange_rate()
+ self.set_amounts_in_company_currency()
+
+ def set_account_currency(self):
+ company_currency = erpnext.get_company_currency(self.doc.company)
+ for d in self.doc.get(self.tax_field):
+ if not d.account_currency:
+ account_currency = frappe.db.get_value('Account', d.expense_account, 'account_currency')
+ d.account_currency = account_currency or company_currency
+
+ def set_exchange_rate(self):
+ company_currency = erpnext.get_company_currency(self.doc.company)
+ for d in self.doc.get(self.tax_field):
+ if d.account_currency == company_currency:
+ d.exchange_rate = 1
+ elif not d.exchange_rate or d.exchange_rate == 1 or self.doc.posting_date:
+ d.exchange_rate = get_exchange_rate(self.doc.posting_date, account=d.expense_account,
+ account_currency=d.account_currency, company=self.doc.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.doc.get(self.tax_field):
+ d.amount = flt(d.amount, d.precision("amount"))
+ d.base_amount = flt(d.amount * flt(d.exchange_rate), d.precision("base_amount"))
\ No newline at end of file
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 c817f05..02ff8fa 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.js
@@ -1,6 +1,7 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
// License: GNU General Public License v3. See license.txt
+{% include 'erpnext/stock/landed_taxes_and_charges_common.js' %};
frappe.provide("erpnext.stock");
@@ -29,19 +30,9 @@
this.frm.add_fetch("receipt_document", "supplier", "supplier");
this.frm.add_fetch("receipt_document", "posting_date", "posting_date");
this.frm.add_fetch("receipt_document", "base_grand_total", "grand_total");
-
- this.frm.set_query("expense_account", "taxes", function() {
- return {
- filters: {
- "account_type": ['in', ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation", "Expenses Included In Asset Valuation"]],
- "company": me.frm.doc.company
- }
- };
- });
-
},
- refresh: function(frm) {
+ refresh: function() {
var help_content =
`<br><br>
<table class="table table-bordered" style="background-color: #f9f9f9;">
@@ -71,6 +62,11 @@
</table>`;
set_field_options("landed_cost_help", help_content);
+
+ if (this.frm.doc.company) {
+ let company_currency = frappe.get_doc(":Company", this.frm.doc.company).default_currency;
+ this.frm.set_currency_labels(["total_taxes_and_charges"], company_currency);
+ }
},
get_items_from_purchase_receipts: function() {
@@ -137,53 +133,6 @@
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);
- });
- }
- },
-
- onload: function(frm) {
- let company_currency = frappe.get_doc(":Company", frm.doc.company).default_currency;
- frm.set_currency_labels(["total_taxes_and_charges"], company_currency);
- },
-
- 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);
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 fee641e..24bbc40 100644
--- a/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
+++ b/erpnext/stock/doctype/landed_cost_voucher/landed_cost_voucher.py
@@ -9,7 +9,7 @@
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
+from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals
class LandedCostVoucher(Document):
def get_items_from_purchase_receipts(self):
@@ -41,9 +41,7 @@
def validate(self):
self.check_mandatory()
self.validate_purchase_receipts()
- self.set_account_currency()
- self.set_exchange_rate()
- self.set_amounts_in_company_currency()
+ init_landed_taxes_and_totals(self)
self.set_total_taxes_and_charges()
if not self.get("items"):
self.get_items_from_purchase_receipts()
@@ -101,30 +99,6 @@
diff = self.total_taxes_and_charges - total_charges
self.get('items')[item_count - 1].applicable_charges += diff
- def set_account_currency(self):
- company_currency = erpnext.get_company_currency(self.company)
- for d in self.get('taxes'):
- if not d.account_currency:
- account_currency = frappe.db.get_value('Account', d.expense_account, 'account_currency')
- d.account_currency = account_currency or company_currency
-
- 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()
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index 98116ec..f3f5ac8 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -1,6 +1,8 @@
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors // License: GNU General Public License v3. See license.txt
frappe.provide("erpnext.stock");
+{% include 'erpnext/stock/landed_taxes_and_charges_common.js' %};
+
frappe.ui.form.on('Stock Entry', {
setup: function(frm) {
@@ -86,15 +88,6 @@
}
});
- frm.set_query("expense_account", "additional_costs", 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"],
- "company": frm.doc.company
- }
- };
- });
frm.add_fetch("bom_no", "inspection_required", "inspection_required");
},
@@ -524,7 +517,7 @@
})
);
}
-
+
for (let i in frm.doc.items) {
let item = frm.doc.items[i];
@@ -547,7 +540,7 @@
calculate_total_additional_costs: function(frm) {
const total_additional_costs = frappe.utils.sum(
- (frm.doc.additional_costs || []).map(function(c) { return flt(c.amount); })
+ (frm.doc.additional_costs || []).map(function(c) { return flt(c.base_amount); })
);
frm.set_value("total_additional_costs",
@@ -716,8 +709,18 @@
};
frappe.ui.form.on('Landed Cost Taxes and Charges', {
- amount: function(frm) {
- frm.events.calculate_amount(frm);
+ amount: function(frm, cdt, cdn) {
+ frm.events.set_base_amount(frm, cdt, cdn);
+
+ // Adding this check because same table in used in LCV
+ // This causes an error if you try to post an LCV immediately after a Stock Entry
+ if (frm.doc.doctype == 'Stock Entry') {
+ frm.events.calculate_amount(frm);
+ }
+ },
+
+ expense_account: function(frm, cdt, cdn) {
+ frm.events.set_account_currency(frm, cdt, cdn);
}
});
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index afdb54c..adaaff7 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -19,6 +19,7 @@
from erpnext.stock.doctype.serial_no.serial_no import update_serial_nos_after_submit, get_serial_nos
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import OpeningEntryAccountError
from erpnext.accounts.general_ledger import process_gl_map
+from erpnext.controllers.taxes_and_totals import init_landed_taxes_and_totals
import json
from six import string_types, itervalues, iteritems
@@ -186,7 +187,7 @@
and (sed.t_warehouse is null or sed.t_warehouse = '')""", self.project, as_list=1)
amount = amount[0][0] if amount else 0
- additional_costs = frappe.db.sql(""" select ifnull(sum(sed.amount), 0)
+ additional_costs = frappe.db.sql(""" select ifnull(sum(sed.base_amount), 0)
from
`tabStock Entry` se, `tabLanded Cost Taxes and Charges` sed
where
@@ -431,6 +432,7 @@
def calculate_rate_and_amount(self, reset_outgoing_rate=True, raise_error_if_no_rate=True):
self.set_basic_rate(reset_outgoing_rate, raise_error_if_no_rate)
+ init_landed_taxes_and_totals(self)
self.distribute_additional_costs()
self.update_valuation_rate()
self.set_total_incoming_outgoing_value()
@@ -518,7 +520,7 @@
if not any([d.item_code for d in self.items if d.t_warehouse]):
self.additional_costs = []
- self.total_additional_costs = sum([flt(t.amount) for t in self.get("additional_costs")])
+ self.total_additional_costs = sum([flt(t.base_amount) for t in self.get("additional_costs")])
if self.purpose in ("Repack", "Manufacture"):
incoming_items_cost = sum([flt(t.basic_amount) for t in self.get("items") if t.is_finished_item])
@@ -698,7 +700,7 @@
# SLE for target warehouse
self.get_sle_for_target_warehouse(sl_entries, finished_item_row)
-
+
# reverse sl entries if cancel
if self.docstatus == 2:
sl_entries.reverse()
@@ -726,9 +728,9 @@
sle.dependant_sle_voucher_detail_no = d.name
elif finished_item_row and (finished_item_row.item_code != d.item_code or finished_item_row.t_warehouse != d.s_warehouse):
sle.dependant_sle_voucher_detail_no = finished_item_row.name
-
+
sl_entries.append(sle)
-
+
def get_sle_for_target_warehouse(self, sl_entries, finished_item_row):
for d in self.get('items'):
if cstr(d.t_warehouse):
@@ -758,13 +760,19 @@
for d in self.get("items"):
if d.t_warehouse:
item_account_wise_additional_cost.setdefault((d.item_code, d.name), {})
- item_account_wise_additional_cost[(d.item_code, d.name)].setdefault(t.expense_account, 0.0)
+ item_account_wise_additional_cost[(d.item_code, d.name)].setdefault(t.expense_account, {
+ "amount": 0.0,
+ "base_amount": 0.0
+ })
multiply_based_on = d.basic_amount if total_basic_amount else d.qty
- item_account_wise_additional_cost[(d.item_code, d.name)][t.expense_account] += \
+ item_account_wise_additional_cost[(d.item_code, d.name)][t.expense_account]["amount"] += \
flt(t.amount * multiply_based_on) / divide_based_on
+ item_account_wise_additional_cost[(d.item_code, d.name)][t.expense_account]["base_amount"] += \
+ flt(t.base_amount * multiply_based_on) / divide_based_on
+
if item_account_wise_additional_cost:
for d in self.get("items"):
for account, amount in iteritems(item_account_wise_additional_cost.get((d.item_code, d.name), {})):
@@ -775,7 +783,8 @@
"against": d.expense_account,
"cost_center": d.cost_center,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
- "credit": amount
+ "credit_in_account_currency": flt(amount["amount"]),
+ "credit": flt(amount["base_amount"])
}, item=d))
gl_entries.append(self.get_gl_dict({
@@ -783,7 +792,7 @@
"against": account,
"cost_center": d.cost_center,
"remarks": self.get("remarks") or _("Accounting Entry for Stock"),
- "credit": -1 * amount # put it as negative credit instead of debit purposefully
+ "credit": -1 * amount['base_amount'] # put it as negative credit instead of debit purposefully
}, item=d))
return process_gl_map(gl_entries)
diff --git a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
index 6fe6029..b4c2284 100644
--- a/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
+++ b/erpnext/stock/doctype/stock_entry_detail/stock_entry_detail.json
@@ -526,7 +526,7 @@
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
- "modified": "2020-09-23 17:55:03.384138",
+ "modified": "2020-09-25 17:55:03.384138",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",
diff --git a/erpnext/stock/landed_taxes_and_charges_common.js b/erpnext/stock/landed_taxes_and_charges_common.js
new file mode 100644
index 0000000..8ad0880
--- /dev/null
+++ b/erpnext/stock/landed_taxes_and_charges_common.js
@@ -0,0 +1,58 @@
+let document_list = ['Landed Cost Voucher', 'Stock Entry'];
+
+document_list.forEach((doctype) => {
+ frappe.ui.form.on(doctype, {
+ refresh: function(frm) {
+ let tax_field = frm.doc.doctype == 'Landed Cost Voucher' ? 'taxes' : 'additional_costs';
+ frm.set_query("expense_account", tax_field, function() {
+ return {
+ filters: {
+ "account_type": ['in', ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation", "Expenses Included In Asset Valuation"]],
+ "company": frm.doc.company
+ }
+ };
+ });
+ },
+
+ 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)));
+ }
+ });
+});
+