Merge branch 'bom_currency' into develop
This commit is contained in:
commit
2967d7ed01
@ -5,7 +5,10 @@ frappe.provide("erpnext.bom");
|
||||
|
||||
frappe.ui.form.on("BOM", {
|
||||
setup: function(frm) {
|
||||
frm.add_fetch('buying_price_list', 'currency', 'currency');
|
||||
frm.add_fetch("item", "description", "description");
|
||||
frm.add_fetch("item", "image", "image");
|
||||
frm.add_fetch("item", "item_name", "item_name");
|
||||
frm.add_fetch("item", "stock_uom", "uom");
|
||||
|
||||
frm.set_query("bom_no", "items", function() {
|
||||
return {
|
||||
@ -23,6 +26,38 @@ frappe.ui.form.on("BOM", {
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("item", function() {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.item_query"
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("project", function() {
|
||||
return{
|
||||
filters:[
|
||||
['Project', 'status', 'not in', 'Completed, Cancelled']
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("item_code", "items", function() {
|
||||
return {
|
||||
query: "erpnext.controllers.queries.item_query",
|
||||
filters: [["Item", "name", "!=", cur_frm.doc.item]]
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("bom_no", "items", function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
return {
|
||||
filters: {
|
||||
'item': d.item_code,
|
||||
'is_active': 1,
|
||||
'docstatus': 1
|
||||
}
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
onload_post_render: function(frm) {
|
||||
@ -69,14 +104,14 @@ frappe.ui.form.on("BOM", {
|
||||
});
|
||||
|
||||
erpnext.bom.BomController = erpnext.TransactionController.extend({
|
||||
conversion_rate: function(doc, cdt, cdn) {
|
||||
conversion_rate: function(doc) {
|
||||
if(this.frm.doc.currency === this.get_company_currency()) {
|
||||
this.frm.set_value("conversion_rate", 1.0);
|
||||
} else {
|
||||
erpnext.bom.update_cost(doc);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
item_code: function(doc, cdt, cdn){
|
||||
var scrap_items = false;
|
||||
var child = locals[cdt][cdn];
|
||||
@ -90,39 +125,34 @@ erpnext.bom.BomController = erpnext.TransactionController.extend({
|
||||
|
||||
get_bom_material_detail(doc, cdt, cdn, scrap_items);
|
||||
},
|
||||
conversion_factor: function(doc, cdt, cdn, dont_fetch_price_list_rate) {
|
||||
conversion_factor: function(doc, cdt, 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));
|
||||
refresh_field("stock_qty", item.name, item.parentfield);
|
||||
this.toggle_conversion_factor(item);
|
||||
this.frm.events.update_cost(this.frm);
|
||||
}
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
$.extend(cur_frm.cscript, new erpnext.bom.BomController({frm: cur_frm}));
|
||||
|
||||
cur_frm.add_fetch("item", "description", "description");
|
||||
cur_frm.add_fetch("item", "image", "image");
|
||||
cur_frm.add_fetch("item", "item_name", "item_name");
|
||||
cur_frm.add_fetch("item", "stock_uom", "uom");
|
||||
|
||||
|
||||
cur_frm.cscript.hour_rate = function(doc, dt, dn) {
|
||||
cur_frm.cscript.hour_rate = function(doc) {
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
};
|
||||
|
||||
cur_frm.cscript.time_in_mins = cur_frm.cscript.hour_rate;
|
||||
|
||||
cur_frm.cscript.bom_no = function(doc, cdt, cdn) {
|
||||
get_bom_material_detail(doc, cdt, cdn, false);
|
||||
}
|
||||
};
|
||||
|
||||
cur_frm.cscript.is_default = function(doc) {
|
||||
if (doc.is_default) cur_frm.set_value("is_active", 1);
|
||||
}
|
||||
};
|
||||
|
||||
var get_bom_material_detail= function(doc, cdt, cdn, scrap_items) {
|
||||
var d = locals[cdt][cdn];
|
||||
@ -141,6 +171,7 @@ var get_bom_material_detail= function(doc, cdt, cdn, scrap_items) {
|
||||
$.extend(d, r.message);
|
||||
refresh_field("items");
|
||||
refresh_field("scrap_items");
|
||||
|
||||
doc = locals[doc.doctype][doc.name];
|
||||
erpnext.bom.calculate_rm_cost(doc);
|
||||
erpnext.bom.calculate_scrap_materials_cost(doc);
|
||||
@ -149,13 +180,13 @@ var get_bom_material_detail= function(doc, cdt, cdn, scrap_items) {
|
||||
freeze: true
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cur_frm.cscript.qty = function(doc, cdt, cdn) {
|
||||
cur_frm.cscript.qty = function(doc) {
|
||||
erpnext.bom.calculate_rm_cost(doc);
|
||||
erpnext.bom.calculate_scrap_materials_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
};
|
||||
|
||||
cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
@ -173,14 +204,14 @@ cur_frm.cscript.rate = function(doc, cdt, cdn) {
|
||||
erpnext.bom.calculate_scrap_materials_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.bom.update_cost = function(doc) {
|
||||
erpnext.bom.calculate_op_cost(doc);
|
||||
erpnext.bom.calculate_rm_cost(doc);
|
||||
erpnext.bom.calculate_scrap_materials_cost(doc);
|
||||
erpnext.bom.calculate_total(doc);
|
||||
}
|
||||
};
|
||||
|
||||
erpnext.bom.calculate_op_cost = function(doc) {
|
||||
var op = doc.operations || [];
|
||||
@ -189,7 +220,7 @@ erpnext.bom.calculate_op_cost = function(doc) {
|
||||
|
||||
for(var i=0;i<op.length;i++) {
|
||||
var operating_cost = flt(flt(op[i].hour_rate) * flt(op[i].time_in_mins) / 60, 2);
|
||||
var base_operating_cost = flt(flt(op[i].base_hour_rate) * flt(op[i].time_in_mins) / 60, 2);
|
||||
var base_operating_cost = flt(operating_cost * doc.conversion_rate, 2);
|
||||
frappe.model.set_value('BOM Operation',op[i].name, "operating_cost", operating_cost);
|
||||
frappe.model.set_value('BOM Operation',op[i].name, "base_operating_cost", base_operating_cost);
|
||||
|
||||
@ -197,7 +228,7 @@ erpnext.bom.calculate_op_cost = function(doc) {
|
||||
doc.base_operating_cost += base_operating_cost;
|
||||
}
|
||||
refresh_field(['operating_cost', 'base_operating_cost']);
|
||||
}
|
||||
};
|
||||
|
||||
// rm : raw material
|
||||
erpnext.bom.calculate_rm_cost = function(doc) {
|
||||
@ -206,19 +237,23 @@ erpnext.bom.calculate_rm_cost = function(doc) {
|
||||
var base_total_rm_cost = 0;
|
||||
for(var i=0;i<rm.length;i++) {
|
||||
var amount = flt(rm[i].rate) * flt(rm[i].qty);
|
||||
var base_amount = flt(rm[i].rate) * flt(doc.conversion_rate) * flt(rm[i].qty);
|
||||
frappe.model.set_value('BOM Item', rm[i].name, 'base_rate', flt(rm[i].rate) * flt(doc.conversion_rate))
|
||||
frappe.model.set_value('BOM Item', rm[i].name, 'amount', amount)
|
||||
frappe.model.set_value('BOM Item', rm[i].name, 'qty_consumed_per_unit', flt(rm[i].qty)/flt(doc.quantity))
|
||||
frappe.model.set_value('BOM Item', rm[i].name, 'base_amount', base_amount)
|
||||
var base_amount = amount * flt(doc.conversion_rate);
|
||||
|
||||
frappe.model.set_value('BOM Item', rm[i].name, 'base_rate',
|
||||
flt(rm[i].rate) * flt(doc.conversion_rate));
|
||||
frappe.model.set_value('BOM Item', rm[i].name, 'amount', amount);
|
||||
frappe.model.set_value('BOM Item', rm[i].name, 'base_amount', base_amount);
|
||||
frappe.model.set_value('BOM Item', rm[i].name,
|
||||
'qty_consumed_per_unit', flt(rm[i].stock_qty)/flt(doc.quantity));
|
||||
|
||||
total_rm_cost += amount;
|
||||
base_total_rm_cost += base_amount;
|
||||
}
|
||||
cur_frm.set_value("raw_material_cost", total_rm_cost);
|
||||
cur_frm.set_value("base_raw_material_cost", base_total_rm_cost);
|
||||
}
|
||||
};
|
||||
|
||||
//sm : scrap material
|
||||
// sm : scrap material
|
||||
erpnext.bom.calculate_scrap_materials_cost = function(doc) {
|
||||
var sm = doc.scrap_items || [];
|
||||
var total_sm_cost = 0;
|
||||
@ -226,64 +261,34 @@ erpnext.bom.calculate_scrap_materials_cost = function(doc) {
|
||||
|
||||
for(var i=0;i<sm.length;i++) {
|
||||
var base_rate = flt(sm[i].rate) * flt(doc.conversion_rate);
|
||||
var amount = flt(sm[i].rate) * flt(sm[i].qty);
|
||||
var base_amount = flt(sm[i].rate) * flt(sm[i].qty) * flt(doc.conversion_rate);
|
||||
var amount = flt(sm[i].rate) * flt(sm[i].stock_qty);
|
||||
var base_amount = amount * flt(doc.conversion_rate);
|
||||
|
||||
frappe.model.set_value('BOM Scrap Item',sm[i].name, 'base_rate', base_rate);
|
||||
frappe.model.set_value('BOM Scrap Item',sm[i].name, 'amount', amount);
|
||||
frappe.model.set_value('BOM Scrap Item',sm[i].name, 'base_amount', base_amount);
|
||||
|
||||
|
||||
total_sm_cost += amount;
|
||||
base_total_sm_cost += base_amount;
|
||||
}
|
||||
|
||||
|
||||
cur_frm.set_value("scrap_material_cost", total_sm_cost);
|
||||
cur_frm.set_value("base_scrap_material_cost", base_total_sm_cost);
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate Total Cost
|
||||
erpnext.bom.calculate_total = function(doc) {
|
||||
var total_cost = flt(doc.operating_cost) + flt(doc.raw_material_cost) - flt(doc.scrap_material_cost);
|
||||
var base_total_cost = flt(doc.base_operating_cost) + flt(doc.base_raw_material_cost) - flt(doc.base_scrap_material_cost);
|
||||
var base_total_cost = flt(doc.base_operating_cost) + flt(doc.base_raw_material_cost)
|
||||
- flt(doc.base_scrap_material_cost);
|
||||
|
||||
cur_frm.set_value("total_cost", total_cost);
|
||||
cur_frm.set_value("base_total_cost", base_total_cost);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
cur_frm.fields_dict['item'].get_query = function(doc) {
|
||||
return{
|
||||
query: "erpnext.controllers.queries.item_query"
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['project'].get_query = function(doc, dt, dn) {
|
||||
return{
|
||||
filters:[
|
||||
['Project', 'status', 'not in', 'Completed, Cancelled']
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['items'].grid.get_field('item_code').get_query = function(doc) {
|
||||
return{
|
||||
query: "erpnext.controllers.queries.item_query",
|
||||
filters: [["Item", "name", "!=", cur_frm.doc.item]]
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.fields_dict['items'].grid.get_field('bom_no').get_query = function(doc, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
return{
|
||||
filters:{
|
||||
'item': d.item_code,
|
||||
'is_active': 1,
|
||||
'docstatus': 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.validate = function(doc, dt, dn) {
|
||||
erpnext.bom.update_cost(doc)
|
||||
}
|
||||
cur_frm.cscript.validate = function(doc) {
|
||||
erpnext.bom.update_cost(doc);
|
||||
};
|
||||
|
||||
frappe.ui.form.on("BOM Operation", "operation", function(frm, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
@ -304,7 +309,7 @@ frappe.ui.form.on("BOM Operation", "operation", function(frm, cdt, cdn) {
|
||||
frappe.model.set_value(d.doctype, d.name, "workstation", data.message.workstation);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
frappe.ui.form.on("BOM Operation", "workstation", function(frm, cdt, cdn) {
|
||||
@ -317,21 +322,22 @@ frappe.ui.form.on("BOM Operation", "workstation", function(frm, cdt, cdn) {
|
||||
name: d.workstation
|
||||
},
|
||||
callback: function (data) {
|
||||
frappe.model.set_value(d.doctype, d.name, "hour_rate", data.message.hour_rate);
|
||||
frappe.model.set_value(d.doctype, d.name, "base_hour_rate", flt(data.message.hour_rate) * flt(frm.doc.conversion_rate));
|
||||
frappe.model.set_value(d.doctype, d.name, "base_hour_rate", data.message.hour_rate);
|
||||
frappe.model.set_value(d.doctype, d.name, "hour_rate",
|
||||
flt(flt(data.message.hour_rate) / flt(frm.doc.conversion_rate)), 2);
|
||||
|
||||
erpnext.bom.calculate_op_cost(frm.doc);
|
||||
erpnext.bom.calculate_total(frm.doc);
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
frappe.ui.form.on("BOM Item", "qty", function(frm, cdt, cdn) {
|
||||
var d = locals[cdt][cdn];
|
||||
d.stock_qty = d.qty * d.conversion_factor;
|
||||
refresh_field("items");
|
||||
refresh_field("stock_qty", d.name, d.parentfield);
|
||||
});
|
||||
|
||||
|
||||
|
||||
frappe.ui.form.on("BOM Operation", "operations_remove", function(frm) {
|
||||
erpnext.bom.calculate_op_cost(frm.doc);
|
||||
erpnext.bom.calculate_total(frm.doc);
|
||||
@ -344,7 +350,7 @@ frappe.ui.form.on("BOM Item", "items_remove", function(frm) {
|
||||
|
||||
var toggle_operations = function(frm) {
|
||||
frm.toggle_display("operations_section", cint(frm.doc.with_operations) == 1);
|
||||
}
|
||||
};
|
||||
|
||||
frappe.ui.form.on("BOM", "with_operations", function(frm) {
|
||||
if(!cint(frm.doc.with_operations)) {
|
||||
@ -355,4 +361,4 @@ frappe.ui.form.on("BOM", "with_operations", function(frm) {
|
||||
|
||||
cur_frm.cscript.image = function() {
|
||||
refresh_field("image_view");
|
||||
}
|
||||
};
|
||||
|
@ -322,6 +322,37 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1051,37 +1082,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Company",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 1,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1322,7 +1322,7 @@
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"fieldname": "section_break0",
|
||||
|
@ -2,7 +2,7 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import frappe, erpnext
|
||||
from frappe.utils import cint, cstr, flt
|
||||
from frappe import _
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
@ -41,16 +41,12 @@ class BOM(WebsiteGenerator):
|
||||
self.name = 'BOM-' + self.item + ('-%.3i' % idx)
|
||||
|
||||
def validate(self):
|
||||
# if not self.route:
|
||||
self.route = frappe.scrub(self.name).replace('_', '-')
|
||||
self.clear_operations()
|
||||
self.validate_main_item()
|
||||
self.validate_currency()
|
||||
self.set_conversion_rate()
|
||||
|
||||
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
||||
validate_uom_is_integer(self, "stock_uom", "stock_qty", "BOM Item")
|
||||
|
||||
self.validate_uom_is_interger()
|
||||
self.update_stock_qty()
|
||||
self.set_bom_material_details()
|
||||
self.validate_materials()
|
||||
@ -96,14 +92,18 @@ class BOM(WebsiteGenerator):
|
||||
|
||||
def set_bom_material_details(self):
|
||||
for item in self.get("items"):
|
||||
ret = self.get_bom_material_detail({"item_code": item.item_code, "item_name": item.item_name, "bom_no": item.bom_no,
|
||||
"stock_qty": item.stock_qty})
|
||||
self.validate_bom_currecny(item)
|
||||
|
||||
ret = self.get_bom_material_detail({
|
||||
"item_code": item.item_code,
|
||||
"item_name": item.item_name,
|
||||
"bom_no": item.bom_no,
|
||||
"stock_qty": item.stock_qty
|
||||
})
|
||||
for r in ret:
|
||||
if not item.get(r):
|
||||
item.set(r, ret[r])
|
||||
|
||||
self.validate_bom_currecny(item)
|
||||
|
||||
def get_bom_material_detail(self, args=None):
|
||||
""" Get raw material details like uom, desc and rate"""
|
||||
if not args:
|
||||
@ -126,17 +126,19 @@ class BOM(WebsiteGenerator):
|
||||
'image' : item and args['image'] or '',
|
||||
'stock_uom' : item and args['stock_uom'] or '',
|
||||
'uom' : item and args['stock_uom'] or '',
|
||||
'conversion_factor' : 1,
|
||||
'conversion_factor': 1,
|
||||
'bom_no' : args['bom_no'],
|
||||
'rate' : rate,
|
||||
'rate' : rate / self.conversion_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 if self.company_currency() == self.currency else rate * self.conversion_rate
|
||||
'base_rate' : rate
|
||||
}
|
||||
return ret_item
|
||||
|
||||
def validate_bom_currecny(self, item):
|
||||
if item.get('bom_no') and frappe.db.get_value('BOM', item.get('bom_no'), 'currency') != self.currency:
|
||||
frappe.throw(_("Row {0}: Currency of the BOM #{1} should be equal to the selected currency {2}").format(item.idx, item.bom_no, self.currency))
|
||||
frappe.throw(_("Row {0}: Currency of the BOM #{1} should be equal to the selected currency {2}")
|
||||
.format(item.idx, item.bom_no, self.currency))
|
||||
|
||||
def get_rm_rate(self, arg):
|
||||
""" Get raw material rate as per selected method, if bom exists takes bom cost """
|
||||
@ -148,17 +150,21 @@ class BOM(WebsiteGenerator):
|
||||
if self.rm_cost_as_per == 'Valuation Rate':
|
||||
rate = self.get_valuation_rate(arg)
|
||||
elif self.rm_cost_as_per == 'Last Purchase Rate':
|
||||
rate = arg['last_purchase_rate']
|
||||
rate = arg['last_purchase_rate'] \
|
||||
or frappe.db.get_value("Item", arg['item_code'], "last_purchase_rate")
|
||||
elif self.rm_cost_as_per == "Price List":
|
||||
if not self.buying_price_list:
|
||||
frappe.throw(_("Please select Price List"))
|
||||
rate = frappe.db.get_value("Item Price", {"price_list": self.buying_price_list,
|
||||
"item_code": arg["item_code"]}, "price_list_rate") or 0
|
||||
rate = frappe.db.get_value("Item Price",
|
||||
{"price_list": self.buying_price_list, "item_code": arg["item_code"]}, "price_list_rate")
|
||||
price_list_currency = frappe.db.get_value("Price List", self.buying_price_list, "currency")
|
||||
if price_list_currency != self.company_currency():
|
||||
rate = flt(rate * self.conversion_rate)
|
||||
|
||||
if arg['bom_no'] and (not rate or self.set_rate_of_sub_assembly_item_based_on_bom):
|
||||
rate = self.get_bom_unitcost(arg['bom_no'])
|
||||
|
||||
return rate
|
||||
return flt(rate)
|
||||
|
||||
def update_cost(self, update_parent=True, from_child_bom=False):
|
||||
if self.docstatus == 2:
|
||||
@ -167,10 +173,9 @@ class BOM(WebsiteGenerator):
|
||||
existing_bom_cost = self.total_cost
|
||||
|
||||
for d in self.get("items"):
|
||||
rate = self.get_bom_material_detail({'item_code': d.item_code, 'bom_no': d.bom_no,
|
||||
'stock_qty': d.stock_qty})["rate"]
|
||||
rate = self.get_rm_rate({"item_code": d.item_code, "bom_no": d.bom_no})
|
||||
if rate:
|
||||
d.rate = rate
|
||||
d.rate = rate * flt(d.conversion_factor) / flt(self.conversion_rate)
|
||||
|
||||
if self.docstatus == 1:
|
||||
self.flags.ignore_validate_update_after_submit = True
|
||||
@ -190,7 +195,7 @@ class BOM(WebsiteGenerator):
|
||||
frappe.msgprint(_("Cost Updated"))
|
||||
|
||||
def get_bom_unitcost(self, bom_no):
|
||||
bom = frappe.db.sql("""select name, total_cost/quantity as unit_cost from `tabBOM`
|
||||
bom = frappe.db.sql("""select name, base_total_cost/quantity as unit_cost from `tabBOM`
|
||||
where is_active = 1 and name = %s""", bom_no, as_dict=1)
|
||||
return bom and bom[0]['unit_cost'] or 0
|
||||
|
||||
@ -253,14 +258,14 @@ class BOM(WebsiteGenerator):
|
||||
frappe.throw(_("Quantity should be greater than 0"))
|
||||
|
||||
def validate_currency(self):
|
||||
if self.rm_cost_as_per == 'Price List' and \
|
||||
frappe.db.get_value('Price List', self.buying_price_list, 'currency') != self.currency:
|
||||
frappe.throw(_("Currency of the price list {0} is not similar with the selected currency {1}").format(self.buying_price_list, self.currency))
|
||||
if self.rm_cost_as_per == 'Price List':
|
||||
price_list_currency = frappe.db.get_value('Price List', self.buying_price_list, 'currency')
|
||||
if price_list_currency not in (self.currency, self.company_currency()):
|
||||
frappe.throw(_("Currency of the price list {0} must be {1} or {2}")
|
||||
.format(self.buying_price_list, self.currency, self.company_currency()))
|
||||
|
||||
|
||||
def update_stock_qty(self):
|
||||
for m in self.get('items'):
|
||||
|
||||
if not m.conversion_factor:
|
||||
m.conversion_factor = flt(get_conversion_factor(m.item_code, m.uom)['conversion_factor'])
|
||||
if m.uom and m.qty:
|
||||
@ -268,10 +273,17 @@ class BOM(WebsiteGenerator):
|
||||
if not m.uom and m.stock_uom:
|
||||
m.uom = m.stock_uom
|
||||
m.qty = m.stock_qty
|
||||
|
||||
|
||||
|
||||
def validate_uom_is_interger(self):
|
||||
from erpnext.utilities.transaction_base import validate_uom_is_integer
|
||||
validate_uom_is_integer(self, "uom", "qty", "BOM Item")
|
||||
validate_uom_is_integer(self, "stock_uom", "stock_qty", "BOM Item")
|
||||
|
||||
def set_conversion_rate(self):
|
||||
self.conversion_rate = get_exchange_rate(self.currency, self.company_currency())
|
||||
if self.currency == self.company_currency():
|
||||
self.conversion_rate = 1
|
||||
elif self.conversion_rate == 1 or flt(self.conversion_rate) <= 0:
|
||||
self.conversion_rate = get_exchange_rate(self.currency, self.company_currency())
|
||||
|
||||
def validate_materials(self):
|
||||
""" Validate raw material entries """
|
||||
@ -289,7 +301,7 @@ class BOM(WebsiteGenerator):
|
||||
for m in self.get('items'):
|
||||
if m.bom_no:
|
||||
validate_bom_no(m.item_code, m.bom_no)
|
||||
if flt(m.stock_qty) <= 0:
|
||||
if flt(m.qty) <= 0:
|
||||
frappe.throw(_("Quantity required for Item {0} in row {1}").format(m.item_code, m.idx))
|
||||
check_list.append(m)
|
||||
|
||||
@ -361,12 +373,13 @@ class BOM(WebsiteGenerator):
|
||||
for d in self.get('operations'):
|
||||
if d.workstation:
|
||||
if not d.hour_rate:
|
||||
d.hour_rate = flt(frappe.db.get_value("Workstation", d.workstation, "hour_rate"))
|
||||
hour_rate = flt(frappe.db.get_value("Workstation", d.workstation, "hour_rate"))
|
||||
d.hour_rate = hour_rate / flt(self.conversion_rate)
|
||||
|
||||
if d.hour_rate and d.time_in_mins:
|
||||
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
|
||||
d.base_hour_rate = flt(d.hour_rate) * flt(self.conversion_rate)
|
||||
d.base_operating_cost = flt(d.base_hour_rate) * flt(d.time_in_mins) / 60.0
|
||||
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
|
||||
d.base_operating_cost = flt(d.operating_cost) * flt(self.conversion_rate)
|
||||
|
||||
self.operating_cost += flt(d.operating_cost)
|
||||
self.base_operating_cost += flt(d.base_operating_cost)
|
||||
@ -378,9 +391,11 @@ class BOM(WebsiteGenerator):
|
||||
|
||||
for d in self.get('items'):
|
||||
d.base_rate = flt(d.rate) * flt(self.conversion_rate)
|
||||
d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d))
|
||||
d.amount = flt(d.rate, d.precision("rate")) * flt(d.qty, d.precision("qty"))
|
||||
d.base_amount = d.amount * flt(self.conversion_rate)
|
||||
d.qty_consumed_per_unit = flt(d.stock_qty, self.precision("stock_qty", d)) / flt(self.quantity, self.precision("quantity"))
|
||||
d.qty_consumed_per_unit = flt(d.stock_qty, d.precision("stock_qty")) \
|
||||
/ flt(self.quantity, self.precision("quantity"))
|
||||
|
||||
total_rm_cost += d.amount
|
||||
base_total_rm_cost += d.base_amount
|
||||
|
||||
@ -394,7 +409,7 @@ class BOM(WebsiteGenerator):
|
||||
|
||||
for d in self.get('scrap_items'):
|
||||
d.base_rate = d.rate * self.conversion_rate
|
||||
d.amount = flt(d.rate, self.precision("rate", d)) * flt(d.stock_qty, self.precision("stock_qty", d))
|
||||
d.amount = flt(d.rate, d.precision("rate")) * flt(d.stock_qty, d.precision("stock_qty"))
|
||||
d.base_amount = d.amount * self.conversion_rate
|
||||
total_sm_cost += d.amount
|
||||
base_total_sm_cost += d.base_amount
|
||||
@ -421,12 +436,12 @@ class BOM(WebsiteGenerator):
|
||||
'description' : d.description,
|
||||
'image' : d.image,
|
||||
'stock_uom' : d.stock_uom,
|
||||
'stock_qty' : flt(d.stock_qty),
|
||||
'stock_qty' : flt(d.stock_qty),
|
||||
'rate' : d.base_rate,
|
||||
}))
|
||||
|
||||
def company_currency(self):
|
||||
return frappe.db.get_value('Company', self.company, 'default_currency')
|
||||
return erpnext.get_company_currency(self.company)
|
||||
|
||||
def add_to_cur_exploded_items(self, args):
|
||||
if self.cur_exploded_items.get(args.item_code):
|
||||
@ -459,6 +474,7 @@ class BOM(WebsiteGenerator):
|
||||
"Add items to Flat BOM table"
|
||||
frappe.db.sql("""delete from `tabBOM Explosion Item` where parent=%s""", self.name)
|
||||
self.set('exploded_items', [])
|
||||
|
||||
for d in sorted(self.cur_exploded_items, key=itemgetter(0)):
|
||||
ch = self.append('exploded_items', {})
|
||||
for i in self.cur_exploded_items[d].keys():
|
||||
|
@ -14,14 +14,16 @@ test_records = frappe.get_test_records('BOM')
|
||||
class TestBOM(unittest.TestCase):
|
||||
def test_get_items(self):
|
||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||
items_dict = get_bom_items_as_dict(bom=get_default_bom(), company="_Test Company", qty=1, fetch_exploded=0)
|
||||
items_dict = get_bom_items_as_dict(bom=get_default_bom(),
|
||||
company="_Test Company", qty=1, fetch_exploded=0)
|
||||
self.assertTrue(test_records[2]["items"][0]["item_code"] in items_dict)
|
||||
self.assertTrue(test_records[2]["items"][1]["item_code"] in items_dict)
|
||||
self.assertEquals(len(items_dict.values()), 2)
|
||||
|
||||
def test_get_items_exploded(self):
|
||||
from erpnext.manufacturing.doctype.bom.bom import get_bom_items_as_dict
|
||||
items_dict = get_bom_items_as_dict(bom=get_default_bom(), company="_Test Company", qty=1, fetch_exploded=1)
|
||||
items_dict = get_bom_items_as_dict(bom=get_default_bom(),
|
||||
company="_Test Company", qty=1, fetch_exploded=1)
|
||||
self.assertTrue(test_records[2]["items"][0]["item_code"] in items_dict)
|
||||
self.assertFalse(test_records[2]["items"][1]["item_code"] in items_dict)
|
||||
self.assertTrue(test_records[0]["items"][0]["item_code"] in items_dict)
|
||||
@ -75,5 +77,50 @@ class TestBOM(unittest.TestCase):
|
||||
where item_code='_Test Item 2' and docstatus=1""", as_dict=1):
|
||||
self.assertEqual(d.rate, rm_rate + 10)
|
||||
|
||||
def test_bom_cost(self):
|
||||
bom = frappe.copy_doc(test_records[2])
|
||||
bom.insert()
|
||||
|
||||
# test amounts in selected currency
|
||||
self.assertEqual(bom.operating_cost, 100)
|
||||
self.assertEqual(bom.raw_material_cost, 8000)
|
||||
self.assertEqual(bom.total_cost, 8100)
|
||||
|
||||
# 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)
|
||||
|
||||
def test_bom_cost_multi_uom_multi_currency(self):
|
||||
for item_code, rate in (("_Test Item", 3600), ("_Test Item Home Desktop Manufactured", 3000)):
|
||||
item_price = frappe.new_doc("Item Price")
|
||||
item_price.price_list = "_Test Price List"
|
||||
item_price.item_code = item_code
|
||||
item_price.price_list_rate = rate
|
||||
item_price.insert()
|
||||
|
||||
bom = frappe.copy_doc(test_records[2])
|
||||
bom.rm_cost_as_per = "Price List"
|
||||
bom.buying_price_list = "_Test Price List"
|
||||
bom.items[0].uom = "_Test UOM 1"
|
||||
bom.items[0].conversion_factor = 5
|
||||
bom.insert()
|
||||
|
||||
bom.update_cost()
|
||||
|
||||
# test amounts in selected currency
|
||||
self.assertEqual(bom.items[0].rate, 300)
|
||||
self.assertEqual(bom.items[1].rate, 50)
|
||||
self.assertEqual(bom.operating_cost, 100)
|
||||
self.assertEqual(bom.raw_material_cost, 450)
|
||||
self.assertEqual(bom.total_cost, 550)
|
||||
|
||||
# test amounts in selected currency
|
||||
self.assertEqual(bom.items[0].base_rate, 18000)
|
||||
self.assertEqual(bom.items[1].base_rate, 3000)
|
||||
self.assertEqual(bom.base_operating_cost, 6000)
|
||||
self.assertEqual(bom.base_raw_material_cost, 27000)
|
||||
self.assertEqual(bom.base_total_cost, 33000)
|
||||
|
||||
def get_default_bom(item_code="_Test FG Item 2"):
|
||||
return frappe.db.get_value("BOM", {"item": item_code, "is_active": 1, "is_default": 1})
|
||||
|
@ -6,8 +6,9 @@
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Serialized Item With Series",
|
||||
"parentfield": "items",
|
||||
"stock_qty": 1.0,
|
||||
"qty": 1.0,
|
||||
"rate": 5000.0,
|
||||
"uom": "_Test UOM",
|
||||
"stock_uom": "_Test UOM",
|
||||
"source_warehouse": "_Test Warehouse - _TC"
|
||||
},
|
||||
@ -16,8 +17,9 @@
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item 2",
|
||||
"parentfield": "items",
|
||||
"stock_qty": 2.0,
|
||||
"qty": 2.0,
|
||||
"rate": 1000.0,
|
||||
"uom": "_Test UOM",
|
||||
"stock_uom": "_Test UOM",
|
||||
"source_warehouse": "_Test Warehouse - _TC"
|
||||
}
|
||||
@ -34,9 +36,9 @@
|
||||
"scrap_items":[
|
||||
{
|
||||
"amount": 2000.0,
|
||||
"doctype": "BOM Item",
|
||||
"doctype": "BOM Scrap Item",
|
||||
"item_code": "_Test Item Home Desktop 100",
|
||||
"parentfield": "items",
|
||||
"parentfield": "scrap_items",
|
||||
"stock_qty": 1.0,
|
||||
"rate": 2000.0,
|
||||
"stock_uom": "_Test UOM"
|
||||
@ -48,8 +50,9 @@
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item",
|
||||
"parentfield": "items",
|
||||
"stock_qty": 1.0,
|
||||
"qty": 1.0,
|
||||
"rate": 5000.0,
|
||||
"uom": "_Test UOM",
|
||||
"stock_uom": "_Test UOM",
|
||||
"source_warehouse": "_Test Warehouse - _TC"
|
||||
},
|
||||
@ -58,8 +61,9 @@
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item Home Desktop 100",
|
||||
"parentfield": "items",
|
||||
"stock_qty": 2.0,
|
||||
"qty": 2.0,
|
||||
"rate": 1000.0,
|
||||
"uom": "_Test UOM",
|
||||
"stock_uom": "_Test UOM",
|
||||
"source_warehouse": "_Test Warehouse - _TC"
|
||||
}
|
||||
@ -78,6 +82,7 @@
|
||||
"operation": "_Test Operation 1",
|
||||
"description": "_Test",
|
||||
"workstation": "_Test Workstation 1",
|
||||
"hour_rate": 100,
|
||||
"time_in_mins": 60,
|
||||
"operating_cost": 100
|
||||
}
|
||||
@ -88,19 +93,21 @@
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item",
|
||||
"parentfield": "items",
|
||||
"stock_qty": 1.0,
|
||||
"qty": 1.0,
|
||||
"rate": 5000.0,
|
||||
"uom": "_Test UOM",
|
||||
"stock_uom": "_Test UOM",
|
||||
"source_warehouse": "_Test Warehouse - _TC"
|
||||
},
|
||||
{
|
||||
"amount": 2000.0,
|
||||
"amount": 3000.0,
|
||||
"bom_no": "BOM-_Test Item Home Desktop Manufactured-001",
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item Home Desktop Manufactured",
|
||||
"parentfield": "items",
|
||||
"stock_qty": 3.0,
|
||||
"qty": 3.0,
|
||||
"rate": 1000.0,
|
||||
"uom": "_Test UOM",
|
||||
"stock_uom": "_Test UOM",
|
||||
"source_warehouse": "_Test Warehouse - _TC"
|
||||
}
|
||||
@ -110,6 +117,8 @@
|
||||
"is_active": 1,
|
||||
"is_default": 1,
|
||||
"currency": "USD",
|
||||
"conversion_rate": 60,
|
||||
"company": "_Test Company",
|
||||
"item": "_Test FG Item 2",
|
||||
"quantity": 1.0,
|
||||
"with_operations": 1
|
||||
@ -130,8 +139,9 @@
|
||||
"doctype": "BOM Item",
|
||||
"item_code": "_Test Item",
|
||||
"parentfield": "items",
|
||||
"stock_qty": 2.0,
|
||||
"qty": 2.0,
|
||||
"rate": 3000.0,
|
||||
"uom": "_Test UOM",
|
||||
"stock_uom": "_Test UOM",
|
||||
"source_warehouse": "_Test Warehouse - _TC"
|
||||
}
|
||||
|
@ -171,7 +171,7 @@
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible": 1,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_5",
|
||||
"fieldtype": "Section Break",
|
||||
@ -182,6 +182,7 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
@ -373,7 +374,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -404,7 +405,7 @@
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -464,7 +465,39 @@
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Stock UOM",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -505,8 +538,8 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"fieldname": "rate_amount_section",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
@ -514,16 +547,45 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Stock UOM",
|
||||
"label": "Rate & Amount",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "stock_uom",
|
||||
"oldfieldtype": "Data",
|
||||
"options": "UOM",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fieldname": "rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Rate",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
@ -537,8 +599,7 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "See \"Rate Of Materials Based On\" in Costing Section",
|
||||
"fieldname": "rate",
|
||||
"fieldname": "base_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
@ -547,17 +608,47 @@
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Rate",
|
||||
"label": "Basic Rate (Company Currency)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "currency",
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_21",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
@ -596,37 +687,6 @@
|
||||
"unique": 0,
|
||||
"width": "150px"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "base_rate",
|
||||
"fieldtype": "Currency",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Basic Rate (Company Currency)",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Company:company:default_currency",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -700,7 +760,7 @@
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Scrap %",
|
||||
"length": 0,
|
||||
@ -760,7 +820,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-07-04 17:42:37.218408",
|
||||
"modified": "2017-08-18 16:22:46.078661",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Manufacturing",
|
||||
"name": "BOM Item",
|
||||
|
@ -437,3 +437,4 @@ erpnext.patches.v8_7.fix_purchase_receipt_status
|
||||
erpnext.patches.v8_6.rename_bom_update_tool
|
||||
erpnext.patches.v8_9.add_setup_progress_actions
|
||||
erpnext.patches.v8_9.rename_company_sales_target_field
|
||||
erpnext.patches.v8_8.set_bom_rate_as_per_uom
|
0
erpnext/patches/v8_8/__init__.py
Normal file
0
erpnext/patches/v8_8/__init__.py
Normal file
13
erpnext/patches/v8_8/set_bom_rate_as_per_uom.py
Normal file
13
erpnext/patches/v8_8/set_bom_rate_as_per_uom.py
Normal file
@ -0,0 +1,13 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.db.sql("""
|
||||
update `tabBOM Item`
|
||||
set rate = rate * conversion_factor
|
||||
where uom != stock_uom and docstatus < 2
|
||||
and conversion_factor not in (0, 1)
|
||||
""")
|
Loading…
Reference in New Issue
Block a user