[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++) { | ||||
| 		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, | ||||
| 			{'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 | ||||
| 
 | ||||
| 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() | ||||
| def get_bom_items(bom, company, qty=1, fetch_exploded=1): | ||||
| 	items = get_bom_items_as_dict(bom, company, qty, fetch_exploded).values() | ||||
|  | ||||
| @ -451,6 +451,33 @@ | ||||
|    "set_only_once": 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,  | ||||
|    "bold": 0,  | ||||
| @ -1133,7 +1160,7 @@ | ||||
|  "issingle": 0,  | ||||
|  "istable": 0,  | ||||
|  "max_attachments": 0,  | ||||
|  "modified": "2016-09-19 02:48:09.412858",  | ||||
|  "modified": "2016-09-26 07:01:12.863755",  | ||||
|  "modified_by": "Administrator",  | ||||
|  "module": "Manufacturing",  | ||||
|  "name": "Production Order",  | ||||
|  | ||||
| @ -148,7 +148,7 @@ class StockEntry(StockController): | ||||
| 						if not d.t_warehouse: | ||||
| 							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)) | ||||
| 
 | ||||
| 					else: | ||||
| @ -348,14 +348,14 @@ class StockEntry(StockController): | ||||
| 
 | ||||
| 	def validate_bom(self): | ||||
| 		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) | ||||
| 
 | ||||
| 	def validate_finished_goods(self): | ||||
| 		"""validation: finished good quantity should be same as manufacturing quantity""" | ||||
| 		items_with_target_warehouse = [] | ||||
| 		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}"). \ | ||||
| 					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["to_warehouse"] = self.to_warehouse if self.purpose=="Subcontract" else "" | ||||
| 					 | ||||
| 					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 | ||||
| 			if self.production_order and self.purpose == "Manufacture": | ||||
| 				self.set_serial_nos(self.production_order) | ||||
| @ -608,6 +616,17 @@ class StockEntry(StockController): | ||||
| 			item.from_warehouse = self.from_warehouse or item.default_warehouse | ||||
| 		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): | ||||
| 		transferred_materials = frappe.db.sql(""" | ||||
| 			select | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user