diff --git a/erpnext/patches.txt b/erpnext/patches.txt index a4c5ea1ff8f..624230e0171 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -468,4 +468,5 @@ erpnext.patches.v15_0.replace_http_with_https_in_sales_partner erpnext.patches.v16_0.migrate_asset_type_checkboxes_to_select erpnext.patches.v15_0.delete_quotation_lost_record_detail erpnext.patches.v16_0.add_portal_redirects -erpnext.patches.v16_0.complete_onboarding_steps_for_older_sites #2 \ No newline at end of file +erpnext.patches.v16_0.update_order_qty_and_requested_qty_based_on_mr_and_po +erpnext.patches.v16_0.complete_onboarding_steps_for_older_sites #2 diff --git a/erpnext/patches/v16_0/update_order_qty_and_requested_qty_based_on_mr_and_po.py b/erpnext/patches/v16_0/update_order_qty_and_requested_qty_based_on_mr_and_po.py new file mode 100644 index 00000000000..59a84ec11d0 --- /dev/null +++ b/erpnext/patches/v16_0/update_order_qty_and_requested_qty_based_on_mr_and_po.py @@ -0,0 +1,33 @@ +import frappe +from frappe.query_builder import DocType +from frappe.query_builder.functions import Sum + + +def execute(): + PurchaseOrderItem = DocType("Purchase Order Item") + MaterialRequestItem = DocType("Material Request Item") + + poi_query = ( + frappe.qb.from_(PurchaseOrderItem) + .select(PurchaseOrderItem.sales_order_item, Sum(PurchaseOrderItem.stock_qty)) + .where(PurchaseOrderItem.sales_order_item.isnotnull() & PurchaseOrderItem.docstatus == 1) + .groupby(PurchaseOrderItem.sales_order_item) + ) + + mri_query = ( + frappe.qb.from_(MaterialRequestItem) + .select(MaterialRequestItem.sales_order_item, Sum(MaterialRequestItem.stock_qty)) + .where(MaterialRequestItem.sales_order_item.isnotnull() & MaterialRequestItem.docstatus == 1) + .groupby(MaterialRequestItem.sales_order_item) + ) + + poi_data = poi_query.run() + mri_data = mri_query.run() + + updates_against_poi = {data[0]: {"ordered_qty": data[1]} for data in poi_data} + updates_against_mri = {data[0]: {"requested_qty": data[1], "ordered_qty": 0} for data in mri_data} + + frappe.db.auto_commit_on_many_writes = 1 + frappe.db.bulk_update("Sales Order Item", updates_against_mri) + frappe.db.bulk_update("Sales Order Item", updates_against_poi) + frappe.db.auto_commit_on_many_writes = 0 diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json index 312b882a7df..e6f8ac8696f 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -95,6 +95,7 @@ "ordered_qty", "planned_qty", "production_plan_qty", + "requested_qty", "column_break_69", "work_order_qty", "delivered_qty", @@ -1010,6 +1011,14 @@ "fieldtype": "Float", "label": "Finished Good Qty", "mandatory_depends_on": "eval:parent.is_subcontracted" + }, + { + "fieldname": "requested_qty", + "fieldtype": "Float", + "label": "Requested Qty", + "no_copy": 1, + "print_hide": 1, + "read_only": 1 } ], "grid_page_length": 50, diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.py b/erpnext/selling/doctype/sales_order_item/sales_order_item.py index 9128f8a3e41..98298f22036 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.py +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.py @@ -80,6 +80,7 @@ class SalesOrderItem(Document): quotation_item: DF.Data | None rate: DF.Currency rate_with_margin: DF.Currency + requested_qty: DF.Float reserve_stock: DF.Check returned_qty: DF.Float stock_qty: DF.Float diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 5c383cb469e..b4e6101aa0d 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -92,7 +92,7 @@ class MaterialRequest(BuyingController): { "source_dt": "Material Request Item", "target_dt": "Sales Order Item", - "target_field": "ordered_qty", + "target_field": "requested_qty", "target_parent_dt": "Sales Order", "target_parent_field": "", "join_field": "sales_order_item", @@ -282,6 +282,8 @@ class MaterialRequest(BuyingController): def on_cancel(self): self.update_requested_qty_in_production_plan(cancel=True) self.update_requested_qty() + if self.material_request_type == "Purchase": + self.update_prevdoc_status() def get_mr_items_ordered_qty(self, mr_items): mr_items_ordered_qty = {}