diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 2ee6cf7f00c..dcaf7d6779a 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -406,7 +406,7 @@ erpnext.buying.PurchaseOrderController = class PurchaseOrderController extends ( ); } } else { - if (!doc.items.every((item) => item.qty == item.sco_qty)) { + if (!doc.items.every((item) => item.qty == item.subcontracted_quantity)) { this.frm.add_custom_button( __("Subcontracting Order"), () => { diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 5ee650ead60..001a20e90e6 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -922,7 +922,7 @@ def is_po_fully_subcontracted(po_name): query = ( frappe.qb.from_(table) .select(table.name) - .where((table.parent == po_name) & (table.qty != table.sco_qty)) + .where((table.parent == po_name) & (table.qty != table.subcontracted_quantity)) ) return not query.run(as_dict=True) @@ -977,7 +977,7 @@ def get_mapped_subcontracting_order(source_name, target_doc=None): "material_request_item": "material_request_item", }, "field_no_map": ["qty", "fg_item_qty", "amount"], - "condition": lambda item: item.qty != item.sco_qty, + "condition": lambda item: item.qty != item.subcontracted_quantity, }, }, target_doc, diff --git a/erpnext/buying/doctype/purchase_order/test_purchase_order.py b/erpnext/buying/doctype/purchase_order/test_purchase_order.py index 97d87d931db..f799d52da49 100644 --- a/erpnext/buying/doctype/purchase_order/test_purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/test_purchase_order.py @@ -1097,9 +1097,9 @@ class TestPurchaseOrder(IntegrationTestCase): # Test - 2: Subcontracted Quantity for the PO Items of each line item should be updated accordingly po.reload() - self.assertEqual(po.items[0].sco_qty, 5) - self.assertEqual(po.items[1].sco_qty, 0) - self.assertEqual(po.items[2].sco_qty, 12.5) + self.assertEqual(po.items[0].subcontracted_quantity, 5) + self.assertEqual(po.items[1].subcontracted_quantity, 0) + self.assertEqual(po.items[2].subcontracted_quantity, 12.5) # Test - 3: Amount for both FG Item and its Service Item should be updated correctly based on change in Quantity self.assertEqual(sco.items[0].amount, 2000) @@ -1135,10 +1135,10 @@ class TestPurchaseOrder(IntegrationTestCase): # Test - 8: Subcontracted Quantity for each PO Item should be subtracted if SCO gets cancelled po.reload() - self.assertEqual(po.items[2].sco_qty, 25) + self.assertEqual(po.items[2].subcontracted_quantity, 25) sco.cancel() po.reload() - self.assertEqual(po.items[2].sco_qty, 12.5) + self.assertEqual(po.items[2].subcontracted_quantity, 12.5) sco = make_subcontracting_order(po.name) sco.save() diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json index 97796e51a39..9a0e150554f 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.json @@ -26,7 +26,7 @@ "quantity_and_rate", "qty", "stock_uom", - "sco_qty", + "subcontracted_quantity", "col_break2", "uom", "conversion_factor", @@ -933,7 +933,7 @@ }, { "allow_on_submit": 1, - "fieldname": "sco_qty", + "fieldname": "subcontracted_quantity", "fieldtype": "Float", "label": "Subcontracted Quantity", "no_copy": 1, @@ -941,11 +941,12 @@ "read_only": 1 } ], + "grid_page_length": 50, "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2025-02-18 12:35:04.432636", + "modified": "2025-03-02 16:58:26.059601", "modified_by": "Administrator", "module": "Buying", "name": "Purchase Order Item", @@ -953,6 +954,7 @@ "owner": "Administrator", "permissions": [], "quick_entry": 1, + "row_format": "Dynamic", "search_fields": "item_name", "sort_field": "creation", "sort_order": "DESC", diff --git a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py index 9d65e6bbc1d..aebe6e1299e 100644 --- a/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py +++ b/erpnext/buying/doctype/purchase_order_item/purchase_order_item.py @@ -82,10 +82,10 @@ class PurchaseOrderItem(Document): sales_order_item: DF.Data | None sales_order_packed_item: DF.Data | None schedule_date: DF.Date - sco_qty: DF.Float stock_qty: DF.Float stock_uom: DF.Link stock_uom_rate: DF.Currency + subcontracted_quantity: DF.Float supplier_part_no: DF.Data | None supplier_quotation: DF.Link | None supplier_quotation_item: DF.Link | None diff --git a/erpnext/controllers/subcontracting_controller.py b/erpnext/controllers/subcontracting_controller.py index 1e66587e65a..9f8349b96a2 100644 --- a/erpnext/controllers/subcontracting_controller.py +++ b/erpnext/controllers/subcontracting_controller.py @@ -104,18 +104,18 @@ class SubcontractingController(StockController): ) if ( - self.doctype == "Subcontracting Order" and not item.sc_conversion_factor + self.doctype == "Subcontracting Order" and not item.subcontracting_conversion_factor ): # this condition will only be true if user has recently updated from develop branch service_item_qty = frappe.get_value( "Subcontracting Order Service Item", filters={"purchase_order_item": item.purchase_order_item, "parent": self.name}, fieldname=["qty"], ) - item.sc_conversion_factor = service_item_qty / item.qty + item.subcontracting_conversion_factor = service_item_qty / item.qty if self.doctype not in "Subcontracting Receipt" and item.qty > flt( - get_pending_sco_qty(self.purchase_order).get(item.purchase_order_item) - / item.sc_conversion_factor, + get_pending_subcontracted_quantity(self.purchase_order).get(item.purchase_order_item) + / item.subcontracting_conversion_factor, frappe.get_precision("Purchase Order Item", "qty"), ): frappe.throw( @@ -1138,10 +1138,14 @@ def get_item_details(items): return item_details -def get_pending_sco_qty(po_name): +def get_pending_subcontracted_quantity(po_name): table = frappe.qb.DocType("Purchase Order Item") - query = frappe.qb.from_(table).select(table.name, table.qty, table.sco_qty).where(table.parent == po_name) - return {item.name: item.qty - item.sco_qty for item in query.run(as_dict=True)} + query = ( + frappe.qb.from_(table) + .select(table.name, table.qty, table.subcontracted_quantity) + .where(table.parent == po_name) + ) + return {item.name: item.qty - item.subcontracted_quantity for item in query.run(as_dict=True)} @frappe.whitelist() diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 79fe1d5b0f0..b6258f1880d 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -1433,7 +1433,7 @@ def add_operations_cost(stock_entry, work_order=None, expense_account=None): }, ) - def get_max_op_qty(): + def get_max_operation_quantity(): from frappe.query_builder.functions import Sum table = frappe.qb.DocType("Job Card") @@ -1449,7 +1449,7 @@ def add_operations_cost(stock_entry, work_order=None, expense_account=None): ) return min([d.qty for d in query.run(as_dict=True)], default=0) - def get_utilised_cc(): + def get_utilised_corrective_cost(): from frappe.query_builder.functions import Sum table = frappe.qb.DocType("Stock Entry") @@ -1479,15 +1479,15 @@ def add_operations_cost(stock_entry, work_order=None, expense_account=None): ) ) ): - max_qty = get_max_op_qty() - work_order.produced_qty - remaining_cc = work_order.corrective_operation_cost - get_utilised_cc() + max_qty = get_max_operation_quantity() - work_order.produced_qty + remaining_corrective_cost = work_order.corrective_operation_cost - get_utilised_corrective_cost() stock_entry.append( "additional_costs", { "expense_account": expense_account, "description": "Corrective Operation Cost", "has_corrective_cost": 1, - "amount": remaining_cc / max_qty * flt(stock_entry.fg_completed_qty), + "amount": remaining_corrective_cost / max_qty * flt(stock_entry.fg_completed_qty), }, ) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e1c1f8ece85..77d7f736715 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -260,6 +260,7 @@ erpnext.patches.v14_0.show_loan_management_deprecation_warning erpnext.patches.v14_0.clear_reconciliation_values_from_singles execute:frappe.rename_doc("Report", "TDS Payable Monthly", "Tax Withholding Details", force=True) erpnext.patches.v14_0.update_proprietorship_to_individual +erpnext.patches.v15_0.rename_subcontracting_fields [post_model_sync] erpnext.patches.v15_0.create_asset_depreciation_schedules_from_assets diff --git a/erpnext/patches/v15_0/rename_subcontracting_fields.py b/erpnext/patches/v15_0/rename_subcontracting_fields.py new file mode 100644 index 00000000000..d18d6149cac --- /dev/null +++ b/erpnext/patches/v15_0/rename_subcontracting_fields.py @@ -0,0 +1,7 @@ +import frappe +from frappe.model.utils.rename_field import rename_field + + +def execute(): + rename_field("Purchase Order Item", "sco_qty", "subcontracted_quantity") + rename_field("Subcontracting Order Item", "sc_conversion_factor", "subcontracting_conversion_factor") diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js index ffeff01c066..1e984809b95 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.js @@ -16,14 +16,14 @@ frappe.ui.form.on("Subcontracting Order Item", { service_item.doctype, service_item.name, "qty", - row.qty * row.sc_conversion_factor + row.qty * row.subcontracting_conversion_factor ); frappe.model.set_value(service_item.doctype, service_item.name, "fg_item_qty", row.qty); frappe.model.set_value( service_item.doctype, service_item.name, "amount", - row.qty * row.sc_conversion_factor * service_item.rate + row.qty * row.subcontracting_conversion_factor * service_item.rate ); }, before_items_remove(frm, cdt, cdn) { diff --git a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py index dee13195cfd..bdd17d57c95 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py +++ b/erpnext/subcontracting/doctype/subcontracting_order/subcontracting_order.py @@ -119,12 +119,12 @@ class SubcontractingOrder(SubcontractingController): def on_submit(self): self.update_prevdoc_status() self.update_status() - self.update_sco_qty_in_po() + self.update_subcontracted_quantity_in_po() def on_cancel(self): self.update_prevdoc_status() self.update_status() - self.update_sco_qty_in_po(cancel=True) + self.update_subcontracted_quantity_in_po(cancel=True) def validate_purchase_order_for_subcontracting(self): if self.purchase_order: @@ -162,7 +162,7 @@ class SubcontractingOrder(SubcontractingController): item = next( item for item in self.items if item.purchase_order_item == service_item.purchase_order_item ) - service_item.qty = item.qty * item.sc_conversion_factor + service_item.qty = item.qty * item.subcontracting_conversion_factor service_item.fg_item_qty = item.qty service_item.amount = service_item.qty * service_item.rate @@ -250,7 +250,7 @@ class SubcontractingOrder(SubcontractingController): item = frappe.get_doc("Item", si.fg_item) po_item = frappe.get_doc("Purchase Order Item", si.purchase_order_item) - available_qty = po_item.qty - po_item.sco_qty + available_qty = po_item.qty - po_item.subcontracted_quantity if available_qty == 0: continue @@ -276,7 +276,7 @@ class SubcontractingOrder(SubcontractingController): "schedule_date": self.schedule_date, "description": item.description, "qty": si.fg_item_qty, - "sc_conversion_factor": conversion_factor, + "subcontracting_conversion_factor": conversion_factor, "stock_uom": item.stock_uom, "bom": bom, "purchase_order_item": si.purchase_order_item, @@ -330,10 +330,14 @@ class SubcontractingOrder(SubcontractingController): self.update_ordered_qty_for_subcontracting() self.update_reserved_qty_for_subcontracting() - def update_sco_qty_in_po(self, cancel=False): + def update_subcontracted_quantity_in_po(self, cancel=False): for service_item in self.service_items: doc = frappe.get_doc("Purchase Order Item", service_item.purchase_order_item) - doc.sco_qty = (doc.sco_qty + service_item.qty) if not cancel else (doc.sco_qty - service_item.qty) + doc.subcontracted_quantity = ( + (doc.subcontracted_quantity + service_item.qty) + if not cancel + else (doc.subcontracted_quantity - service_item.qty) + ) doc.save() diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json index 25cc525018f..89f1c562eb0 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.json @@ -55,7 +55,7 @@ "section_break_34", "purchase_order_item", "page_break", - "sc_conversion_factor" + "subcontracting_conversion_factor" ], "fields": [ { @@ -403,18 +403,19 @@ "fieldtype": "Column Break" }, { - "fieldname": "sc_conversion_factor", + "fieldname": "subcontracting_conversion_factor", "fieldtype": "Float", "hidden": 1, - "label": "SC Conversion Factor", + "label": "Subcontracting Conversion Factor", "read_only": 1 } ], + "grid_page_length": 50, "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2024-12-13 13:35:28.935898", + "modified": "2025-03-02 17:05:28.386492", "modified_by": "Administrator", "module": "Subcontracting", "name": "Subcontracting Order Item", @@ -422,6 +423,7 @@ "owner": "Administrator", "permissions": [], "quick_entry": 1, + "row_format": "Dynamic", "search_fields": "item_name", "sort_field": "creation", "sort_order": "DESC", diff --git a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py index d8f2e5664e7..db49fccce3c 100644 --- a/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py +++ b/erpnext/subcontracting/doctype/subcontracting_order_item/subcontracting_order_item.py @@ -42,10 +42,10 @@ class SubcontractingOrderItem(Document): received_qty: DF.Float returned_qty: DF.Float rm_cost_per_qty: DF.Currency - sc_conversion_factor: DF.Float schedule_date: DF.Date | None service_cost_per_qty: DF.Currency stock_uom: DF.Link + subcontracting_conversion_factor: DF.Float warehouse: DF.Link # end: auto-generated types