Merge pull request #38419 from frappe/mergify/bp/version-15-hotfix/pr-38415
fix: incorrect ordered qty for Subcontracting Order (backport #38415)
This commit is contained in:
		
						commit
						4bb1cb50ba
					
				| @ -1001,6 +1001,7 @@ def make_subcontracted_items(): | |||||||
| 		"Subcontracted Item SA5": {}, | 		"Subcontracted Item SA5": {}, | ||||||
| 		"Subcontracted Item SA6": {}, | 		"Subcontracted Item SA6": {}, | ||||||
| 		"Subcontracted Item SA7": {}, | 		"Subcontracted Item SA7": {}, | ||||||
|  | 		"Subcontracted Item SA8": {}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for item, properties in sub_contracted_items.items(): | 	for item, properties in sub_contracted_items.items(): | ||||||
| @ -1020,6 +1021,7 @@ def make_raw_materials(): | |||||||
| 		}, | 		}, | ||||||
| 		"Subcontracted SRM Item 4": {"has_serial_no": 1, "serial_no_series": "SRII.####"}, | 		"Subcontracted SRM Item 4": {"has_serial_no": 1, "serial_no_series": "SRII.####"}, | ||||||
| 		"Subcontracted SRM Item 5": {"has_serial_no": 1, "serial_no_series": "SRIID.####"}, | 		"Subcontracted SRM Item 5": {"has_serial_no": 1, "serial_no_series": "SRIID.####"}, | ||||||
|  | 		"Subcontracted SRM Item 8": {}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for item, properties in raw_materials.items(): | 	for item, properties in raw_materials.items(): | ||||||
| @ -1043,6 +1045,7 @@ def make_service_items(): | |||||||
| 		"Subcontracted Service Item 5": {}, | 		"Subcontracted Service Item 5": {}, | ||||||
| 		"Subcontracted Service Item 6": {}, | 		"Subcontracted Service Item 6": {}, | ||||||
| 		"Subcontracted Service Item 7": {}, | 		"Subcontracted Service Item 7": {}, | ||||||
|  | 		"Subcontracted Service Item 8": {}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for item, properties in service_items.items(): | 	for item, properties in service_items.items(): | ||||||
| @ -1066,6 +1069,7 @@ def make_bom_for_subcontracted_items(): | |||||||
| 		"Subcontracted Item SA5": ["Subcontracted SRM Item 5"], | 		"Subcontracted Item SA5": ["Subcontracted SRM Item 5"], | ||||||
| 		"Subcontracted Item SA6": ["Subcontracted SRM Item 3"], | 		"Subcontracted Item SA6": ["Subcontracted SRM Item 3"], | ||||||
| 		"Subcontracted Item SA7": ["Subcontracted SRM Item 1"], | 		"Subcontracted Item SA7": ["Subcontracted SRM Item 1"], | ||||||
|  | 		"Subcontracted Item SA8": ["Subcontracted SRM Item 8"], | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for item_code, raw_materials in boms.items(): | 	for item_code, raw_materials in boms.items(): | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ from frappe.utils import flt | |||||||
| 
 | 
 | ||||||
| from erpnext.buying.doctype.purchase_order.purchase_order import is_subcontracting_order_created | from erpnext.buying.doctype.purchase_order.purchase_order import is_subcontracting_order_created | ||||||
| from erpnext.controllers.subcontracting_controller import SubcontractingController | from erpnext.controllers.subcontracting_controller import SubcontractingController | ||||||
| from erpnext.stock.stock_balance import get_ordered_qty, update_bin_qty | from erpnext.stock.stock_balance import update_bin_qty | ||||||
| from erpnext.stock.utils import get_bin | from erpnext.stock.utils import get_bin | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -114,7 +114,32 @@ class SubcontractingOrder(SubcontractingController): | |||||||
| 			): | 			): | ||||||
| 				item_wh_list.append([item.item_code, item.warehouse]) | 				item_wh_list.append([item.item_code, item.warehouse]) | ||||||
| 		for item_code, warehouse in item_wh_list: | 		for item_code, warehouse in item_wh_list: | ||||||
| 			update_bin_qty(item_code, warehouse, {"ordered_qty": get_ordered_qty(item_code, warehouse)}) | 			update_bin_qty( | ||||||
|  | 				item_code, warehouse, {"ordered_qty": self.get_ordered_qty(item_code, warehouse)} | ||||||
|  | 			) | ||||||
|  | 
 | ||||||
|  | 	@staticmethod | ||||||
|  | 	def get_ordered_qty(item_code, warehouse): | ||||||
|  | 		table = frappe.qb.DocType("Subcontracting Order") | ||||||
|  | 		child = frappe.qb.DocType("Subcontracting Order Item") | ||||||
|  | 
 | ||||||
