mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-13 11:55:11 +00:00
chore: fix conflicts
This commit is contained in:
@@ -1693,419 +1693,6 @@ class TestProductionPlan(FrappeTestCase):
|
||||
self.assertEqual(mr_items[0].get("quantity"), 80)
|
||||
self.assertEqual(mr_items[1].get("quantity"), 70)
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
def test_stock_reservation_against_production_plan(self):
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
|
||||
from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
|
||||
from erpnext.stock.doctype.material_request.material_request import make_purchase_order
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
|
||||
frappe.db.set_single_value("Stock Settings", "enable_stock_reservation", 1)
|
||||
|
||||
bom_tree = {
|
||||
"Finished Good For SR": {
|
||||
"Sub Assembly For SR 1": {"Raw Material For SR 1": {}},
|
||||
"Sub Assembly For SR 2": {"Raw Material For SR 2": {}},
|
||||
"Sub Assembly For SR 3": {"Raw Material For SR 3": {}},
|
||||
}
|
||||
}
|
||||
parent_bom = create_nested_bom(bom_tree, prefix="")
|
||||
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
|
||||
for item_code in [
|
||||
"Sub Assembly For SR 1",
|
||||
"Sub Assembly For SR 2",
|
||||
"Sub Assembly For SR 3",
|
||||
"Raw Material For SR 1",
|
||||
"Raw Material For SR 2",
|
||||
"Raw Material For SR 3",
|
||||
]:
|
||||
make_stock_entry(item_code=item_code, target=warehouse, qty=5, basic_rate=100)
|
||||
|
||||
plan = create_production_plan(
|
||||
item_code=parent_bom.item,
|
||||
planned_qty=15,
|
||||
skip_available_sub_assembly_item=1,
|
||||
ignore_existing_ordered_qty=1,
|
||||
do_not_submit=1,
|
||||
warehouse=warehouse,
|
||||
sub_assembly_warehouse=warehouse,
|
||||
for_warehouse=warehouse,
|
||||
reserve_stock=1,
|
||||
)
|
||||
|
||||
plan.get_sub_assembly_items()
|
||||
plan.set("mr_items", [])
|
||||
mr_items = get_items_for_material_requests(plan.as_dict())
|
||||
for d in mr_items:
|
||||
plan.append("mr_items", d)
|
||||
|
||||
plan.save()
|
||||
|
||||
self.assertTrue(len(plan.sub_assembly_items) == 3)
|
||||
for row in plan.sub_assembly_items:
|
||||
self.assertEqual(row.required_qty, 15.0)
|
||||
self.assertEqual(row.qty, 10.0)
|
||||
|
||||
self.assertTrue(len(plan.mr_items) == 3)
|
||||
for row in plan.mr_items:
|
||||
self.assertEqual(row.required_bom_qty, 10.0)
|
||||
self.assertEqual(row.quantity, 5.0)
|
||||
|
||||
plan.submit()
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 6)
|
||||
|
||||
for row in reserved_entries:
|
||||
self.assertEqual(row.reserved_qty, 5.0)
|
||||
|
||||
plan.submit_material_request = 1
|
||||
plan.make_material_request()
|
||||
plan.make_work_order()
|
||||
|
||||
material_requests = frappe.get_all(
|
||||
"Material Request", filters={"production_plan": plan.name}, pluck="name"
|
||||
)
|
||||
|
||||
self.assertTrue(len(material_requests) > 0)
|
||||
for mr_name in list(set(material_requests)):
|
||||
po = make_purchase_order(mr_name)
|
||||
po.supplier = "_Test Supplier"
|
||||
po.submit()
|
||||
|
||||
pr = make_purchase_receipt(po.name)
|
||||
pr.submit()
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 9)
|
||||
|
||||
work_orders = frappe.get_all("Work Order", filters={"production_plan": plan.name}, pluck="name")
|
||||
for wo_name in list(set(work_orders)):
|
||||
wo_doc = frappe.get_doc("Work Order", wo_name)
|
||||
self.assertEqual(wo_doc.reserve_stock, 1)
|
||||
|
||||
wo_doc.source_warehouse = warehouse
|
||||
wo_doc.wip_warehouse = warehouse
|
||||
wo_doc.fg_warehouse = warehouse
|
||||
wo_doc.submit()
|
||||
|
||||
sre = StockReservation(wo_doc)
|
||||
reserved_entries = sre.get_reserved_entries("Work Order", wo_doc.name)
|
||||
if wo_doc.production_item == "Finished Good For SR":
|
||||
self.assertEqual(len(reserved_entries), 3)
|
||||
else:
|
||||
# For raw materials 2 stock reservation entries
|
||||
# 5 qty was present already in stock and 5 added from new PO
|
||||
self.assertEqual(len(reserved_entries), 2)
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 0)
|
||||
frappe.db.set_single_value("Stock Settings", "enable_stock_reservation", 0)
|
||||
|
||||
def test_stock_reservation_of_serial_nos_against_production_plan(self):
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
|
||||
from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
|
||||
from erpnext.stock.doctype.material_request.material_request import make_purchase_order
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
|
||||
frappe.db.set_single_value("Stock Settings", "enable_stock_reservation", 1)
|
||||
|
||||
bom_tree = {
|
||||
"Finished Good For SR": {
|
||||
"SN Sub Assembly For SR 1": {"SN Raw Material For SR 1": {}},
|
||||
"SN Sub Assembly For SR 2": {"SN Raw Material For SR 2": {}},
|
||||
"SN Sub Assembly For SR 3": {"SN Raw Material For SR 3": {}},
|
||||
}
|
||||
}
|
||||
parent_bom = create_nested_bom(bom_tree, prefix="")
|
||||
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
|
||||
for item_code in [
|
||||
"SN Sub Assembly For SR 1",
|
||||
"SN Sub Assembly For SR 2",
|
||||
"SN Sub Assembly For SR 3",
|
||||
"SN Raw Material For SR 1",
|
||||
"SN Raw Material For SR 2",
|
||||
"SN Raw Material For SR 3",
|
||||
]:
|
||||
doc = frappe.get_doc("Item", item_code)
|
||||
doc.has_serial_no = 1
|
||||
doc.serial_no_series = f"SNN-{item_code}.-.#####"
|
||||
doc.save()
|
||||
|
||||
make_stock_entry(item_code=item_code, target=warehouse, qty=5, basic_rate=100)
|
||||
|
||||
plan = create_production_plan(
|
||||
item_code=parent_bom.item,
|
||||
planned_qty=15,
|
||||
skip_available_sub_assembly_item=1,
|
||||
ignore_existing_ordered_qty=1,
|
||||
do_not_submit=1,
|
||||
warehouse=warehouse,
|
||||
sub_assembly_warehouse=warehouse,
|
||||
for_warehouse=warehouse,
|
||||
reserve_stock=1,
|
||||
)
|
||||
|
||||
plan.get_sub_assembly_items()
|
||||
plan.set("mr_items", [])
|
||||
mr_items = get_items_for_material_requests(plan.as_dict())
|
||||
for d in mr_items:
|
||||
plan.append("mr_items", d)
|
||||
|
||||
plan.save()
|
||||
|
||||
self.assertTrue(len(plan.sub_assembly_items) == 3)
|
||||
for row in plan.sub_assembly_items:
|
||||
self.assertEqual(row.required_qty, 15.0)
|
||||
self.assertEqual(row.qty, 10.0)
|
||||
|
||||
self.assertTrue(len(plan.mr_items) == 3)
|
||||
for row in plan.mr_items:
|
||||
self.assertEqual(row.required_bom_qty, 10.0)
|
||||
self.assertEqual(row.quantity, 5.0)
|
||||
|
||||
plan.submit()
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 6)
|
||||
|
||||
for row in reserved_entries:
|
||||
self.assertEqual(row.reserved_qty, 5.0)
|
||||
|
||||
plan.submit_material_request = 1
|
||||
plan.make_material_request()
|
||||
plan.make_work_order()
|
||||
|
||||
material_requests = frappe.get_all(
|
||||
"Material Request", filters={"production_plan": plan.name}, pluck="name"
|
||||
)
|
||||
|
||||
additional_serial_nos = []
|
||||
|
||||
for item_code in [
|
||||
"SN Sub Assembly For SR 1",
|
||||
"SN Sub Assembly For SR 2",
|
||||
"SN Sub Assembly For SR 3",
|
||||
"SN Raw Material For SR 1",
|
||||
"SN Raw Material For SR 2",
|
||||
"SN Raw Material For SR 3",
|
||||
]:
|
||||
se = make_stock_entry(item_code=item_code, target=warehouse, qty=5, basic_rate=100)
|
||||
additional_serial_nos.extend(get_serial_nos_from_bundle(se.items[0].serial_and_batch_bundle))
|
||||
|
||||
self.assertTrue(additional_serial_nos)
|
||||
|
||||
self.assertTrue(len(material_requests) > 0)
|
||||
for mr_name in list(set(material_requests)):
|
||||
po = make_purchase_order(mr_name)
|
||||
po.supplier = "_Test Supplier"
|
||||
po.submit()
|
||||
|
||||
pr = make_purchase_receipt(po.name)
|
||||
pr.submit()
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 9)
|
||||
serial_nos_res_for_pp = frappe.get_all(
|
||||
"Serial and Batch Entry",
|
||||
filters={"parent": ("in", [x.name for x in reserved_entries]), "docstatus": 1},
|
||||
pluck="serial_no",
|
||||
)
|
||||
|
||||
work_orders = frappe.get_all("Work Order", filters={"production_plan": plan.name}, pluck="name")
|
||||
for wo_name in list(set(work_orders)):
|
||||
wo_doc = frappe.get_doc("Work Order", wo_name)
|
||||
self.assertEqual(wo_doc.reserve_stock, 1)
|
||||
|
||||
wo_doc.source_warehouse = warehouse
|
||||
wo_doc.wip_warehouse = warehouse
|
||||
wo_doc.fg_warehouse = warehouse
|
||||
wo_doc.submit()
|
||||
|
||||
sre = StockReservation(wo_doc)
|
||||
reserved_entries = sre.get_reserved_entries("Work Order", wo_doc.name)
|
||||
serial_nos_res_for_wo = frappe.get_all(
|
||||
"Serial and Batch Entry",
|
||||
filters={"parent": ("in", [x.name for x in reserved_entries]), "docstatus": 1},
|
||||
pluck="serial_no",
|
||||
)
|
||||
|
||||
for serial_no in serial_nos_res_for_wo:
|
||||
self.assertTrue(serial_no in serial_nos_res_for_pp)
|
||||
self.assertFalse(serial_no in additional_serial_nos)
|
||||
|
||||
if wo_doc.production_item == "Finished Good For SR":
|
||||
self.assertEqual(len(reserved_entries), 3)
|
||||
else:
|
||||
# For raw materials 2 stock reservation entries
|
||||
# 5 qty was present already in stock and 5 added from new PO
|
||||
self.assertEqual(len(reserved_entries), 2)
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 0)
|
||||
frappe.db.set_single_value("Stock Settings", "enable_stock_reservation", 0)
|
||||
|
||||
def test_stock_reservation_of_batch_nos_against_production_plan(self):
|
||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
|
||||
from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
|
||||
from erpnext.stock.doctype.material_request.material_request import make_purchase_order
|
||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||
|
||||
frappe.db.set_single_value("Stock Settings", "enable_stock_reservation", 1)
|
||||
|
||||
bom_tree = {
|
||||
"Finished Good For SR": {
|
||||
"Batch Sub Assembly For SR 1": {"Batch Raw Material For SR 1": {}},
|
||||
"Batch Sub Assembly For SR 2": {"Batch Raw Material For SR 2": {}},
|
||||
"Batch Sub Assembly For SR 3": {"Batch Raw Material For SR 3": {}},
|
||||
}
|
||||
}
|
||||
parent_bom = create_nested_bom(bom_tree, prefix="")
|
||||
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
|
||||
for item_code in [
|
||||
"Batch Sub Assembly For SR 1",
|
||||
"Batch Sub Assembly For SR 2",
|
||||
"Batch Sub Assembly For SR 3",
|
||||
"Batch Raw Material For SR 1",
|
||||
"Batch Raw Material For SR 2",
|
||||
"Batch Raw Material For SR 3",
|
||||
]:
|
||||
doc = frappe.get_doc("Item", item_code)
|
||||
doc.has_batch_no = 1
|
||||
doc.create_new_batch = 1
|
||||
doc.batch_number_series = f"BCH-{item_code}.-.#####"
|
||||
doc.save()
|
||||
|
||||
make_stock_entry(item_code=item_code, target=warehouse, qty=5, basic_rate=100)
|
||||
|
||||
plan = create_production_plan(
|
||||
item_code=parent_bom.item,
|
||||
planned_qty=15,
|
||||
skip_available_sub_assembly_item=1,
|
||||
ignore_existing_ordered_qty=1,
|
||||
do_not_submit=1,
|
||||
warehouse=warehouse,
|
||||
sub_assembly_warehouse=warehouse,
|
||||
for_warehouse=warehouse,
|
||||
reserve_stock=1,
|
||||
)
|
||||
|
||||
plan.get_sub_assembly_items()
|
||||
plan.set("mr_items", [])
|
||||
mr_items = get_items_for_material_requests(plan.as_dict())
|
||||
for d in mr_items:
|
||||
plan.append("mr_items", d)
|
||||
|
||||
plan.save()
|
||||
|
||||
self.assertTrue(len(plan.sub_assembly_items) == 3)
|
||||
for row in plan.sub_assembly_items:
|
||||
self.assertEqual(row.required_qty, 15.0)
|
||||
self.assertEqual(row.qty, 10.0)
|
||||
|
||||
self.assertTrue(len(plan.mr_items) == 3)
|
||||
for row in plan.mr_items:
|
||||
self.assertEqual(row.required_bom_qty, 10.0)
|
||||
self.assertEqual(row.quantity, 5.0)
|
||||
|
||||
plan.submit()
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 6)
|
||||
|
||||
for row in reserved_entries:
|
||||
self.assertEqual(row.reserved_qty, 5.0)
|
||||
|
||||
plan.submit_material_request = 1
|
||||
plan.make_material_request()
|
||||
plan.make_work_order()
|
||||
|
||||
material_requests = frappe.get_all(
|
||||
"Material Request", filters={"production_plan": plan.name}, pluck="name"
|
||||
)
|
||||
|
||||
additional_batches = []
|
||||
|
||||
for item_code in [
|
||||
"Batch Sub Assembly For SR 1",
|
||||
"Batch Sub Assembly For SR 2",
|
||||
"Batch Sub Assembly For SR 3",
|
||||
"Batch Raw Material For SR 1",
|
||||
"Batch Raw Material For SR 2",
|
||||
"Batch Raw Material For SR 3",
|
||||
]:
|
||||
se = make_stock_entry(item_code=item_code, target=warehouse, qty=5, basic_rate=100)
|
||||
batch_no = get_batch_from_bundle(se.items[0].serial_and_batch_bundle)
|
||||
additional_batches.append(batch_no)
|
||||
|
||||
self.assertTrue(additional_batches)
|
||||
|
||||
self.assertTrue(len(material_requests) > 0)
|
||||
for mr_name in list(set(material_requests)):
|
||||
po = make_purchase_order(mr_name)
|
||||
po.supplier = "_Test Supplier"
|
||||
po.submit()
|
||||
|
||||
pr = make_purchase_receipt(po.name)
|
||||
pr.submit()
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 9)
|
||||
batches_reserved_for_pp = frappe.get_all(
|
||||
"Serial and Batch Entry",
|
||||
filters={"parent": ("in", [x.name for x in reserved_entries]), "docstatus": 1},
|
||||
pluck="batch_no",
|
||||
)
|
||||
|
||||
work_orders = frappe.get_all("Work Order", filters={"production_plan": plan.name}, pluck="name")
|
||||
for wo_name in list(set(work_orders)):
|
||||
wo_doc = frappe.get_doc("Work Order", wo_name)
|
||||
self.assertEqual(wo_doc.reserve_stock, 1)
|
||||
|
||||
wo_doc.source_warehouse = warehouse
|
||||
wo_doc.wip_warehouse = warehouse
|
||||
wo_doc.fg_warehouse = warehouse
|
||||
wo_doc.submit()
|
||||
|
||||
sre = StockReservation(wo_doc)
|
||||
reserved_entries = sre.get_reserved_entries("Work Order", wo_doc.name)
|
||||
batches_reserved_for_wo = frappe.get_all(
|
||||
"Serial and Batch Entry",
|
||||
filters={"parent": ("in", [x.name for x in reserved_entries]), "docstatus": 1},
|
||||
pluck="batch_no",
|
||||
)
|
||||
|
||||
for batch_no in batches_reserved_for_wo:
|
||||
self.assertTrue(batch_no in batches_reserved_for_pp)
|
||||
self.assertFalse(batch_no in additional_batches)
|
||||
|
||||
if wo_doc.production_item == "Finished Good For SR":
|
||||
self.assertEqual(len(reserved_entries), 3)
|
||||
else:
|
||||
# For raw materials 2 stock reservation entries
|
||||
# 5 qty was present already in stock and 5 added from new PO
|
||||
self.assertEqual(len(reserved_entries), 2)
|
||||
|
||||
sre = StockReservation(plan)
|
||||
reserved_entries = sre.get_reserved_entries("Production Plan", plan.name)
|
||||
self.assertTrue(len(reserved_entries) == 0)
|
||||
frappe.db.set_single_value("Stock Settings", "enable_stock_reservation", 0)
|
||||
|
||||
def test_production_plan_for_partial_sub_assembly_items(self):
|
||||
from erpnext.controllers.status_updater import OverAllowanceError
|
||||
from erpnext.manufacturing.doctype.bom.test_bom import create_nested_bom
|
||||
@@ -2163,7 +1750,6 @@ class TestProductionPlan(FrappeTestCase):
|
||||
for row in plan.sub_assembly_items:
|
||||
self.assertEqual(row.ordered_qty, 10.0)
|
||||
|
||||
>>>>>>> 384f4e120a (fix: do not create repeat work orders)
|
||||
|
||||
def create_production_plan(**args):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user