Merge pull request #29715 from aaronmenezes/fix_reserved_for_production_calc
fix: Reserved for Production calculation considered closed work orders
This commit is contained in:
commit
2abc1c244e
@ -201,6 +201,21 @@ class TestWorkOrder(ERPNextTestCase):
|
|||||||
self.assertEqual(cint(bin1_on_end_production.reserved_qty_for_production),
|
self.assertEqual(cint(bin1_on_end_production.reserved_qty_for_production),
|
||||||
cint(bin1_on_start_production.reserved_qty_for_production))
|
cint(bin1_on_start_production.reserved_qty_for_production))
|
||||||
|
|
||||||
|
def test_reserved_qty_for_production_closed(self):
|
||||||
|
|
||||||
|
wo1 = make_wo_order_test_record(item="_Test FG Item", qty=2,
|
||||||
|
source_warehouse=self.warehouse)
|
||||||
|
item = wo1.required_items[0].item_code
|
||||||
|
bin_before = get_bin(item, self.warehouse)
|
||||||
|
bin_before.update_reserved_qty_for_production()
|
||||||
|
|
||||||
|
make_wo_order_test_record(item="_Test FG Item", qty=2,
|
||||||
|
source_warehouse=self.warehouse)
|
||||||
|
close_work_order(wo1.name, "Closed")
|
||||||
|
|
||||||
|
bin_after = get_bin(item, self.warehouse)
|
||||||
|
self.assertEqual(bin_before.reserved_qty_for_production, bin_after.reserved_qty_for_production)
|
||||||
|
|
||||||
def test_backflush_qty_for_overpduction_manufacture(self):
|
def test_backflush_qty_for_overpduction_manufacture(self):
|
||||||
cancel_stock_entry = []
|
cancel_stock_entry = []
|
||||||
allow_overproduction("overproduction_percentage_for_work_order", 30)
|
allow_overproduction("overproduction_percentage_for_work_order", 30)
|
||||||
|
@ -8,6 +8,8 @@ from dateutil.relativedelta import relativedelta
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
|
from frappe.query_builder import Case
|
||||||
|
from frappe.query_builder.functions import Sum
|
||||||
from frappe.utils import (
|
from frappe.utils import (
|
||||||
cint,
|
cint,
|
||||||
date_diff,
|
date_diff,
|
||||||
@ -1175,3 +1177,27 @@ def create_pick_list(source_name, target_doc=None, for_qty=None):
|
|||||||
doc.set_item_locations()
|
doc.set_item_locations()
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
def get_reserved_qty_for_production(item_code: str, warehouse: str) -> float:
|
||||||
|
"""Get total reserved quantity for any item in specified warehouse"""
|
||||||
|
wo = frappe.qb.DocType("Work Order")
|
||||||
|
wo_item = frappe.qb.DocType("Work Order Item")
|
||||||
|
|
||||||
|
return (
|
||||||
|
frappe.qb
|
||||||
|
.from_(wo)
|
||||||
|
.from_(wo_item)
|
||||||
|
.select(Sum(Case()
|
||||||
|
.when(wo.skip_transfer == 0, wo_item.required_qty - wo_item.transferred_qty)
|
||||||
|
.else_(wo_item.required_qty - wo_item.consumed_qty))
|
||||||
|
)
|
||||||
|
.where(
|
||||||
|
(wo_item.item_code == item_code)
|
||||||
|
& (wo_item.parent == wo.name)
|
||||||
|
& (wo.docstatus == 1)
|
||||||
|
& (wo_item.source_warehouse == warehouse)
|
||||||
|
& (wo.status.notin(["Stopped", "Completed", "Closed"]))
|
||||||
|
& ((wo_item.required_qty > wo_item.transferred_qty)
|
||||||
|
| (wo_item.required_qty > wo_item.consumed_qty))
|
||||||
|
)
|
||||||
|
).run()[0][0] or 0.0
|
||||||
|
@ -350,3 +350,4 @@ erpnext.patches.v14_0.migrate_cost_center_allocations
|
|||||||
erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
|
erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
|
||||||
erpnext.patches.v13_0.shopping_cart_to_ecommerce
|
erpnext.patches.v13_0.shopping_cart_to_ecommerce
|
||||||
erpnext.patches.v13_0.update_disbursement_account
|
erpnext.patches.v13_0.update_disbursement_account
|
||||||
|
erpnext.patches.v13_0.update_reserved_qty_closed_wo
|
||||||
|
28
erpnext/patches/v13_0/update_reserved_qty_closed_wo.py
Normal file
28
erpnext/patches/v13_0/update_reserved_qty_closed_wo.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
from erpnext.stock.utils import get_bin
|
||||||
|
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
|
||||||
|
wo = frappe.qb.DocType("Work Order")
|
||||||
|
wo_item = frappe.qb.DocType("Work Order Item")
|
||||||
|
|
||||||
|
incorrect_item_wh = (
|
||||||
|
frappe.qb
|
||||||
|
.from_(wo)
|
||||||
|
.join(wo_item).on(wo.name == wo_item.parent)
|
||||||
|
.select(wo_item.item_code, wo.source_warehouse).distinct()
|
||||||
|
.where(
|
||||||
|
(wo.status == "Closed")
|
||||||
|
& (wo.docstatus == 1)
|
||||||
|
& (wo.source_warehouse.notnull())
|
||||||
|
)
|
||||||
|
).run()
|
||||||
|
|
||||||
|
for item_code, warehouse in incorrect_item_wh:
|
||||||
|
if not (item_code and warehouse):
|
||||||
|
continue
|
||||||
|
|
||||||
|
bin = get_bin(item_code, warehouse)
|
||||||
|
bin.update_reserved_qty_for_production()
|
@ -35,28 +35,9 @@ class Bin(Document):
|
|||||||
def update_reserved_qty_for_production(self):
|
def update_reserved_qty_for_production(self):
|
||||||
'''Update qty reserved for production from Production Item tables
|
'''Update qty reserved for production from Production Item tables
|
||||||
in open work orders'''
|
in open work orders'''
|
||||||
|
from erpnext.manufacturing.doctype.work_order.work_order import get_reserved_qty_for_production
|
||||||
|
|
||||||
wo = frappe.qb.DocType("Work Order")
|
self.reserved_qty_for_production = get_reserved_qty_for_production(self.item_code, self.warehouse)
|
||||||
wo_item = frappe.qb.DocType("Work Order Item")
|
|
||||||
|
|
||||||
self.reserved_qty_for_production = (
|
|
||||||
frappe.qb
|
|
||||||
.from_(wo)
|
|
||||||
.from_(wo_item)
|
|
||||||
.select(Sum(Case()
|
|
||||||
.when(wo.skip_transfer == 0, wo_item.required_qty - wo_item.transferred_qty)
|
|
||||||
.else_(wo_item.required_qty - wo_item.consumed_qty))
|
|
||||||
)
|
|
||||||
.where(
|
|
||||||
(wo_item.item_code == self.item_code)
|
|
||||||
& (wo_item.parent == wo.name)
|
|
||||||
& (wo.docstatus == 1)
|
|
||||||
& (wo_item.source_warehouse == self.warehouse)
|
|
||||||
& (wo.status.notin(["Stopped", "Completed"]))
|
|
||||||
& ((wo_item.required_qty > wo_item.transferred_qty)
|
|
||||||
| (wo_item.required_qty > wo_item.consumed_qty))
|
|
||||||
)
|
|
||||||
).run()[0][0] or 0.0
|
|
||||||
|
|
||||||
self.set_projected_qty()
|
self.set_projected_qty()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user