mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-20 09:49:58 +00:00
fix(stock): restore subcontracting inward warehouse checks (#58183)
This commit is contained in:
@@ -14,6 +14,7 @@ class MaterialReceiptStockEntry(BaseStockEntry):
|
||||
self.validate_warehouse()
|
||||
|
||||
def set_default_warehouse(self):
|
||||
self.doc.from_warehouse = None
|
||||
for row in self.doc.items:
|
||||
row.s_warehouse = None
|
||||
if not row.t_warehouse and self.doc.to_warehouse:
|
||||
@@ -27,6 +28,7 @@ class MaterialReceiptStockEntry(BaseStockEntry):
|
||||
|
||||
class BaseMaterialIssueStockEntry(BaseStockEntry):
|
||||
def set_default_warehouse(self):
|
||||
self.doc.to_warehouse = None
|
||||
for row in self.doc.items:
|
||||
row.t_warehouse = None
|
||||
if not row.s_warehouse and self.doc.from_warehouse:
|
||||
@@ -38,13 +40,15 @@ class BaseMaterialIssueStockEntry(BaseStockEntry):
|
||||
frappe.throw(_("Source Warehouse is required for item {0}").format(row.item_code))
|
||||
|
||||
|
||||
class MaterialIssueStockEntry(BaseMaterialIssueStockEntry):
|
||||
class SourceOnlyStockEntry(BaseMaterialIssueStockEntry):
|
||||
def before_validate(self):
|
||||
self.set_default_warehouse()
|
||||
|
||||
def validate(self):
|
||||
self.validate_warehouse()
|
||||
|
||||
|
||||
class MaterialIssueStockEntry(SourceOnlyStockEntry):
|
||||
def add_items(self):
|
||||
self.add_raw_materials_based_on_bom()
|
||||
|
||||
|
||||
@@ -627,13 +627,15 @@ frappe.ui.form.on("Stock Entry", {
|
||||
frm.fields_dict["items"].grid.update_docfield_property(
|
||||
"s_warehouse",
|
||||
"in_list_view",
|
||||
!["Material Receipt", "Receive from Customer"].includes(frm.doc.purpose)
|
||||
!["Material Receipt", "Receive from Customer", "Subcontracting Return"].includes(frm.doc.purpose)
|
||||
);
|
||||
|
||||
frm.fields_dict["items"].grid.update_docfield_property(
|
||||
"t_warehouse",
|
||||
"in_list_view",
|
||||
!["Material Issue"].includes(frm.doc.purpose)
|
||||
!["Material Issue", "Return Raw Material to Customer", "Subcontracting Delivery"].includes(
|
||||
frm.doc.purpose
|
||||
)
|
||||
);
|
||||
|
||||
frm.fields_dict["items"].grid.reset_grid();
|
||||
|
||||
@@ -45,7 +45,11 @@ from .services.manufacturing import (
|
||||
OperationsNotCompleteError,
|
||||
RepackStockEntry,
|
||||
)
|
||||
from .services.material_receipt_issue import MaterialIssueStockEntry, MaterialReceiptStockEntry
|
||||
from .services.material_receipt_issue import (
|
||||
MaterialIssueStockEntry,
|
||||
MaterialReceiptStockEntry,
|
||||
SourceOnlyStockEntry,
|
||||
)
|
||||
from .services.material_transfer import (
|
||||
MaterialRequestStockEntry,
|
||||
MaterialTransferForManufactureStockEntry,
|
||||
@@ -216,6 +220,10 @@ class StockEntry(StockController, SubcontractingInwardController):
|
||||
"Send to Subcontractor": SendToSubcontractorStockEntry,
|
||||
"Material Issue": MaterialIssueStockEntry,
|
||||
"Material Receipt": MaterialReceiptStockEntry,
|
||||
"Receive from Customer": MaterialReceiptStockEntry,
|
||||
"Return Raw Material to Customer": SourceOnlyStockEntry,
|
||||
"Subcontracting Delivery": SourceOnlyStockEntry,
|
||||
"Subcontracting Return": MaterialReceiptStockEntry,
|
||||
}
|
||||
|
||||
self.purpose_cls = purpose_map.get(self.purpose)
|
||||
|
||||
@@ -61,6 +61,71 @@ class TestStockEntry(ERPNextTestSuite):
|
||||
self.load_test_records("Stock Entry")
|
||||
frappe.local.flags.dont_execute_stock_reposts = False
|
||||
|
||||
def test_subcontracting_inward_warehouse_direction(self):
|
||||
source_warehouse = "_Test Warehouse - _TC"
|
||||
target_warehouse = "_Test Warehouse 1 - _TC"
|
||||
|
||||
for purpose in ("Return Raw Material to Customer", "Subcontracting Delivery"):
|
||||
with self.subTest(purpose=purpose):
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry.purpose = purpose
|
||||
stock_entry.from_warehouse = source_warehouse
|
||||
stock_entry.to_warehouse = target_warehouse
|
||||
stock_entry.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": "_Test Item",
|
||||
"t_warehouse": target_warehouse,
|
||||
"cost_center": "Main - _TC",
|
||||
},
|
||||
)
|
||||
|
||||
stock_entry.before_validate()
|
||||
|
||||
self.assertEqual(stock_entry.from_warehouse, source_warehouse)
|
||||
self.assertIsNone(stock_entry.to_warehouse)
|
||||
self.assertEqual(stock_entry.items[0].s_warehouse, source_warehouse)
|
||||
self.assertIsNone(stock_entry.items[0].t_warehouse)
|
||||
|
||||
for purpose in ("Receive from Customer", "Subcontracting Return"):
|
||||
with self.subTest(purpose=purpose):
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry.purpose = purpose
|
||||
stock_entry.from_warehouse = source_warehouse
|
||||
stock_entry.to_warehouse = target_warehouse
|
||||
stock_entry.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": "_Test Item",
|
||||
"s_warehouse": source_warehouse,
|
||||
"cost_center": "Main - _TC",
|
||||
},
|
||||
)
|
||||
|
||||
stock_entry.before_validate()
|
||||
|
||||
self.assertIsNone(stock_entry.from_warehouse)
|
||||
self.assertEqual(stock_entry.to_warehouse, target_warehouse)
|
||||
self.assertIsNone(stock_entry.items[0].s_warehouse)
|
||||
self.assertEqual(stock_entry.items[0].t_warehouse, target_warehouse)
|
||||
|
||||
def test_subcontracting_inward_warehouse_is_mandatory(self):
|
||||
purposes = {
|
||||
"Return Raw Material to Customer": "Source Warehouse is required",
|
||||
"Subcontracting Delivery": "Source Warehouse is required",
|
||||
"Receive from Customer": "Target Warehouse is required",
|
||||
"Subcontracting Return": "Target Warehouse is required",
|
||||
}
|
||||
|
||||
for purpose, message in purposes.items():
|
||||
with self.subTest(purpose=purpose):
|
||||
stock_entry = frappe.new_doc("Stock Entry")
|
||||
stock_entry.purpose = purpose
|
||||
stock_entry.append("items", {"item_code": "_Test Item"})
|
||||
|
||||
with self.assertRaisesRegex(frappe.ValidationError, message):
|
||||
stock_entry.validate()
|
||||
|
||||
def test_stock_entry_qty(self):
|
||||
item_code = "_Test Item 2"
|
||||
warehouse = "_Test Warehouse - _TC"
|
||||
|
||||
Reference in New Issue
Block a user