bom code cleanup
This commit is contained in:
parent
33e0b5581e
commit
4301dadaab
@ -60,7 +60,6 @@ class DocType:
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_workstation_details(self,workstation):
|
def get_workstation_details(self,workstation):
|
||||||
""" Fetch hour rate from workstation master"""
|
""" Fetch hour rate from workstation master"""
|
||||||
|
|
||||||
@ -83,7 +82,6 @@ class DocType:
|
|||||||
msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1)
|
msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_bom_material_detail(self):
|
def get_bom_material_detail(self):
|
||||||
""" Get raw material details like uom, desc and rate"""
|
""" Get raw material details like uom, desc and rate"""
|
||||||
|
|
||||||
@ -146,7 +144,6 @@ class DocType:
|
|||||||
return rate and flt(sum(rate))/len(rate) or 0
|
return rate and flt(sum(rate))/len(rate) or 0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def manage_default_bom(self):
|
def manage_default_bom(self):
|
||||||
""" Uncheck others if current one is selected as default,
|
""" Uncheck others if current one is selected as default,
|
||||||
update default bom in item master
|
update default bom in item master
|
||||||
@ -156,68 +153,16 @@ class DocType:
|
|||||||
sql("update `tabBOM` set is_default = 0 where name != %s and item=%s",
|
sql("update `tabBOM` set is_default = 0 where name != %s and item=%s",
|
||||||
(self.doc.name, self.doc.item))
|
(self.doc.name, self.doc.item))
|
||||||
|
|
||||||
# update default bom in Item Master
|
webnotes.conn.set_value("Item", self.doc.item, "default_bom", self.doc.name)
|
||||||
sql("update `tabItem` set default_bom = %s where name = %s",
|
|
||||||
(self.doc.name, self.doc.item))
|
|
||||||
else:
|
else:
|
||||||
sql("update `tabItem` set default_bom = '' where name = %s and default_bom = %s",
|
sql("update `tabItem` set default_bom = '' where name = %s and default_bom = %s",
|
||||||
(self.doc.item, self.doc.name))
|
(self.doc.item, self.doc.name))
|
||||||
|
|
||||||
|
|
||||||
def manage_active_bom(self):
|
def validate(self):
|
||||||
""" Manage active/inactive """
|
self.validate_main_item()
|
||||||
if self.doc.is_active == 'Yes':
|
self.validate_operations()
|
||||||
self.validate()
|
self.validate_materials()
|
||||||
else:
|
|
||||||
self.check_active_parent_boms()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def check_active_parent_boms(self):
|
|
||||||
""" Check parent BOM before making it inactive """
|
|
||||||
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 = 'Yes'
|
|
||||||
and t2.docstatus = 1 and t1.docstatus =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)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_cost(self):
|
|
||||||
"""Calculate bom totals"""
|
|
||||||
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"""
|
|
||||||
total_op_cost = 0
|
|
||||||
for d in getlist(self.doclist, 'bom_operations'):
|
|
||||||
if d.hour_rate and d.time_in_mins:
|
|
||||||
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
|
|
||||||
d.save()
|
|
||||||
total_op_cost += flt(d.operating_cost)
|
|
||||||
self.doc.operating_cost = total_op_cost
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def calculate_rm_cost(self):
|
|
||||||
"""Fetch RM rate as per today's valuation rate and calculate totals"""
|
|
||||||
total_rm_cost = 0
|
|
||||||
for d in getlist(self.doclist, 'bom_materials'):
|
|
||||||
if d.bom_no:
|
|
||||||
d.rate = self.get_bom_unitcost(d.bom_no)
|
|
||||||
d.amount = flt(d.rate) * flt(d.qty)
|
|
||||||
d.qty_consumed_per_unit = flt(d.qty) / flt(self.doc.quantity)
|
|
||||||
d.save()
|
|
||||||
total_rm_cost += d.amount
|
|
||||||
self.doc.raw_material_cost = total_rm_cost
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def validate_main_item(self):
|
def validate_main_item(self):
|
||||||
""" Validate main FG item"""
|
""" Validate main FG item"""
|
||||||
@ -285,7 +230,6 @@ class DocType:
|
|||||||
(bom_no, item, idx), raise_exception = 1)
|
(bom_no, item, idx), raise_exception = 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def check_if_item_repeated(self, item, op, check_list):
|
def check_if_item_repeated(self, item, op, check_list):
|
||||||
if [cstr(item), cstr(op)] in check_list:
|
if [cstr(item), cstr(op)] in check_list:
|
||||||
msgprint("Item %s has been entered twice against same operation" %
|
msgprint("Item %s has been entered twice against same operation" %
|
||||||
@ -294,10 +238,9 @@ class DocType:
|
|||||||
check_list.append([cstr(item), cstr(op)])
|
check_list.append([cstr(item), cstr(op)])
|
||||||
|
|
||||||
|
|
||||||
def validate(self):
|
def on_update(self):
|
||||||
self.validate_main_item()
|
self.check_recursion()
|
||||||
self.validate_operations()
|
self.update_cost_and_exploded_items()
|
||||||
self.validate_materials()
|
|
||||||
|
|
||||||
def check_recursion(self):
|
def check_recursion(self):
|
||||||
""" Check whether recursion occurs in any bom"""
|
""" Check whether recursion occurs in any bom"""
|
||||||
@ -317,25 +260,89 @@ class DocType:
|
|||||||
bom_list.append(b[0])
|
bom_list.append(b[0])
|
||||||
|
|
||||||
|
|
||||||
def on_update(self):
|
def update_cost_and_exploded_items(self, calculate_cost=True):
|
||||||
self.check_recursion()
|
bom_list = self.traverse_tree()
|
||||||
self.update_cost_by_traversing()
|
bom_list.reverse()
|
||||||
self.update_flat_bom_by_traversing()
|
for bom in bom_list:
|
||||||
|
bom_obj = get_obj("BOM", bom, with_children=1)
|
||||||
|
if calculate_cost:
|
||||||
|
bom_obj.calculate_cost()
|
||||||
|
bom_obj.update_flat_bom()
|
||||||
|
|
||||||
|
|
||||||
|
def traverse_tree(self):
|
||||||
|
def _get_childs(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)]
|
||||||
|
|
||||||
def add_to_flat_bom_detail(self):
|
bom_list, count = [self.doc.name], 0
|
||||||
"Add items to Flat BOM table"
|
while(count < len(bom_list)):
|
||||||
self.doclist = self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
|
for child_bom in _get_childs(bom_list[count]):
|
||||||
for d in self.cur_flat_bom_items:
|
if child_bom not in bom_list:
|
||||||
ch = addchild(self.doc, 'flat_bom_details', 'BOM Explosion Item', 1, self.doclist)
|
bom_list.append(child_bom)
|
||||||
for i in d.keys():
|
count += 1
|
||||||
ch.fields[i] = d[i]
|
return bom_list
|
||||||
ch.docstatus = self.doc.docstatus
|
|
||||||
ch.save(1)
|
|
||||||
|
def calculate_cost(self):
|
||||||
|
"""Calculate bom totals"""
|
||||||
|
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()
|
self.doc.save()
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_op_cost(self):
|
||||||
|
"""Update workstation rate and calculates totals"""
|
||||||
|
total_op_cost = 0
|
||||||
|
for d in getlist(self.doclist, 'bom_operations'):
|
||||||
|
if d.hour_rate and d.time_in_mins:
|
||||||
|
d.operating_cost = flt(d.hour_rate) * flt(d.time_in_mins) / 60.0
|
||||||
|
d.save()
|
||||||
|
total_op_cost += flt(d.operating_cost)
|
||||||
|
self.doc.operating_cost = total_op_cost
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_rm_cost(self):
|
||||||
|
"""Fetch RM rate as per today's valuation rate and calculate totals"""
|
||||||
|
total_rm_cost = 0
|
||||||
|
for d in getlist(self.doclist, 'bom_materials'):
|
||||||
|
if d.bom_no:
|
||||||
|
d.rate = self.get_bom_unitcost(d.bom_no)
|
||||||
|
d.amount = flt(d.rate) * flt(d.qty)
|
||||||
|
d.qty_consumed_per_unit = flt(d.qty) / flt(self.doc.quantity)
|
||||||
|
d.save()
|
||||||
|
total_rm_cost += d.amount
|
||||||
|
self.doc.raw_material_cost = total_rm_cost
|
||||||
|
|
||||||
|
|
||||||
|
def update_flat_bom(self):
|
||||||
|
""" Update Flat BOM, following will be correct data"""
|
||||||
|
self.get_flat_bom_items()
|
||||||
|
self.add_to_flat_bom_detail()
|
||||||
|
|
||||||
|
|
||||||
|
def get_flat_bom_items(self):
|
||||||
|
""" Get all raw materials including items from child bom"""
|
||||||
|
self.cur_flat_bom_items = []
|
||||||
|
for d in getlist(self.doclist, 'bom_materials'):
|
||||||
|
if d.bom_no:
|
||||||
|
self.get_child_flat_bom_items(d.bom_no, d.qty)
|
||||||
|
else:
|
||||||
|
self.cur_flat_bom_items.append({
|
||||||
|
'item_code' : d.item_code,
|
||||||
|
'description' : d.description,
|
||||||
|
'stock_uom' : d.stock_uom,
|
||||||
|
'qty' : flt(d.qty),
|
||||||
|
'rate' : flt(d.rate),
|
||||||
|
'amount' : flt(d.amount),
|
||||||
|
'parent_bom' : d.parent,
|
||||||
|
'mat_detail_no' : d.name,
|
||||||
|
'qty_consumed_per_unit' : flt(d.qty_consumed_per_unit)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def get_child_flat_bom_items(self, bom_no, qty):
|
def get_child_flat_bom_items(self, bom_no, qty):
|
||||||
""" Add all items from Flat BOM of child BOM"""
|
""" Add all items from Flat BOM of child BOM"""
|
||||||
|
|
||||||
@ -357,31 +364,16 @@ class DocType:
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def add_to_flat_bom_detail(self):
|
||||||
def get_flat_bom_items(self):
|
"Add items to Flat BOM table"
|
||||||
""" Get all raw materials including items from child bom"""
|
self.doclist = self.doc.clear_table(self.doclist, 'flat_bom_details', 1)
|
||||||
self.cur_flat_bom_items = []
|
for d in self.cur_flat_bom_items:
|
||||||
for d in getlist(self.doclist, 'bom_materials'):
|
ch = addchild(self.doc, 'flat_bom_details', 'BOM Explosion Item', 1, self.doclist)
|
||||||
if d.bom_no:
|
for i in d.keys():
|
||||||
self.get_child_flat_bom_items(d.bom_no, d.qty)
|
ch.fields[i] = d[i]
|
||||||
else:
|
ch.docstatus = self.doc.docstatus
|
||||||
self.cur_flat_bom_items.append({
|
ch.save(1)
|
||||||
'item_code' : d.item_code,
|
self.doc.save()
|
||||||
'description' : d.description,
|
|
||||||
'stock_uom' : d.stock_uom,
|
|
||||||
'qty' : flt(d.qty),
|
|
||||||
'rate' : flt(d.rate),
|
|
||||||
'amount' : flt(d.amount),
|
|
||||||
'parent_bom' : d.parent,
|
|
||||||
'mat_detail_no' : d.name,
|
|
||||||
'qty_consumed_per_unit' : flt(d.qty_consumed_per_unit)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
def update_flat_bom(self):
|
|
||||||
""" Update Flat BOM, following will be correct data"""
|
|
||||||
self.get_flat_bom_items()
|
|
||||||
self.add_to_flat_bom_detail()
|
|
||||||
|
|
||||||
|
|
||||||
def get_parent_bom_list(self, bom_no):
|
def get_parent_bom_list(self, bom_no):
|
||||||
@ -392,6 +384,7 @@ class DocType:
|
|||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.manage_default_bom()
|
self.manage_default_bom()
|
||||||
|
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
# check if used in any other bom
|
# check if used in any other bom
|
||||||
par = sql("""select t1.parent from `tabBOM Item` t1, `tabBOM` t2
|
par = sql("""select t1.parent from `tabBOM Item` t1, `tabBOM` t2
|
||||||
@ -404,30 +397,19 @@ class DocType:
|
|||||||
webnotes.conn.set(self.doc, "is_active", "No")
|
webnotes.conn.set(self.doc, "is_active", "No")
|
||||||
webnotes.conn.set(self.doc, "is_default", 0)
|
webnotes.conn.set(self.doc, "is_default", 0)
|
||||||
self.manage_default_bom()
|
self.manage_default_bom()
|
||||||
self.update_flat_bom_by_traversing()
|
self.update_cost_and_exploded_items(calculate_cost=False)
|
||||||
|
|
||||||
def traverse_tree(self):
|
|
||||||
def _get_childs(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
|
def on_update_after_submit(self):
|
||||||
while(count < len(bom_list)):
|
self.manage_default_bom()
|
||||||
for child_bom in _get_childs(bom_list[count]):
|
self.validate_inactive_bom()
|
||||||
if child_bom not in bom_list:
|
|
||||||
bom_list.append(child_bom)
|
|
||||||
count += 1
|
|
||||||
|
|
||||||
return bom_list
|
|
||||||
|
|
||||||
def update_cost_by_traversing(self):
|
def validate_inactive_bom(self):
|
||||||
bom_list = self.traverse_tree()
|
if self.doc.is_active == 'No':
|
||||||
bom_list.reverse()
|
act_pbom = sql("""select distinct t1.parent from `tabBOM Item` t1, `tabBOM` t2
|
||||||
for bom in bom_list:
|
where t1.bom_no =%s and t2.name = t1.parent and t2.is_active = 'Yes'
|
||||||
get_obj("BOM", bom, with_children=1).calculate_cost()
|
and t2.docstatus = 1 and t1.docstatus =1 """, self.doc.name)
|
||||||
|
if act_pbom and act_pbom[0][0]:
|
||||||
def update_flat_bom_by_traversing(self):
|
msgprint("""Sorry cannot inactivate as BOM: %s is child
|
||||||
bom_list = self.traverse_tree()
|
of one or many other active parent BOMs""" % self.doc.name, raise_exception=1)
|
||||||
bom_list.reverse()
|
|
||||||
for bom in bom_list:
|
|
||||||
get_obj("BOM", bom, with_children=1).update_flat_bom()
|
|
||||||
Loading…
x
Reference in New Issue
Block a user