[enhance] scrap management
This commit is contained in:
parent
464c27e189
commit
5a2fa8aac7
@ -143,8 +143,6 @@ erpnext.bom.calculate_sm_cost = function(doc) {
|
|||||||
for(var i=0;i<sm.length;i++) {
|
for(var i=0;i<sm.length;i++) {
|
||||||
amt = flt(sm[i].rate) * flt(sm[i].qty);
|
amt = flt(sm[i].rate) * flt(sm[i].qty);
|
||||||
set_multiple('BOM Scrap Item',sm[i].name, {'amount': amt}, 'scrap_items');
|
set_multiple('BOM Scrap Item',sm[i].name, {'amount': amt}, 'scrap_items');
|
||||||
set_multiple('BOM Scrap Item',sm[i].name,
|
|
||||||
{'qty_consumed_per_unit': flt(sm[i].qty)/flt(doc.quantity)}, 'scrap_items');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,6 +425,48 @@ def get_bom_items_as_dict(bom, company, qty=1, fetch_exploded=1):
|
|||||||
|
|
||||||
return item_dict
|
return item_dict
|
||||||
|
|
||||||
|
def get_bom_scrap_items_as_dict(bom, company, qty=1, fetch_exploded=1):
|
||||||
|
item_dict = {}
|
||||||
|
|
||||||
|
# Did not use qty_consumed_per_unit in the query, as it leads to rounding loss
|
||||||
|
query = """select
|
||||||
|
bom_scrap_item.item_code,
|
||||||
|
item.item_name,
|
||||||
|
sum(bom_scrap_item.qty/ifnull(bom.quantity, 1)) * %(qty)s as qty,
|
||||||
|
item.description,
|
||||||
|
item.image,
|
||||||
|
item.stock_uom,
|
||||||
|
item.default_warehouse,
|
||||||
|
item.expense_account as expense_account,
|
||||||
|
item.buying_cost_center as cost_center
|
||||||
|
from
|
||||||
|
`tabBOM Scrap Item` bom_scrap_item, `tabBOM` bom, `tabItem` item
|
||||||
|
where
|
||||||
|
bom_scrap_item.parent = bom.name
|
||||||
|
and bom_scrap_item.docstatus < 2
|
||||||
|
and bom_scrap_item.parent = %(bom)s
|
||||||
|
and item.name = bom_scrap_item.item_code
|
||||||
|
and is_stock_item = 1
|
||||||
|
group by item_code, stock_uom"""
|
||||||
|
|
||||||
|
items = frappe.db.sql(query, { "qty": qty, "bom": bom }, as_dict=True)
|
||||||
|
|
||||||
|
# make unique
|
||||||
|
for item in items:
|
||||||
|
if item_dict.has_key(item.item_code):
|
||||||
|
item_dict[item.item_code]["qty"] += flt(item.qty)
|
||||||
|
else:
|
||||||
|
item_dict[item.item_code] = item
|
||||||
|
|
||||||
|
for item, item_details in item_dict.items():
|
||||||
|
for d in [["Account", "expense_account", "default_expense_account"],
|
||||||
|
["Cost Center", "cost_center", "cost_center"], ["Warehouse", "default_warehouse", ""]]:
|
||||||
|
company_in_record = frappe.db.get_value(d[0], item_details.get(d[1]), "company")
|
||||||
|
if not item_details.get(d[1]) or (company_in_record and company != company_in_record):
|
||||||
|
item_dict[item][d[1]] = frappe.db.get_value("Company", company, d[2]) if d[2] else None
|
||||||
|
|
||||||
|
return item_dict
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_bom_items(bom, company, qty=1, fetch_exploded=1):
|
def get_bom_items(bom, company, qty=1, fetch_exploded=1):
|
||||||
items = get_bom_items_as_dict(bom, company, qty, fetch_exploded).values()
|
items = get_bom_items_as_dict(bom, company, qty, fetch_exploded).values()
|
||||||
|
@ -451,6 +451,33 @@
|
|||||||
"set_only_once": 0,
|
"set_only_once": 0,
|
||||||
"unique": 0
|
"unique": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"fieldname": "scrap_warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"label": "Scrap Warehouse",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Warehouse",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"unique": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 0,
|
"allow_on_submit": 0,
|
||||||
"bold": 0,
|
"bold": 0,
|
||||||
@ -1133,7 +1160,7 @@
|
|||||||
"issingle": 0,
|
"issingle": 0,
|
||||||
"istable": 0,
|
"istable": 0,
|
||||||
"max_attachments": 0,
|
"max_attachments": 0,
|
||||||
"modified": "2016-09-19 02:48:09.412858",
|
"modified": "2016-09-26 07:01:12.863755",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Manufacturing",
|
"module": "Manufacturing",
|
||||||
"name": "Production Order",
|
"name": "Production Order",
|
||||||
|
@ -148,7 +148,7 @@ class StockEntry(StockController):
|
|||||||
if not d.t_warehouse:
|
if not d.t_warehouse:
|
||||||
frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx))
|
frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx))
|
||||||
|
|
||||||
elif self.pro_doc and cstr(d.t_warehouse) != self.pro_doc.fg_warehouse:
|
elif self.pro_doc and (cstr(d.t_warehouse) != self.pro_doc.fg_warehouse and cstr(d.t_warehouse) != self.pro_doc.scrap_warehouse):
|
||||||
frappe.throw(_("Target warehouse in row {0} must be same as Production Order").format(d.idx))
|
frappe.throw(_("Target warehouse in row {0} must be same as Production Order").format(d.idx))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -348,14 +348,14 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
def validate_bom(self):
|
def validate_bom(self):
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.bom_no:
|
if d.bom_no and (d.t_warehouse != self.pro_doc.scrap_warehouse):
|
||||||
validate_bom_no(d.item_code, d.bom_no)
|
validate_bom_no(d.item_code, d.bom_no)
|
||||||
|
|
||||||
def validate_finished_goods(self):
|
def validate_finished_goods(self):
|
||||||
"""validation: finished good quantity should be same as manufacturing quantity"""
|
"""validation: finished good quantity should be same as manufacturing quantity"""
|
||||||
items_with_target_warehouse = []
|
items_with_target_warehouse = []
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty):
|
if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty) and (d.t_warehouse != self.pro_doc.scrap_warehouse):
|
||||||
frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
|
frappe.throw(_("Quantity in row {0} ({1}) must be same as manufactured quantity {2}"). \
|
||||||
format(d.idx, d.transfer_qty, self.fg_completed_qty))
|
format(d.idx, d.transfer_qty, self.fg_completed_qty))
|
||||||
|
|
||||||
@ -557,7 +557,15 @@ class StockEntry(StockController):
|
|||||||
item["from_warehouse"] = self.pro_doc.wip_warehouse
|
item["from_warehouse"] = self.pro_doc.wip_warehouse
|
||||||
|
|
||||||
item["to_warehouse"] = self.to_warehouse if self.purpose=="Subcontract" else ""
|
item["to_warehouse"] = self.to_warehouse if self.purpose=="Subcontract" else ""
|
||||||
|
|
||||||
self.add_to_stock_entry_detail(item_dict)
|
self.add_to_stock_entry_detail(item_dict)
|
||||||
|
|
||||||
|
scrap_item_dict = self.get_bom_scrap_material(self.fg_completed_qty)
|
||||||
|
for item in scrap_item_dict.values():
|
||||||
|
if self.pro_doc and self.pro_doc.scrap_warehouse:
|
||||||
|
item["to_warehouse"] = self.pro_doc.scrap_warehouse
|
||||||
|
self.add_to_stock_entry_detail(scrap_item_dict, bom_no=self.bom_no)
|
||||||
|
|
||||||
# fetch the serial_no of the first stock entry for the second stock entry
|
# fetch the serial_no of the first stock entry for the second stock entry
|
||||||
if self.production_order and self.purpose == "Manufacture":
|
if self.production_order and self.purpose == "Manufacture":
|
||||||
self.set_serial_nos(self.production_order)
|
self.set_serial_nos(self.production_order)
|
||||||
@ -608,6 +616,17 @@ class StockEntry(StockController):
|
|||||||
item.from_warehouse = self.from_warehouse or item.default_warehouse
|
item.from_warehouse = self.from_warehouse or item.default_warehouse
|
||||||
return item_dict
|
return item_dict
|
||||||
|
|
||||||
|
def get_bom_scrap_material(self, qty):
|
||||||
|
from erpnext.manufacturing.doctype.bom.bom import get_bom_scrap_items_as_dict
|
||||||
|
|
||||||
|
# item dict = { item_code: {qty, description, stock_uom} }
|
||||||
|
item_dict = get_bom_scrap_items_as_dict(self.bom_no, self.company, qty=qty,
|
||||||
|
fetch_exploded = self.use_multi_level_bom)
|
||||||
|
|
||||||
|
for item in item_dict.values():
|
||||||
|
item.from_warehouse = ""
|
||||||
|
return item_dict
|
||||||
|
|
||||||
def get_transfered_raw_materials(self):
|
def get_transfered_raw_materials(self):
|
||||||
transferred_materials = frappe.db.sql("""
|
transferred_materials = frappe.db.sql("""
|
||||||
select
|
select
|
||||||
|
Loading…
Reference in New Issue
Block a user