mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-03 20:29:09 +00:00
updates in manufacturing module
This commit is contained in:
@@ -61,7 +61,7 @@ cur_frm.fields_dict["bom_operations"].grid.on_row_delete = function(cdt, cdn){
|
||||
|
||||
cur_frm.cscript.item = function(doc, dt, dn) {
|
||||
if (doc.item) {
|
||||
get_server_fields('get_item_details',doc.item,'',doc,dt,dn,1);
|
||||
get_server_fields('get_item_details', doc.item, '', doc, dt, dn, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,10 @@ cur_frm.cscript.bom_no = function(doc, cdt, cdn) {
|
||||
get_bom_material_detail(doc, cdt, cdn);
|
||||
}
|
||||
|
||||
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) {
|
||||
var d = locals[cdt][cdn];
|
||||
if (d.item_code) {
|
||||
|
||||
@@ -20,7 +20,7 @@ from webnotes.utils import cint, cstr, flt, now, nowdate
|
||||
from webnotes.model.doc import Document, addchild
|
||||
from webnotes.model.wrapper import getlist
|
||||
from webnotes.model.code import get_obj
|
||||
from webnotes import msgprint
|
||||
from webnotes import msgprint, _
|
||||
|
||||
sql = webnotes.conn.sql
|
||||
|
||||
@@ -47,28 +47,24 @@ class DocType:
|
||||
|
||||
def on_update(self):
|
||||
self.check_recursion()
|
||||
self.update_cost_and_exploded_items()
|
||||
self.calculate_cost()
|
||||
self.update_exploded_items()
|
||||
self.doc.save()
|
||||
|
||||
def on_submit(self):
|
||||
self.manage_default_bom()
|
||||
|
||||
def on_cancel(self):
|
||||
# check if used in any other bom
|
||||
par = sql("""select t1.parent from `tabBOM Item` t1, `tabBOM` t2
|
||||
where t1.parent = t2.name and t1.bom_no = %s and t1.docstatus = 1
|
||||
and t2.is_active = 1""", self.doc.name)
|
||||
if par:
|
||||
msgprint("""BOM can not be cancelled, as it is a child item \
|
||||
in following active BOM %s""" % [d[0] for d in par], raise_exception=1)
|
||||
|
||||
webnotes.conn.set(self.doc, "is_active", 0)
|
||||
webnotes.conn.set(self.doc, "is_default", 0)
|
||||
|
||||
# check if used in any other bom
|
||||
self.validate_bom_links()
|
||||
self.manage_default_bom()
|
||||
self.update_cost_and_exploded_items(calculate_cost=False)
|
||||
|
||||
def on_update_after_submit(self):
|
||||
self.validate_bom_links()
|
||||
self.manage_default_bom()
|
||||
self.validate_inactive_bom()
|
||||
|
||||
def get_item_det(self, item_code):
|
||||
item = sql("""select name, is_asset_item, is_purchase_item, docstatus, description,
|
||||
@@ -79,7 +75,9 @@ class DocType:
|
||||
return item
|
||||
|
||||
def get_item_details(self, item_code):
|
||||
return { 'uom' : webnotes.conn.get_value("Item", item_code, "stock_uom")}
|
||||
res = sql("""select description, stock_uom as uom
|
||||
from `tabItem` where item_code = %s""", item_code, as_dict = 1, debug=1)
|
||||
return res and res[0] or {}
|
||||
|
||||
def get_workstation_details(self,workstation):
|
||||
return {'hour_rate': webnotes.conn.get_value("Workstation", workstation, "hour_rate")}
|
||||
@@ -158,7 +156,6 @@ class DocType:
|
||||
""" Uncheck others if current one is selected as default,
|
||||
update default bom in item master
|
||||
"""
|
||||
webnotes.conn.set(self.doc, "is_default", cint(self.doc.is_default))
|
||||
if self.doc.is_default and self.doc.is_active:
|
||||
from webnotes.model.utils import set_default
|
||||
set_default(self.doc, "item")
|
||||
@@ -174,6 +171,8 @@ class DocType:
|
||||
def clear_operations(self):
|
||||
if not self.doc.with_operations:
|
||||
self.doclist = self.doc.clear_table(self.doclist, 'bom_operations')
|
||||
for d in self.doclist.get({"parentfield": "bom_materials"}):
|
||||
d.operation_no = None
|
||||
|
||||
def validate_main_item(self):
|
||||
""" Validate main FG item"""
|
||||
@@ -209,8 +208,7 @@ class DocType:
|
||||
(m.operation_no, m.item_code, m.idx), raise_exception = 1)
|
||||
|
||||
item = self.get_item_det(m.item_code)
|
||||
if item[0]['is_manufactured_item'] == 'Yes' or \
|
||||
item[0]['is_sub_contracted_item'] == 'Yes':
|
||||
if item[0]['is_manufactured_item'] == 'Yes':
|
||||
if not m.bom_no:
|
||||
msgprint("Please enter BOM No aginst item: %s at row no: %s" %
|
||||
(m.item_code, m.idx), raise_exception=1)
|
||||
@@ -240,8 +238,8 @@ class DocType:
|
||||
|
||||
def check_if_item_repeated(self, item, op, check_list):
|
||||
if [cstr(item), cstr(op)] in check_list:
|
||||
msgprint("Item %s has been entered twice against same operation" %
|
||||
item, raise_exception = 1)
|
||||
msgprint(_("Item") + " %s " % (item,) + _("has been entered atleast twice")
|
||||
+ (cstr(op) and _(" against same operation") or ""), raise_exception=1)
|
||||
else:
|
||||
check_list.append([cstr(item), cstr(op)])
|
||||
|
||||
@@ -262,28 +260,24 @@ class DocType:
|
||||
if b[0]:
|
||||
bom_list.append(b[0])
|
||||
|
||||
def update_cost_and_exploded_items(self, calculate_cost=True):
|
||||
def update_cost_and_exploded_items(self):
|
||||
bom_list = self.traverse_tree()
|
||||
bom_list.reverse()
|
||||
for bom in bom_list:
|
||||
bom_obj = get_obj("BOM", bom, with_children=1)
|
||||
if calculate_cost:
|
||||
bom_obj.calculate_cost()
|
||||
bom_obj.update_exploded_items()
|
||||
if bom == self.doc.name:
|
||||
self.doc, self.doclist = bom_obj.doc, bom_obj.doclist
|
||||
bom_obj.on_update()
|
||||
|
||||
def traverse_tree(self):
|
||||
def _get_childs(bom_no):
|
||||
def _get_children(bom_no):
|
||||
return [cstr(d[0]) for d in webnotes.conn.sql("""select bom_no from `tabBOM Item`
|
||||
where parent = %s and ifnull(bom_no, '') != ''""", bom_no)]
|
||||
|
||||
bom_list, count = [self.doc.name], 0
|
||||
while(count < len(bom_list)):
|
||||
for child_bom in _get_childs(bom_list[count]):
|
||||
for child_bom in _get_children(bom_list[count]):
|
||||
if child_bom not in bom_list:
|
||||
bom_list.append(child_bom)
|
||||
count += 1
|
||||
bom_list.reverse()
|
||||
return bom_list
|
||||
|
||||
def calculate_cost(self):
|
||||
@@ -291,8 +285,6 @@ class DocType:
|
||||
self.calculate_op_cost()
|
||||
self.calculate_rm_cost()
|
||||
self.doc.total_cost = self.doc.raw_material_cost + self.doc.operating_cost
|
||||
self.doc.modified = now()
|
||||
self.doc.save()
|
||||
|
||||
def calculate_op_cost(self):
|
||||
"""Update workstation rate and calculates totals"""
|
||||
@@ -370,17 +362,19 @@ class DocType:
|
||||
ch.fields[i] = d[i]
|
||||
ch.docstatus = self.doc.docstatus
|
||||
ch.save(1)
|
||||
self.doc.save()
|
||||
|
||||
def get_parent_bom_list(self, bom_no):
|
||||
p_bom = sql("select parent from `tabBOM Item` where bom_no = '%s'" % bom_no)
|
||||
return p_bom and [i[0] for i in p_bom] or []
|
||||
|
||||
def validate_inactive_bom(self):
|
||||
def validate_bom_links(self):
|
||||
if not self.doc.is_active:
|
||||
act_pbom = sql("""select distinct t1.parent from `tabBOM Item` t1, `tabBOM` t2
|
||||
where t1.bom_no = %s and t2.name = t1.parent and t2.is_active = 1
|
||||
and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name)
|
||||
act_pbom = sql("""select distinct bom_item.parent from `tabBOM Item` bom_item
|
||||
where bom_item.bom_no = %s and bom_item.docstatus = 1
|
||||
and exists (select * from `tabBOM` where name = bom_item.parent
|
||||
and docstatus = 1 and is_active = 1)""", self.doc.name)
|
||||
|
||||
if act_pbom and act_pbom[0][0]:
|
||||
msgprint("""Sorry cannot inactivate as BOM: %s is child
|
||||
of one or many other active parent BOMs""" % self.doc.name, raise_exception=1)
|
||||
action = self.doc.docstatus < 2 and _("deactivate") or _("cancel")
|
||||
msgprint(_("Cannot ") + action + _(": It is linked to other active BOM(s)"),
|
||||
raise_exception=1)
|
||||
@@ -2,9 +2,9 @@
|
||||
{
|
||||
"owner": "Administrator",
|
||||
"docstatus": 0,
|
||||
"creation": "2012-12-14 10:15:15",
|
||||
"creation": "2012-12-19 12:29:06",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2012-12-14 16:51:01"
|
||||
"modified": "2012-12-19 15:52:47"
|
||||
},
|
||||
{
|
||||
"istable": 0,
|
||||
@@ -222,6 +222,13 @@
|
||||
"permlevel": 0,
|
||||
"in_filter": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"label": "Item Desription",
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"permlevel": 1
|
||||
},
|
||||
{
|
||||
"print_hide": 1,
|
||||
"no_copy": 1,
|
||||
@@ -256,17 +263,6 @@
|
||||
"hidden": 0,
|
||||
"options": "BOM Explosion Item"
|
||||
},
|
||||
{
|
||||
"print_hide": 1,
|
||||
"description": "The date at which current entry is corrected in the system.",
|
||||
"no_copy": 1,
|
||||
"depends_on": "eval:doc.amended_from",
|
||||
"doctype": "DocField",
|
||||
"label": "Amendment Date",
|
||||
"fieldname": "amendment_date",
|
||||
"fieldtype": "Date",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
|
||||
@@ -18,7 +18,7 @@ from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes.utils import cstr, flt
|
||||
from webnotes.model.code import get_obj
|
||||
from webnotes import msgprint
|
||||
from webnotes import msgprint, _
|
||||
|
||||
class DocType:
|
||||
def __init__( self, doc, doclist=[]):
|
||||
@@ -31,7 +31,9 @@ class DocType:
|
||||
bom_list = self.get_parent_boms()
|
||||
for bom in bom_list:
|
||||
bom_obj = get_obj("BOM", bom, with_children=1)
|
||||
bom_obj.on_update()
|
||||
bom_obj.update_cost_and_exploded_items()
|
||||
|
||||
webnotes.msgprint(_("BOM replaced"))
|
||||
|
||||
def validate_bom(self):
|
||||
if cstr(self.doc.current_bom) == cstr(self.doc.new_bom):
|
||||
|
||||
@@ -19,7 +19,6 @@ cur_frm.cscript.onload = function(doc, dt, dn) {
|
||||
cfn_set_fields(doc, dt, dn);
|
||||
}
|
||||
|
||||
// ================================== Refresh ==========================================
|
||||
cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
cur_frm.set_intro("");
|
||||
cfn_set_fields(doc, dt, dn);
|
||||
@@ -36,23 +35,6 @@ cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cur_frm.cscript.update_status_html(doc);
|
||||
}
|
||||
|
||||
cur_frm.cscript.update_status_html = function(doc) {
|
||||
$(cur_frm.get_field("status_html").wrapper).empty();
|
||||
|
||||
if(doc.issued_qty) {
|
||||
$(repl("<div class='progress'>\
|
||||
<div class='bar bar-success' style='width: %(manufactured)s%' \
|
||||
title='%(manufactured_qty)s %(uom)s manufactured'></div> \
|
||||
</div>"), {
|
||||
manufactured_qty: doc.produced_qty,
|
||||
manufactured: Math.round((doc.produced_qty / doc.qty) * 100),
|
||||
uom: doc.stock_uom,
|
||||
}).appendTo(cur_frm.get_field("status_html").wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
var cfn_set_fields = function(doc, dt, dn) {
|
||||
@@ -106,6 +88,9 @@ cur_frm.cscript.make_se = function(doc, purpose) {
|
||||
se.purpose = purpose;
|
||||
se.production_order = doc.name;
|
||||
se.company = doc.company;
|
||||
se.fg_completed_qty = doc.qty - doc.produced_qty;
|
||||
se.bom_no = doc.bom_no;
|
||||
se.use_multi_level_bom = 1;
|
||||
loaddoc('Stock Entry', se.name);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@ class DocType:
|
||||
% cstr(self.doc.production_item), raise_exception=1)
|
||||
|
||||
if self.doc.bom_no:
|
||||
bom = sql("""select name from `tabBOM` where name = %s and docstatus = 1
|
||||
and is_active = 'Yes' and item = %s"""
|
||||
bom = sql("""select name from `tabBOM` where name=%s and docstatus=1
|
||||
and is_active=1 and item=%s"""
|
||||
, (self.doc.bom_no, self.doc.production_item), as_dict =1)
|
||||
if not bom:
|
||||
msgprint("""Incorrect BOM: %s entered.
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
{
|
||||
"owner": "Administrator",
|
||||
"docstatus": 0,
|
||||
"creation": "2012-12-11 15:15:05",
|
||||
"creation": "2012-12-19 12:29:07",
|
||||
"modified_by": "Administrator",
|
||||
"modified": "2012-12-11 18:30:35"
|
||||
"modified": "2012-12-19 17:45:59"
|
||||
},
|
||||
{
|
||||
"is_submittable": 1,
|
||||
@@ -99,14 +99,6 @@
|
||||
"fieldname": "column_break1",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"read_only": 0,
|
||||
"depends_on": "issued_qty",
|
||||
"doctype": "DocField",
|
||||
"label": "Status HTML",
|
||||
"fieldname": "status_html",
|
||||
"fieldtype": "HTML"
|
||||
},
|
||||
{
|
||||
"read_only": 0,
|
||||
"oldfieldtype": "Currency",
|
||||
@@ -186,16 +178,12 @@
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"read_only": 0,
|
||||
"oldfieldtype": "Select",
|
||||
"doctype": "DocField",
|
||||
"label": "Fiscal Year",
|
||||
"oldfieldname": "fiscal_year",
|
||||
"fieldname": "fiscal_year",
|
||||
"fieldtype": "Select",
|
||||
"reqd": 1,
|
||||
"options": "link:Fiscal Year",
|
||||
"in_filter": 1
|
||||
"options": "link:Fiscal Year"
|
||||
},
|
||||
{
|
||||
"read_only": 1,
|
||||
@@ -207,16 +195,6 @@
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Data"
|
||||
},
|
||||
{
|
||||
"print_hide": 1,
|
||||
"description": "The date at which current entry is corrected in the system.",
|
||||
"no_copy": 1,
|
||||
"depends_on": "eval:doc.amended_from",
|
||||
"doctype": "DocField",
|
||||
"label": "Amendment Date",
|
||||
"fieldname": "amendment_date",
|
||||
"fieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"doctype": "DocPerm"
|
||||
}
|
||||
|
||||
@@ -188,6 +188,8 @@ class DocType:
|
||||
items = self.get_distinct_items_and_boms()[1]
|
||||
pro = self.create_production_order(items)
|
||||
if pro:
|
||||
pro = ["""<a href="#Form/Production Order/%s" target="_blank">%s</a>""" % \
|
||||
(p, p) for p in pro]
|
||||
msgprint("Following Production Order has been generated:\n" + '\n'.join(pro))
|
||||
else :
|
||||
msgprint("No Production Order generated.")
|
||||
|
||||
Reference in New Issue
Block a user