Merge pull request #32082 from s-aga-r/t3
fix: validate available qty for consumption in SCR
This commit is contained in:
commit
fb54277484
@ -187,22 +187,13 @@ class TestSubcontractingOrder(FrappeTestCase):
|
||||
self.assertEqual(len(ste.items), len(rm_items))
|
||||
|
||||
def test_update_reserved_qty_for_subcontracting(self):
|
||||
# Make stock available for raw materials
|
||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100)
|
||||
# Create RM Material Receipt
|
||||
make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item", qty=10, basic_rate=100)
|
||||
make_stock_entry(
|
||||
target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100", qty=20, basic_rate=100
|
||||
)
|
||||
make_stock_entry(
|
||||
target="_Test Warehouse 1 - _TC", item_code="_Test Item", qty=30, basic_rate=100
|
||||
)
|
||||
make_stock_entry(
|
||||
target="_Test Warehouse 1 - _TC",
|
||||
item_code="_Test Item Home Desktop 100",
|
||||
qty=30,
|
||||
basic_rate=100,
|
||||
)
|
||||
|
||||
bin1 = frappe.db.get_value(
|
||||
bin_before_sco = frappe.db.get_value(
|
||||
"Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname=["reserved_qty_for_sub_contract", "projected_qty", "modified"],
|
||||
@ -222,102 +213,97 @@ class TestSubcontractingOrder(FrappeTestCase):
|
||||
]
|
||||
sco = get_subcontracting_order(service_items=service_items)
|
||||
|
||||
bin2 = frappe.db.get_value(
|
||||
bin_after_sco = frappe.db.get_value(
|
||||
"Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname=["reserved_qty_for_sub_contract", "projected_qty", "modified"],
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
self.assertEqual(bin2.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
|
||||
self.assertEqual(bin2.projected_qty, bin1.projected_qty - 10)
|
||||
self.assertNotEqual(bin1.modified, bin2.modified)
|
||||
# reserved_qty_for_sub_contract should be increased by 10
|
||||
self.assertEqual(
|
||||
bin_after_sco.reserved_qty_for_sub_contract, bin_before_sco.reserved_qty_for_sub_contract + 10
|
||||
)
|
||||
|
||||
# Create stock transfer
|
||||
# projected_qty should be decreased by 10
|
||||
self.assertEqual(bin_after_sco.projected_qty, bin_before_sco.projected_qty - 10)
|
||||
|
||||
self.assertNotEqual(bin_before_sco.modified, bin_after_sco.modified)
|
||||
|
||||
# Create Stock Entry(Send to Subcontractor)
|
||||
rm_items = [
|
||||
{
|
||||
"item_code": "_Test FG Item",
|
||||
"rm_item_code": "_Test Item",
|
||||
"item_name": "_Test Item",
|
||||
"qty": 6,
|
||||
"qty": 10,
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"rate": 100,
|
||||
"amount": 600,
|
||||
"amount": 1000,
|
||||
"stock_uom": "Nos",
|
||||
}
|
||||
},
|
||||
{
|
||||
"item_code": "_Test FG Item",
|
||||
"rm_item_code": "_Test Item Home Desktop 100",
|
||||
"item_name": "_Test Item Home Desktop 100",
|
||||
"qty": 20,
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"rate": 100,
|
||||
"amount": 2000,
|
||||
"stock_uom": "Nos",
|
||||
},
|
||||
]
|
||||
ste = frappe.get_doc(make_rm_stock_entry(sco.name, rm_items))
|
||||
ste.to_warehouse = "_Test Warehouse 1 - _TC"
|
||||
ste.save()
|
||||
ste.submit()
|
||||
|
||||
bin3 = frappe.db.get_value(
|
||||
bin_after_rm_transfer = frappe.db.get_value(
|
||||
"Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
self.assertEqual(bin3.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
|
||||
|
||||
make_stock_entry(
|
||||
target="_Test Warehouse 1 - _TC", item_code="_Test Item", qty=40, basic_rate=100
|
||||
)
|
||||
make_stock_entry(
|
||||
target="_Test Warehouse 1 - _TC",
|
||||
item_code="_Test Item Home Desktop 100",
|
||||
qty=40,
|
||||
basic_rate=100,
|
||||
# reserved_qty_for_sub_contract should be decreased by 10
|
||||
self.assertEqual(
|
||||
bin_after_rm_transfer.reserved_qty_for_sub_contract,
|
||||
bin_after_sco.reserved_qty_for_sub_contract - 10,
|
||||
)
|
||||
|
||||
# Make SCR against the SCO
|
||||
scr = make_subcontracting_receipt(sco.name)
|
||||
scr.save()
|
||||
scr.submit()
|
||||
|
||||
bin4 = frappe.db.get_value(
|
||||
"Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
self.assertEqual(bin4.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
|
||||
|
||||
# Cancel SCR
|
||||
scr.reload()
|
||||
scr.cancel()
|
||||
bin5 = frappe.db.get_value(
|
||||
"Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
self.assertEqual(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6)
|
||||
|
||||
# Cancel Stock Entry
|
||||
# Cancel Stock Entry(Send to Subcontractor)
|
||||
ste.cancel()
|
||||
bin6 = frappe.db.get_value(
|
||||
bin_after_cancel_ste = frappe.db.get_value(
|
||||
"Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
self.assertEqual(bin6.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10)
|
||||
# reserved_qty_for_sub_contract should be increased by 10
|
||||
self.assertEqual(
|
||||
bin_after_cancel_ste.reserved_qty_for_sub_contract,
|
||||
bin_after_rm_transfer.reserved_qty_for_sub_contract + 10,
|
||||
)
|
||||
|
||||
# Cancel PO
|
||||
# Cancel SCO
|
||||
sco.reload()
|
||||
sco.cancel()
|
||||
bin7 = frappe.db.get_value(
|
||||
bin_after_cancel_sco = frappe.db.get_value(
|
||||
"Bin",
|
||||
filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"},
|
||||
fieldname="reserved_qty_for_sub_contract",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
self.assertEqual(bin7.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
|
||||
# reserved_qty_for_sub_contract should be decreased by 10
|
||||
self.assertEqual(
|
||||
bin_after_cancel_sco.reserved_qty_for_sub_contract,
|
||||
bin_after_cancel_ste.reserved_qty_for_sub_contract - 10,
|
||||
)
|
||||
self.assertEqual(
|
||||
bin_after_cancel_sco.reserved_qty_for_sub_contract, bin_before_sco.reserved_qty_for_sub_contract
|
||||
)
|
||||
|
||||
def test_exploded_items(self):
|
||||
item_code = "_Test Subcontracted FG Item 11"
|
||||
|
@ -75,6 +75,7 @@ class SubcontractingReceipt(SubcontractingController):
|
||||
self.get_current_stock()
|
||||
|
||||
def on_submit(self):
|
||||
self.validate_available_qty_for_consumption()
|
||||
self.update_status_updater_args()
|
||||
self.update_prevdoc_status()
|
||||
self.set_subcontracting_order_status()
|
||||
@ -107,10 +108,42 @@ class SubcontractingReceipt(SubcontractingController):
|
||||
self.set_missing_values_in_supplied_items()
|
||||
self.set_missing_values_in_items()
|
||||
|
||||
def set_available_qty_for_consumption(self):
|
||||
supplied_items_details = {}
|
||||
|
||||
sco_supplied_item = frappe.qb.DocType("Subcontracting Order Supplied Item")
|
||||
for item in self.get("items"):
|
||||
supplied_items = (
|
||||
frappe.qb.from_(sco_supplied_item)
|
||||
.select(
|
||||
sco_supplied_item.rm_item_code,
|
||||
sco_supplied_item.reference_name,
|
||||
(sco_supplied_item.total_supplied_qty - sco_supplied_item.consumed_qty).as_("available_qty"),
|
||||
)
|
||||
.where(
|
||||
(sco_supplied_item.parent == item.subcontracting_order)
|
||||
& (sco_supplied_item.main_item_code == item.item_code)
|
||||
& (sco_supplied_item.reference_name == item.subcontracting_order_item)
|
||||
)
|
||||
).run(as_dict=True)
|
||||
|
||||
if supplied_items:
|
||||
supplied_items_details[item.name] = {}
|
||||
|
||||
for supplied_item in supplied_items:
|
||||
supplied_items_details[item.name][supplied_item.rm_item_code] = supplied_item.available_qty
|
||||
else:
|
||||
for item in self.get("supplied_items"):
|
||||
item.available_qty_for_consumption = supplied_items_details.get(item.reference_name, {}).get(
|
||||
item.rm_item_code, 0
|
||||
)
|
||||
|
||||
def set_missing_values_in_supplied_items(self):
|
||||
for item in self.get("supplied_items") or []:
|
||||
item.amount = item.rate * item.consumed_qty
|
||||
|
||||
self.set_available_qty_for_consumption()
|
||||
|
||||
def set_missing_values_in_items(self):
|
||||
rm_supp_cost = {}
|
||||
for item in self.get("supplied_items") or []:
|
||||
@ -147,6 +180,17 @@ class SubcontractingReceipt(SubcontractingController):
|
||||
_("Rejected Warehouse is mandatory against rejected Item {0}").format(item.item_code)
|
||||
)
|
||||
|
||||
def validate_available_qty_for_consumption(self):
|
||||
for item in self.get("supplied_items"):
|
||||
if (
|
||||
item.available_qty_for_consumption and item.available_qty_for_consumption < item.consumed_qty
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row {0}: Consumed Qty must be less than or equal to Available Qty For Consumption in Consumed Items Table."
|
||||
).format(item.idx)
|
||||
)
|
||||
|
||||
def set_items_cost_center(self):
|
||||
if self.company:
|
||||
cost_center = frappe.get_cached_value("Company", self.company, "cost_center")
|
||||
|
@ -70,6 +70,55 @@ class TestSubcontractingReceipt(FrappeTestCase):
|
||||
rm_supp_cost = sum(item.amount for item in scr.get("supplied_items"))
|
||||
self.assertEqual(scr.get("items")[0].rm_supp_cost, flt(rm_supp_cost))
|
||||
|
||||
def test_available_qty_for_consumption(self):
|
||||
make_stock_entry(
|
||||
item_code="_Test Item", qty=100, target="_Test Warehouse 1 - _TC", basic_rate=100
|
||||
)
|
||||
make_stock_entry(
|
||||
item_code="_Test Item Home Desktop 100",
|
||||
qty=100,
|
||||
target="_Test Warehouse 1 - _TC",
|
||||
basic_rate=100,
|
||||
)
|
||||
service_items = [
|
||||
{
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"item_code": "Subcontracted Service Item 1",
|
||||
"qty": 10,
|
||||
"rate": 100,
|
||||
"fg_item": "_Test FG Item",
|
||||
"fg_item_qty": 10,
|
||||
},
|
||||
]
|
||||
sco = get_subcontracting_order(service_items=service_items)
|
||||
rm_items = [
|
||||
{
|
||||
"main_item_code": "_Test FG Item",
|
||||
"item_code": "_Test Item",
|
||||
"qty": 5.0,
|
||||
"rate": 100.0,
|
||||
"stock_uom": "_Test UOM",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
},
|
||||
{
|
||||
"main_item_code": "_Test FG Item",
|
||||
"item_code": "_Test Item Home Desktop 100",
|
||||
"qty": 10.0,
|
||||
"rate": 100.0,
|
||||
"stock_uom": "_Test UOM",
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
},
|
||||
]
|
||||
itemwise_details = make_stock_in_entry(rm_items=rm_items)
|
||||
make_stock_transfer_entry(
|
||||
sco_no=sco.name,
|
||||
rm_items=rm_items,
|
||||
itemwise_details=copy.deepcopy(itemwise_details),
|
||||
)
|
||||
scr = make_subcontracting_receipt(sco.name)
|
||||
scr.save()
|
||||
self.assertRaises(frappe.ValidationError, scr.submit)
|
||||
|
||||
def test_subcontracting_gle_fg_item_rate_zero(self):
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
"col_break2",
|
||||
"amount",
|
||||
"secbreak_2",
|
||||
"available_qty_for_consumption",
|
||||
"required_qty",
|
||||
"col_break3",
|
||||
"consumed_qty",
|
||||
@ -75,8 +76,7 @@
|
||||
{
|
||||
"fieldname": "required_qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Available Qty For Consumption",
|
||||
"label": "Required Qty",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
@ -85,7 +85,7 @@
|
||||
"fieldname": "consumed_qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Qty to be Consumed",
|
||||
"label": "Consumed Qty",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
@ -179,12 +179,21 @@
|
||||
"options": "Subcontracting Order",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "available_qty_for_consumption",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Available Qty For Consumption",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-04-18 10:45:16.538479",
|
||||
"modified": "2022-09-02 22:28:53.392381",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Subcontracting",
|
||||
"name": "Subcontracting Receipt Supplied Item",
|
||||
@ -193,6 +202,6 @@
|
||||
"permissions": [],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"states": []
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
Loading…
Reference in New Issue
Block a user