Merge branch 'develop' into so-mr-wo-back-update
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d104bc0..c26451a 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -352,3 +352,4 @@
erpnext.patches.v13_0.update_disbursement_account
erpnext.patches.v13_0.update_reserved_qty_closed_wo
erpnext.patches.v14_0.delete_amazon_mws_doctype
+erpnext.patches.v14_0.set_work_order_qty_in_so_from_mr
diff --git a/erpnext/patches/v14_0/set_work_order_qty_in_so_from_mr.py b/erpnext/patches/v14_0/set_work_order_qty_in_so_from_mr.py
new file mode 100644
index 0000000..f097ab9
--- /dev/null
+++ b/erpnext/patches/v14_0/set_work_order_qty_in_so_from_mr.py
@@ -0,0 +1,36 @@
+import frappe
+
+
+def execute():
+ """
+ 1. Get submitted Work Orders with MR, MR Item and SO set
+ 2. Get SO Item detail from MR Item detail in WO, and set in WO
+ 3. Update work_order_qty in SO
+ """
+ work_order = frappe.qb.DocType("Work Order")
+ query = (
+ frappe.qb.from_(work_order)
+ .select(
+ work_order.name, work_order.produced_qty,
+ work_order.material_request,
+ work_order.material_request_item,
+ work_order.sales_order
+ ).where(
+ (work_order.material_request.isnotnull())
+ & (work_order.material_request_item.isnotnull())
+ & (work_order.sales_order.isnotnull())
+ & (work_order.docstatus == 1)
+ & (work_order.produced_qty > 0)
+ )
+ )
+ results = query.run(as_dict=True)
+
+ for row in results:
+ so_item = frappe.get_value(
+ "Material Request Item", row.material_request_item, "sales_order_item"
+ )
+ frappe.db.set_value("Work Order", row.name, "sales_order_item", so_item)
+
+ if so_item:
+ wo = frappe.get_doc("Work Order", row.name)
+ wo.update_work_order_qty_in_so()
diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py
index acf048e..73c5bd2 100644
--- a/erpnext/selling/doctype/sales_order/test_sales_order.py
+++ b/erpnext/selling/doctype/sales_order/test_sales_order.py
@@ -6,7 +6,7 @@
import frappe
import frappe.permissions
from frappe.core.doctype.user_permission.test_user_permission import create_user
-from frappe.utils import add_days, flt, getdate, nowdate
+from frappe.utils import add_days, flt, getdate, nowdate, today
from erpnext.controllers.accounts_controller import update_child_qty_rate
from erpnext.maintenance.doctype.maintenance_schedule.test_maintenance_schedule import (
@@ -1399,6 +1399,48 @@
so.load_from_db()
self.assertEqual(so.billing_status, 'Fully Billed')
+ def test_so_back_updated_from_wo_via_mr(self):
+ "SO -> MR (Manufacture) -> WO. Test if WO Qty is updated in SO."
+ from erpnext.manufacturing.doctype.work_order.work_order import (
+ make_stock_entry as make_se_from_wo,
+ )
+ from erpnext.stock.doctype.material_request.material_request import raise_work_orders
+
+ so = make_sales_order(item_list=[{"item_code": "_Test FG Item","qty": 2, "rate":100}])
+
+ mr = make_material_request(so.name)
+ mr.material_request_type = "Manufacture"
+ mr.schedule_date = today()
+ mr.submit()
+
+ # WO from MR
+ wo_name = raise_work_orders(mr.name)[0]
+ wo = frappe.get_doc("Work Order", wo_name)
+ wo.wip_warehouse = "Work In Progress - _TC"
+ wo.skip_transfer = True
+
+ self.assertEqual(wo.sales_order, so.name)
+ self.assertEqual(wo.sales_order_item, so.items[0].name)
+
+ wo.submit()
+ make_stock_entry(item_code="_Test Item", # Stock RM
+ target="Work In Progress - _TC",
+ qty=4, basic_rate=100
+ )
+ make_stock_entry(item_code="_Test Item Home Desktop 100", # Stock RM
+ target="Work In Progress - _TC",
+ qty=4, basic_rate=100
+ )
+
+ se = frappe.get_doc(make_se_from_wo(wo.name, "Manufacture", 2))
+ se.submit() # Finish WO
+
+ mr.reload()
+ wo.reload()
+ so.reload()
+ self.assertEqual(so.items[0].work_order_qty, wo.produced_qty)
+ self.assertEqual(mr.status, "Manufactured")
+
def automatically_fetch_payment_terms(enable=1):
accounts_settings = frappe.get_doc("Accounts Settings")
accounts_settings.automatically_fetch_payment_terms = enable
diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py
index 103e8d6..b39328f 100644
--- a/erpnext/stock/doctype/material_request/material_request.py
+++ b/erpnext/stock/doctype/material_request/material_request.py
@@ -533,6 +533,7 @@
"stock_uom": d.stock_uom,
"expected_delivery_date": d.schedule_date,
"sales_order": d.sales_order,
+ "sales_order_item": d.get("sales_order_item"),
"bom_no": get_item_details(d.item_code).bom_no,
"material_request": mr.name,
"material_request_item": d.name,