feat: Handle Excess/Multiple Item Transfer against Job Card
- Hide MR/Material Transfer buttons in JC if cancelled - Show MR/Material transfer buttons if pending to transfer or excess transfer allowed - Renamed ‘Transferred Qty’ to ‘FG Qty from Transferred Raw Materials’ in JC - Set status to Completed in JC in case of excess transfer too - During excess transfer against JC, avoid negative ‘For Quantity’. Set to 0 instead - Job card section and excess transfer allowance checkbox in Manufacturing Settings - Renamed ’Allow Multiple Material Consumption’ to ‘Allow Continuous Material Consumption’ (fiedname is same) - Secured denominator variables in `get_transfered_raw_materials` to avoid ZeroDivisionError
This commit is contained in:
		
							parent
							
								
									d743c41b54
								
							
						
					
					
						commit
						9520215e2b
					
				| @ -27,14 +27,21 @@ frappe.ui.form.on('Job Card', { | ||||
| 		frappe.flags.pause_job = 0; | ||||
| 		frappe.flags.resume_job = 0; | ||||
| 
 | ||||
| 		if(!frm.doc.__islocal && frm.doc.items && frm.doc.items.length) { | ||||
| 			if (frm.doc.for_quantity != frm.doc.transferred_qty) { | ||||
| 		if(!frm.doc.__islocal && frm.doc.items && frm.doc.items.length && frm.doc.docstatus < 2) { | ||||
| 			let to_request = frm.doc.for_quantity > frm.doc.transferred_qty; | ||||
| 			let excess_transfer_allowed = frm.doc.__onload.job_card_excess_transfer; | ||||
| 
 | ||||
| 			if (to_request || excess_transfer_allowed) { | ||||
| 				frm.add_custom_button(__("Material Request"), () => { | ||||
| 					frm.trigger("make_material_request"); | ||||
| 				}); | ||||
| 			} | ||||
| 
 | ||||
| 			if (frm.doc.for_quantity != frm.doc.transferred_qty) { | ||||
| 			// check if any row has untransferred materials
 | ||||
| 			// in case of multiple items in JC
 | ||||
| 			let to_transfer = frm.doc.items.some((row) => row.transferred_qty < row.required_qty); | ||||
| 
 | ||||
| 			if (to_transfer || excess_transfer_allowed) { | ||||
| 				frm.add_custom_button(__("Material Transfer"), () => { | ||||
| 					frm.trigger("make_stock_entry"); | ||||
| 				}).addClass("btn-primary"); | ||||
|  | ||||
| @ -185,7 +185,7 @@ | ||||
|    "default": "0", | ||||
|    "fieldname": "transferred_qty", | ||||
|    "fieldtype": "Float", | ||||
|    "label": "Transferred Qty", | ||||
|    "label": "FG Qty from Transferred Raw Materials", | ||||
|    "read_only": 1 | ||||
|   }, | ||||
|   { | ||||
| @ -396,10 +396,11 @@ | ||||
|  ], | ||||
|  "is_submittable": 1, | ||||
|  "links": [], | ||||
|  "modified": "2021-03-16 15:59:32.766484", | ||||
|  "modified": "2021-09-13 21:34:15.177928", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Manufacturing", | ||||
|  "name": "Job Card", | ||||
|  "naming_rule": "By \"Naming Series\" field", | ||||
|  "owner": "Administrator", | ||||
|  "permissions": [ | ||||
|   { | ||||
|  | ||||
| @ -37,6 +37,10 @@ class OperationSequenceError(frappe.ValidationError): pass | ||||
| class JobCardCancelError(frappe.ValidationError): pass | ||||
| 
 | ||||
| class JobCard(Document): | ||||
| 	def onload(self): | ||||
| 		excess_transfer = frappe.db.get_single_value("Manufacturing Settings", "job_card_excess_transfer") | ||||
| 		self.set_onload("job_card_excess_transfer", excess_transfer) | ||||
| 
 | ||||
| 	def validate(self): | ||||
| 		self.validate_time_logs() | ||||
| 		self.set_status() | ||||
| @ -449,6 +453,7 @@ class JobCard(Document): | ||||
| 			frappe.db.set_value('Job Card Item', row.job_card_item, 'transferred_qty', flt(qty)) | ||||
| 
 | ||||
| 	def set_transferred_qty(self, update_status=False): | ||||
| 		"Set total FG Qty for which RM was transferred." | ||||
| 		if not self.items: | ||||
| 			self.transferred_qty = self.for_quantity if self.docstatus == 1 else 0 | ||||
| 
 | ||||
| @ -457,6 +462,7 @@ class JobCard(Document): | ||||
| 			return | ||||
| 
 | ||||
| 		if self.items: | ||||
| 			# sum of 'For Quantity' of Stock Entries against JC | ||||
| 			self.transferred_qty = frappe.db.get_value('Stock Entry', { | ||||
| 				'job_card': self.name, | ||||
| 				'work_order': self.work_order, | ||||
| @ -500,7 +506,9 @@ class JobCard(Document): | ||||
| 			self.status = 'Work In Progress' | ||||
| 
 | ||||
| 		if (self.docstatus == 1 and | ||||
| 			(self.for_quantity == self.transferred_qty or not self.items)): | ||||
| 			(self.for_quantity <= self.transferred_qty or not self.items)): | ||||
| 			# consider excess transfer | ||||
| 			# completed qty is checked via separate validation | ||||
| 			self.status = 'Completed' | ||||
| 
 | ||||
| 		if self.status != 'Completed': | ||||
| @ -618,7 +626,11 @@ def make_stock_entry(source_name, target_doc=None): | ||||
| 	def set_missing_values(source, target): | ||||
| 		target.purpose = "Material Transfer for Manufacture" | ||||
| 		target.from_bom = 1 | ||||
| 		target.fg_completed_qty = source.get('for_quantity', 0) - source.get('transferred_qty', 0) | ||||
| 
 | ||||
| 		# avoid negative 'For Quantity' | ||||
| 		pending_fg_qty = source.get('for_quantity', 0) - source.get('transferred_qty', 0) | ||||
| 		target.fg_completed_qty = pending_fg_qty if pending_fg_qty > 0 else 0 | ||||
| 
 | ||||
| 		target.set_transfer_qty() | ||||
| 		target.calculate_rate_and_amount() | ||||
| 		target.set_missing_values() | ||||
|  | ||||
| @ -25,9 +25,12 @@ | ||||
|   "overproduction_percentage_for_sales_order", | ||||
|   "column_break_16", | ||||
|   "overproduction_percentage_for_work_order", | ||||
|   "job_card_section", | ||||
|   "add_corrective_operation_cost_in_finished_good_valuation", | ||||
|   "column_break_24", | ||||
|   "job_card_excess_transfer", | ||||
|   "other_settings_section", | ||||
|   "update_bom_costs_automatically", | ||||
|   "add_corrective_operation_cost_in_finished_good_valuation", | ||||
|   "column_break_23", | ||||
|   "make_serial_no_batch_from_work_order" | ||||
|  ], | ||||
| @ -96,10 +99,10 @@ | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "description": "Allow multiple material consumptions against a Work Order", | ||||
|    "description": "Allow material consumptions without immediately manufacturing finished goods against a Work Order", | ||||
|    "fieldname": "material_consumption", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Allow Multiple Material Consumption" | ||||
|    "label": "Allow Continuous Material Consumption" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
| @ -175,13 +178,29 @@ | ||||
|    "fieldname": "add_corrective_operation_cost_in_finished_good_valuation", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Add Corrective Operation Cost in Finished Good Valuation" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "job_card_section", | ||||
|    "fieldtype": "Section Break", | ||||
|    "label": "Job Card" | ||||
|   }, | ||||
|   { | ||||
|    "fieldname": "column_break_24", | ||||
|    "fieldtype": "Column Break" | ||||
|   }, | ||||
|   { | ||||
|    "default": "0", | ||||
|    "description": "Allow transferring raw materials even after the Required Quantity is fulfilled", | ||||
|    "fieldname": "job_card_excess_transfer", | ||||
|    "fieldtype": "Check", | ||||
|    "label": "Allow Excess Material Transfer" | ||||
|   } | ||||
|  ], | ||||
|  "icon": "icon-wrench", | ||||
|  "index_web_pages_for_search": 1, | ||||
|  "issingle": 1, | ||||
|  "links": [], | ||||
|  "modified": "2021-03-16 15:54:38.967341", | ||||
|  "modified": "2021-09-13 22:09:09.401559", | ||||
|  "modified_by": "Administrator", | ||||
|  "module": "Manufacturing", | ||||
|  "name": "Manufacturing Settings", | ||||
|  | ||||
| @ -1264,9 +1264,9 @@ class StockEntry(StockController): | ||||
| 		po_qty = frappe.db.sql("""select qty, produced_qty, material_transferred_for_manufacturing from | ||||
| 			`tabWork Order` where name=%s""", self.work_order, as_dict=1)[0] | ||||
| 
 | ||||
| 		manufacturing_qty = flt(po_qty.qty) | ||||
| 		manufacturing_qty = flt(po_qty.qty) or 1 | ||||
| 		produced_qty = flt(po_qty.produced_qty) | ||||
| 		trans_qty = flt(po_qty.material_transferred_for_manufacturing) | ||||
| 		trans_qty = flt(po_qty.material_transferred_for_manufacturing) or 1 | ||||
| 
 | ||||
| 		for item in transferred_materials: | ||||
| 			qty= item.qty | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user