fix: bom incorrect price list rate for raw material if price list currency is different from company currency (#21585)
* fix: bom incorrect price list rate for raw material if price list currency is different from company currency * fixed test cases * fixed base_rate calculation and added plc_conversion_rate trigger
This commit is contained in:
parent
1e7bc3a97e
commit
be750096ed
@ -212,6 +212,12 @@ frappe.ui.form.on("BOM", {
|
||||
});
|
||||
},
|
||||
|
||||
rm_cost_as_per: function(frm) {
|
||||
if (in_list(["Valuation Rate", "Last Purchase Rate"], frm.doc.rm_cost_as_per)) {
|
||||
frm.set_value("plc_conversion_rate", 1.0);
|
||||
}
|
||||
},
|
||||
|
||||
routing: function(frm) {
|
||||
if (frm.doc.routing) {
|
||||
frappe.call({
|
||||
@ -242,7 +248,7 @@ erpnext.bom.BomController = erpnext.TransactionController.extend({
|
||||
item_code: function(doc, cdt, cdn){
|
||||
var scrap_items = false;
|
||||
var child = locals[cdt][cdn];
|
||||
if(child.doctype == 'BOM Scrap Item') {
|
||||
if (child.doctype == 'BOM Scrap Item') {
|
||||
scrap_items = true;
|
||||
}
|
||||
|
||||
@ -252,8 +258,19 @@ erpnext.bom.BomController = erpnext.TransactionController.extend({
|
||||
|
||||
get_bom_material_detail(doc, cdt, cdn, scrap_items);
|
||||
},
|
||||
|
||||
buying_price_list: function(doc) {
|
||||
this.apply_price_list();
|
||||
},
|
||||
|
||||
plc_conversion_rate: function(doc) {
|
||||
if (!this.in_apply_price_list) {
|
||||
this.apply_price_list();
|
||||
}
|
||||
},
|
||||
|
||||
conversion_factor: function(doc, cdt, cdn) {
|
||||
if(frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
|
||||
if (frappe.meta.get_docfield(cdt, "stock_qty", cdn)) {
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
frappe.model.round_floats_in(item, ["qty", "conversion_factor"]);
|
||||
item.stock_qty = flt(item.qty * item.conversion_factor, precision("stock_qty", item));
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"creation": "2013-01-22 15:11:38",
|
||||
"doctype": "DocType",
|
||||
@ -6,23 +7,25 @@
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"item",
|
||||
"quantity",
|
||||
"set_rate_of_sub_assembly_item_based_on_bom",
|
||||
"company",
|
||||
"item_name",
|
||||
"uom",
|
||||
"cb0",
|
||||
"is_active",
|
||||
"is_default",
|
||||
"allow_alternative_item",
|
||||
"image",
|
||||
"item_name",
|
||||
"uom",
|
||||
"currency_detail",
|
||||
"company",
|
||||
"set_rate_of_sub_assembly_item_based_on_bom",
|
||||
"project",
|
||||
"quantity",
|
||||
"image",
|
||||
"currency_detail",
|
||||
"currency",
|
||||
"conversion_rate",
|
||||
"column_break_12",
|
||||
"currency",
|
||||
"rm_cost_as_per",
|
||||
"buying_price_list",
|
||||
"price_list_currency",
|
||||
"plc_conversion_rate",
|
||||
"section_break_21",
|
||||
"with_operations",
|
||||
"column_break_23",
|
||||
@ -176,7 +179,8 @@
|
||||
},
|
||||
{
|
||||
"fieldname": "currency_detail",
|
||||
"fieldtype": "Section Break"
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Currency and Price List"
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
@ -324,7 +328,7 @@
|
||||
},
|
||||
{
|
||||
"fieldname": "base_scrap_material_cost",
|
||||
"fieldtype": "Data",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Scrap Material Cost(Company Currency)",
|
||||
"no_copy": 1,
|
||||
"options": "Company:company:default_currency",
|
||||
@ -477,13 +481,31 @@
|
||||
{
|
||||
"fieldname": "column_break_52",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"depends_on": "eval:doc.rm_cost_as_per=='Price List'",
|
||||
"fieldname": "plc_conversion_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": "Price List Exchange Rate"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"depends_on": "eval:doc.rm_cost_as_per=='Price List'",
|
||||
"fieldname": "price_list_currency",
|
||||
"fieldtype": "Link",
|
||||
"label": "Price List Currency",
|
||||
"options": "Currency",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-sitemap",
|
||||
"idx": 1,
|
||||
"image_field": "image",
|
||||
"is_submittable": 1,
|
||||
"modified": "2019-11-22 14:35:12.142150",
|
||||
"links": [],
|
||||
"modified": "2020-05-05 14:29:32.634952",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM",
|
||||
|
@ -70,11 +70,13 @@ class BOM(WebsiteGenerator):
|
||||
self.validate_main_item()
|
||||
self.validate_currency()
|
||||
self.set_conversion_rate()
|
||||
self.set_plc_conversion_rate()
|
||||
self.validate_uom_is_interger()
|
||||
self.set_bom_material_details()
|
||||
self.validate_materials()
|
||||
self.validate_operations()
|
||||
self.calculate_cost()
|
||||
self.update_cost(update_parent=False, from_child_bom=True, save=False)
|
||||
|
||||
def get_context(self, context):
|
||||
context.parents = [{'name': 'boms', 'title': _('All BOMs') }]
|
||||
@ -165,7 +167,7 @@ class BOM(WebsiteGenerator):
|
||||
'rate' : rate,
|
||||
'qty' : args.get("qty") or args.get("stock_qty") or 1,
|
||||
'stock_qty' : args.get("qty") or args.get("stock_qty") or 1,
|
||||
'base_rate' : rate,
|
||||
'base_rate' : flt(rate) * (flt(self.conversion_rate) or 1),
|
||||
'include_item_in_manufacturing': cint(args['transfer_for_manufacture']) or 0
|
||||
}
|
||||
|
||||
@ -226,7 +228,7 @@ class BOM(WebsiteGenerator):
|
||||
frappe.msgprint(_("{0} not found for item {1}")
|
||||
.format(self.rm_cost_as_per, arg["item_code"]), alert=True)
|
||||
|
||||
return flt(rate) / (self.conversion_rate or 1)
|
||||
return flt(rate) * flt(self.plc_conversion_rate or 1) / (self.conversion_rate or 1)
|
||||
|
||||
def update_cost(self, update_parent=True, from_child_bom=False, save=True):
|
||||
if self.docstatus == 2:
|
||||
@ -243,10 +245,15 @@ class BOM(WebsiteGenerator):
|
||||
"stock_uom": d.stock_uom,
|
||||
"conversion_factor": d.conversion_factor
|
||||
})
|
||||
|
||||
if rate:
|
||||
d.rate = rate
|
||||
d.amount = flt(d.rate) * flt(d.qty)
|
||||
d.db_update()
|
||||
d.base_rate = flt(d.rate) * flt(self.conversion_rate)
|
||||
d.base_amount = flt(d.amount) * flt(self.conversion_rate)
|
||||
|
||||
if save:
|
||||
d.db_update()
|
||||
|
||||
if self.docstatus == 1:
|
||||
self.flags.ignore_validate_update_after_submit = True
|
||||
@ -372,6 +379,13 @@ class BOM(WebsiteGenerator):
|
||||
elif self.conversion_rate == 1 or flt(self.conversion_rate) <= 0:
|
||||
self.conversion_rate = get_exchange_rate(self.currency, self.company_currency(), args="for_buying")
|
||||
|
||||
def set_plc_conversion_rate(self):
|
||||
if self.rm_cost_as_per in ["Valuation Rate", "Last Purchase Rate"]:
|
||||
self.plc_conversion_rate = 1
|
||||
elif not self.plc_conversion_rate and self.price_list_currency:
|
||||
self.plc_conversion_rate = get_exchange_rate(self.price_list_currency,
|
||||
self.company_currency(), args="for_buying")
|
||||
|
||||
def validate_materials(self):
|
||||
""" Validate raw material entries """
|
||||
|
||||
|
@ -81,13 +81,13 @@ class TestBOM(unittest.TestCase):
|
||||
|
||||
# test amounts in selected currency
|
||||
self.assertEqual(bom.operating_cost, 100)
|
||||
self.assertEqual(bom.raw_material_cost, 8000)
|
||||
self.assertEqual(bom.total_cost, 8100)
|
||||
self.assertEqual(bom.raw_material_cost, 351.68)
|
||||
self.assertEqual(bom.total_cost, 451.68)
|
||||
|
||||
# test amounts in selected currency
|
||||
self.assertEqual(bom.base_operating_cost, 6000)
|
||||
self.assertEqual(bom.base_raw_material_cost, 480000)
|
||||
self.assertEqual(bom.base_total_cost, 486000)
|
||||
self.assertEqual(bom.base_raw_material_cost, 21100.80)
|
||||
self.assertEqual(bom.base_total_cost, 27100.80)
|
||||
|
||||
def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self):
|
||||
frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependent", 1)
|
||||
|
@ -685,3 +685,4 @@ execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)
|
||||
erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
|
||||
erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
|
||||
erpnext.patches.v12_0.set_serial_no_status
|
||||
erpnext.patches.v12_0.update_price_list_currency_in_bom
|
||||
|
31
erpnext/patches/v12_0/update_price_list_currency_in_bom.py
Normal file
31
erpnext/patches/v12_0/update_price_list_currency_in_bom.py
Normal file
@ -0,0 +1,31 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.utils import getdate, flt
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("manufacturing", "doctype", "bom")
|
||||
frappe.reload_doc("manufacturing", "doctype", "bom_item")
|
||||
|
||||
frappe.db.sql(""" UPDATE `tabBOM`, `tabPrice List`
|
||||
SET
|
||||
`tabBOM`.price_list_currency = `tabPrice List`.currency,
|
||||
`tabBOM`.plc_conversion_rate = 1.0
|
||||
WHERE
|
||||
`tabBOM`.buying_price_list = `tabPrice List`.name AND `tabBOM`.docstatus < 2
|
||||
AND `tabBOM`.rm_cost_as_per = 'Price List'
|
||||
""")
|
||||
|
||||
for d in frappe.db.sql("""
|
||||
SELECT
|
||||
bom.creation, bom.name, bom.price_list_currency as currency,
|
||||
company.default_currency as company_currency
|
||||
FROM
|
||||
`tabBOM` as bom, `tabCompany` as company
|
||||
WHERE
|
||||
bom.company = company.name AND bom.rm_cost_as_per = 'Price List' AND
|
||||
bom.price_list_currency != company.default_currency AND bom.docstatus < 2""", as_dict=1):
|
||||
plc_conversion_rate = get_exchange_rate(d.currency,
|
||||
d.company_currency, getdate(d.creation), "for_buying")
|
||||
|
||||
frappe.db.set_value("BOM", d.name, "plc_conversion_rate", plc_conversion_rate)
|
Loading…
x
Reference in New Issue
Block a user