|  | 		query = ( | ||||||
|  | 			frappe.qb.from_(table) | ||||||
|  | 			.inner_join(child) | ||||||
|  | 			.on(table.name == child.parent) | ||||||
|  | 			.select((child.qty - child.received_qty) * child.conversion_factor) | ||||||
|  | 			.where( | ||||||
|  | 				(table.docstatus == 1) | ||||||
|  | 				& (child.item_code == item_code) | ||||||
|  | 				& (child.warehouse == warehouse) | ||||||
|  | 				& (child.qty > child.received_qty) | ||||||
|  | 				& (table.status != "Completed") | ||||||
|  | 			) | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		query = query.run() | ||||||
|  | 
 | ||||||
|  | 		return flt(query[0][0]) if query else 0 | ||||||
| 
 | 
 | ||||||
| 	def update_reserved_qty_for_subcontracting(self): | 	def update_reserved_qty_for_subcontracting(self): | ||||||
| 		for item in self.supplied_items: | 		for item in self.supplied_items: | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ from collections import defaultdict | |||||||
| 
 | 
 | ||||||
| import frappe | import frappe | ||||||
| from frappe.tests.utils import FrappeTestCase | from frappe.tests.utils import FrappeTestCase | ||||||
|  | from frappe.utils import flt | ||||||
| 
 | 
 | ||||||
| from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_subcontracting_order | from erpnext.buying.doctype.purchase_order.purchase_order import get_mapped_subcontracting_order | ||||||
| from erpnext.controllers.subcontracting_controller import ( | from erpnext.controllers.subcontracting_controller import ( | ||||||
| @ -566,6 +567,67 @@ class TestSubcontractingOrder(FrappeTestCase): | |||||||
| 		self.assertEqual(sco.status, "Closed") | 		self.assertEqual(sco.status, "Closed") | ||||||
| 		self.assertEqual(sco.supplied_items[0].returned_qty, 5) | 		self.assertEqual(sco.supplied_items[0].returned_qty, 5) | ||||||
| 
 | 
 | ||||||
|  | 	def test_ordered_qty_for_subcontracting_order(self): | ||||||
|  | 		service_items = [ | ||||||
|  | 			{ | ||||||
|  | 				"warehouse": "_Test Warehouse - _TC", | ||||||
|  | 				"item_code": "Subcontracted Service Item 8", | ||||||
|  | 				"qty": 10, | ||||||
|  | 				"rate": 100, | ||||||
|  | 				"fg_item": "Subcontracted Item SA8", | ||||||
|  | 				"fg_item_qty": 10, | ||||||
|  | 			}, | ||||||
|  | 		] | ||||||
|  | 
 | ||||||
|  | 		ordered_qty = frappe.db.get_value( | ||||||
|  | 			"Bin", | ||||||
|  | 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, | ||||||
|  | 			fieldname="ordered_qty", | ||||||
|  | 		) | ||||||
|  | 		ordered_qty = flt(ordered_qty) | ||||||
|  | 
 | ||||||
|  | 		sco = get_subcontracting_order(service_items=service_items) | ||||||
|  | 		sco.reload() | ||||||
|  | 
 | ||||||
|  | 		new_ordered_qty = frappe.db.get_value( | ||||||
|  | 			"Bin", | ||||||
|  | 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, | ||||||
|  | 			fieldname="ordered_qty", | ||||||
|  | 		) | ||||||
|  | 		new_ordered_qty = flt(new_ordered_qty) | ||||||
|  | 
 | ||||||
|  | 		self.assertEqual(ordered_qty + 10, new_ordered_qty) | ||||||
|  | 
 | ||||||
|  | 		for row in sco.supplied_items: | ||||||
|  | 			make_stock_entry( | ||||||
|  | 				target="_Test Warehouse 1 - _TC", | ||||||
|  | 				item_code=row.rm_item_code, | ||||||
|  | 				qty=row.required_qty, | ||||||
|  | 				basic_rate=100, | ||||||
|  | 			) | ||||||
|  | 
 | ||||||
|  | 		scr = make_subcontracting_receipt(sco.name) | ||||||
|  | 		scr.submit() | ||||||
|  | 
 | ||||||
|  | 		new_ordered_qty = frappe.db.get_value( | ||||||
|  | 			"Bin", | ||||||
|  | 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, | ||||||
|  | 			fieldname="ordered_qty", | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		self.assertEqual(ordered_qty, new_ordered_qty) | ||||||
|  | 
 | ||||||
|  | 		scr.reload() | ||||||
|  | 		scr.cancel() | ||||||
|  | 
 | ||||||
|  | 		new_ordered_qty = frappe.db.get_value( | ||||||
|  | 			"Bin", | ||||||
|  | 			filters={"warehouse": "_Test Warehouse - _TC", "item_code": "Subcontracted Item SA8"}, | ||||||
|  | 			fieldname="ordered_qty", | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		self.assertEqual(ordered_qty + 10, new_ordered_qty) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| def create_subcontracting_order(**args): | def create_subcontracting_order(**args): | ||||||
| 	args = frappe._dict(args) | 	args = frappe._dict(args) | ||||||
|  | |||||||
| @ -95,12 +95,12 @@ class SubcontractingReceipt(SubcontractingController): | |||||||
| 		) | 		) | ||||||
| 		self.update_status_updater_args() | 		self.update_status_updater_args() | ||||||
| 		self.update_prevdoc_status() | 		self.update_prevdoc_status() | ||||||
| 		self.update_stock_ledger() |  | ||||||
| 		self.make_gl_entries_on_cancel() |  | ||||||
| 		self.repost_future_sle_and_gle() |  | ||||||
| 		self.delete_auto_created_batches() | 		self.delete_auto_created_batches() | ||||||
| 		self.set_consumed_qty_in_subcontract_order() | 		self.set_consumed_qty_in_subcontract_order() | ||||||
| 		self.set_subcontracting_order_status() | 		self.set_subcontracting_order_status() | ||||||
|  | 		self.update_stock_ledger() | ||||||
|  | 		self.make_gl_entries_on_cancel() | ||||||
|  | 		self.repost_future_sle_and_gle() | ||||||
| 		self.update_status() | 		self.update_status() | ||||||
| 
 | 
 | ||||||
| 	def validate_items_qty(self): | 	def validate_items_qty(self): | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user