chore: Test and fixes
- Tests as per new design flow - Fixed duplicate data bug in Warehouse Capacity Summary - Set Amount currently on applying rule in client side - Apply rules on server side before validate
This commit is contained in:
parent
0f3cfc502b
commit
a5d8d32775
@ -2050,9 +2050,10 @@ erpnext.apply_putaway_rule = (frm) => {
|
|||||||
|
|
||||||
let items = result.message;
|
let items = result.message;
|
||||||
items.forEach((row) => {
|
items.forEach((row) => {
|
||||||
delete row["name"];
|
delete row["name"]; // dont overwrite name from server side
|
||||||
let child = frm.add_child("items");
|
let child = frm.add_child("items");
|
||||||
Object.assign(child, row);
|
Object.assign(child, row);
|
||||||
|
frm.script_manager.trigger("qty", child.doctype, child.name);
|
||||||
});
|
});
|
||||||
frm.get_field("items").grid.refresh();
|
frm.get_field("items").grid.refresh();
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ erpnext.stock.ItemDashboard = Class.extend({
|
|||||||
|
|
||||||
// more
|
// more
|
||||||
this.content.find('.btn-more').on('click', function() {
|
this.content.find('.btn-more').on('click', function() {
|
||||||
me.start += this.page_length;
|
me.start += me.page_length;
|
||||||
me.refresh();
|
me.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ class PurchaseReceipt(BuyingController):
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
def before_save(self):
|
def before_validate(self):
|
||||||
from erpnext.stock.doctype.putaway_rule.putaway_rule import apply_putaway_rule
|
from erpnext.stock.doctype.putaway_rule.putaway_rule import apply_putaway_rule
|
||||||
|
|
||||||
if self.get("items") and self.apply_putaway_rule:
|
if self.get("items") and self.apply_putaway_rule:
|
||||||
|
@ -979,6 +979,7 @@ def make_purchase_receipt(**args):
|
|||||||
pr.currency = args.currency or "INR"
|
pr.currency = args.currency or "INR"
|
||||||
pr.is_return = args.is_return
|
pr.is_return = args.is_return
|
||||||
pr.return_against = args.return_against
|
pr.return_against = args.return_against
|
||||||
|
pr.apply_putaway_rule = args.apply_putaway_rule
|
||||||
qty = args.qty or 5
|
qty = args.qty or 5
|
||||||
received_qty = args.received_qty or qty
|
received_qty = args.received_qty or qty
|
||||||
rejected_qty = args.rejected_qty or flt(received_qty) - flt(qty)
|
rejected_qty = args.rejected_qty or flt(received_qty) - flt(qty)
|
||||||
@ -994,6 +995,7 @@ def make_purchase_receipt(**args):
|
|||||||
"rejected_warehouse": args.rejected_warehouse or "_Test Rejected Warehouse - _TC" if rejected_qty != 0 else "",
|
"rejected_warehouse": args.rejected_warehouse or "_Test Rejected Warehouse - _TC" if rejected_qty != 0 else "",
|
||||||
"rate": args.rate if args.rate != None else 50,
|
"rate": args.rate if args.rate != None else 50,
|
||||||
"conversion_factor": args.conversion_factor or 1.0,
|
"conversion_factor": args.conversion_factor or 1.0,
|
||||||
|
"stock_qty": flt(qty) * (flt(args.conversion_factor) or 1.0),
|
||||||
"serial_no": args.serial_no,
|
"serial_no": args.serial_no,
|
||||||
"stock_uom": args.stock_uom or "_Test UOM",
|
"stock_uom": args.stock_uom or "_Test UOM",
|
||||||
"uom": uom,
|
"uom": uom,
|
||||||
|
@ -9,8 +9,8 @@ from erpnext.stock.doctype.item.test_item import make_item
|
|||||||
from erpnext.stock.get_item_details import get_conversion_factor
|
from erpnext.stock.get_item_details import get_conversion_factor
|
||||||
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
|
||||||
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry
|
||||||
from erpnext.buying.doctype.purchase_order.purchase_order import make_purchase_receipt
|
|
||||||
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
|
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
|
||||||
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||||
|
|
||||||
class TestPutawayRule(unittest.TestCase):
|
class TestPutawayRule(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@ -42,17 +42,15 @@ class TestPutawayRule(unittest.TestCase):
|
|||||||
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=300,
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=300,
|
||||||
uom="Kg", priority=2)
|
uom="Kg", priority=2)
|
||||||
|
|
||||||
po = create_purchase_order(item_code="_Rice", qty=300)
|
pr = make_purchase_receipt(item_code="_Rice", qty=300, apply_putaway_rule=1,
|
||||||
self.assertEqual(len(po.items), 1)
|
do_not_submit=1)
|
||||||
|
|
||||||
pr = make_purchase_receipt(po.name)
|
|
||||||
self.assertEqual(len(pr.items), 2)
|
self.assertEqual(len(pr.items), 2)
|
||||||
self.assertEqual(pr.items[0].qty, 200)
|
self.assertEqual(pr.items[0].qty, 200)
|
||||||
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
||||||
self.assertEqual(pr.items[1].qty, 100)
|
self.assertEqual(pr.items[1].qty, 100)
|
||||||
self.assertEqual(pr.items[1].warehouse, warehouse_2)
|
self.assertEqual(pr.items[1].warehouse, warehouse_2)
|
||||||
|
|
||||||
po.cancel()
|
pr.delete()
|
||||||
rule_1.delete()
|
rule_1.delete()
|
||||||
rule_2.delete()
|
rule_2.delete()
|
||||||
|
|
||||||
@ -70,10 +68,8 @@ class TestPutawayRule(unittest.TestCase):
|
|||||||
# out of 500 kg capacity, occupy 100 kg in warehouse_1
|
# out of 500 kg capacity, occupy 100 kg in warehouse_1
|
||||||
stock_receipt = make_stock_entry(item_code="_Rice", target=warehouse_1, qty=100, basic_rate=50)
|
stock_receipt = make_stock_entry(item_code="_Rice", target=warehouse_1, qty=100, basic_rate=50)
|
||||||
|
|
||||||
po = create_purchase_order(item_code="_Rice", qty=700)
|
pr = make_purchase_receipt(item_code="_Rice", qty=700, apply_putaway_rule=1,
|
||||||
self.assertEqual(len(po.items), 1)
|
do_not_submit=1)
|
||||||
|
|
||||||
pr = make_purchase_receipt(po.name)
|
|
||||||
self.assertEqual(len(pr.items), 2)
|
self.assertEqual(len(pr.items), 2)
|
||||||
self.assertEqual(pr.items[0].qty, 500)
|
self.assertEqual(pr.items[0].qty, 500)
|
||||||
# warehouse_2 has 500 kg free space, it is given priority
|
# warehouse_2 has 500 kg free space, it is given priority
|
||||||
@ -82,8 +78,8 @@ class TestPutawayRule(unittest.TestCase):
|
|||||||
# warehouse_1 has 400 kg free space, it is given less priority
|
# warehouse_1 has 400 kg free space, it is given less priority
|
||||||
self.assertEqual(pr.items[1].warehouse, warehouse_1)
|
self.assertEqual(pr.items[1].warehouse, warehouse_1)
|
||||||
|
|
||||||
po.cancel()
|
|
||||||
stock_receipt.cancel()
|
stock_receipt.cancel()
|
||||||
|
pr.delete()
|
||||||
rule_1.delete()
|
rule_1.delete()
|
||||||
rule_2.delete()
|
rule_2.delete()
|
||||||
|
|
||||||
@ -97,21 +93,14 @@ class TestPutawayRule(unittest.TestCase):
|
|||||||
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=200,
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=200,
|
||||||
uom="Kg")
|
uom="Kg")
|
||||||
|
|
||||||
po = create_purchase_order(item_code="_Rice", qty=350)
|
pr = make_purchase_receipt(item_code="_Rice", qty=350, apply_putaway_rule=1,
|
||||||
self.assertEqual(len(po.items), 1)
|
do_not_submit=1)
|
||||||
|
self.assertEqual(len(pr.items), 2)
|
||||||
pr = make_purchase_receipt(po.name)
|
|
||||||
|
|
||||||
self.assertEqual(len(pr.items), 3)
|
|
||||||
self.assertEqual(pr.items[0].qty, 200)
|
self.assertEqual(pr.items[0].qty, 200)
|
||||||
self.assertEqual(pr.items[0].warehouse, warehouse_2)
|
self.assertEqual(pr.items[0].warehouse, warehouse_2)
|
||||||
self.assertEqual(pr.items[1].qty, 100)
|
self.assertEqual(pr.items[1].qty, 100)
|
||||||
self.assertEqual(pr.items[1].warehouse, warehouse_1)
|
self.assertEqual(pr.items[1].warehouse, warehouse_1)
|
||||||
# extra qty has no warehouse assigned
|
pr.delete()
|
||||||
self.assertEqual(pr.items[2].qty, 50)
|
|
||||||
self.assertEqual(pr.items[2].warehouse, '')
|
|
||||||
|
|
||||||
po.cancel()
|
|
||||||
rule_1.delete()
|
rule_1.delete()
|
||||||
rule_2.delete()
|
rule_2.delete()
|
||||||
|
|
||||||
@ -135,24 +124,19 @@ class TestPutawayRule(unittest.TestCase):
|
|||||||
uom="Bag")
|
uom="Bag")
|
||||||
self.assertEqual(rule_2.stock_capacity, 4000)
|
self.assertEqual(rule_2.stock_capacity, 4000)
|
||||||
|
|
||||||
|
# populate 'Rack 1' with 1 Bag, making the free space 2 Bags
|
||||||
stock_receipt = make_stock_entry(item_code="_Rice", target=warehouse_1, qty=1000, basic_rate=50)
|
stock_receipt = make_stock_entry(item_code="_Rice", target=warehouse_1, qty=1000, basic_rate=50)
|
||||||
|
|
||||||
po = create_purchase_order(item_code="_Rice", qty=6, do_not_save=True)
|
pr = make_purchase_receipt(item_code="_Rice", qty=6, uom="Bag", stock_uom="Kg",
|
||||||
po.items[0].uom = "Bag"
|
conversion_factor=1000, apply_putaway_rule=1, do_not_submit=1)
|
||||||
po.save()
|
|
||||||
po.submit()
|
|
||||||
|
|
||||||
self.assertEqual(po.items[0].stock_qty, 6000)
|
|
||||||
|
|
||||||
pr = make_purchase_receipt(po.name)
|
|
||||||
self.assertEqual(len(pr.items), 2)
|
self.assertEqual(len(pr.items), 2)
|
||||||
self.assertEqual(pr.items[0].qty, 4)
|
self.assertEqual(pr.items[0].qty, 4)
|
||||||
self.assertEqual(pr.items[0].warehouse, warehouse_2)
|
self.assertEqual(pr.items[0].warehouse, warehouse_2)
|
||||||
self.assertEqual(pr.items[1].qty, 2)
|
self.assertEqual(pr.items[1].qty, 2)
|
||||||
self.assertEqual(pr.items[1].warehouse, warehouse_1)
|
self.assertEqual(pr.items[1].warehouse, warehouse_1)
|
||||||
|
|
||||||
po.cancel()
|
|
||||||
stock_receipt.cancel()
|
stock_receipt.cancel()
|
||||||
|
pr.delete()
|
||||||
rule_1.delete()
|
rule_1.delete()
|
||||||
rule_2.delete()
|
rule_2.delete()
|
||||||
|
|
||||||
@ -180,24 +164,15 @@ class TestPutawayRule(unittest.TestCase):
|
|||||||
self.assertEqual(rule_2.stock_capacity, 500)
|
self.assertEqual(rule_2.stock_capacity, 500)
|
||||||
# total capacity is 1500 Kg
|
# total capacity is 1500 Kg
|
||||||
|
|
||||||
po = create_purchase_order(item_code="_Rice", qty=2, do_not_save=True)
|
pr = make_purchase_receipt(item_code="_Rice", qty=2, uom="Bag", stock_uom="Kg",
|
||||||
# PO for 2 Bags (2000 Kg)
|
conversion_factor=1000, apply_putaway_rule=1, do_not_submit=1)
|
||||||
po.items[0].uom = "Bag"
|
self.assertEqual(len(pr.items), 1)
|
||||||
po.save()
|
|
||||||
po.submit()
|
|
||||||
|
|
||||||
self.assertEqual(po.items[0].stock_qty, 2000)
|
|
||||||
|
|
||||||
pr = make_purchase_receipt(po.name)
|
|
||||||
self.assertEqual(len(pr.items), 2)
|
|
||||||
self.assertEqual(pr.items[0].qty, 1)
|
self.assertEqual(pr.items[0].qty, 1)
|
||||||
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
||||||
# leftover space was for 500 kg (0.5 Bag)
|
# leftover space was for 500 kg (0.5 Bag)
|
||||||
# Since Bag is a whole UOM, 1(out of 2) Bag will be unassigned
|
# Since Bag is a whole UOM, 1(out of 2) Bag will be unassigned
|
||||||
self.assertEqual(pr.items[1].qty, 1)
|
|
||||||
self.assertEqual(pr.items[1].warehouse, '')
|
|
||||||
|
|
||||||
po.cancel()
|
pr.delete()
|
||||||
rule_1.delete()
|
rule_1.delete()
|
||||||
rule_2.delete()
|
rule_2.delete()
|
||||||
|
|
||||||
@ -208,38 +183,58 @@ class TestPutawayRule(unittest.TestCase):
|
|||||||
|
|
||||||
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_1, capacity=200,
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_1, capacity=200,
|
||||||
uom="Kg")
|
uom="Kg")
|
||||||
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=100,
|
# total capacity is 200 Kg
|
||||||
uom="Kg", priority=2)
|
|
||||||
# total capacity is 300 Kg
|
|
||||||
|
|
||||||
po = create_purchase_order(item_code="_Rice", qty=200, rate=100, do_not_save=True)
|
pr = make_purchase_receipt(item_code="_Rice", qty=100, apply_putaway_rule=1,
|
||||||
po.append("items", {
|
do_not_submit=1)
|
||||||
"item_code":"_Rice",
|
pr.append("items", {
|
||||||
|
"item_code": "_Rice",
|
||||||
"warehouse": "_Test Warehouse - _TC",
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
"qty": 300,
|
"qty": 200,
|
||||||
"rate": 120,
|
"uom": "Kg",
|
||||||
"schedule_date": add_days(nowdate(), 1),
|
"stock_uom": "Kg",
|
||||||
})
|
"stock_qty": 200,
|
||||||
po.save()
|
"received_qty": 200,
|
||||||
po.submit()
|
"rate": 100,
|
||||||
# PO for 500 Kg (two rows of same item, different rates)
|
"conversion_factor": 1.0,
|
||||||
self.assertEqual(len(po.items), 2)
|
}) # same item entered again in PR but with different rate
|
||||||
|
pr.save()
|
||||||
pr = make_purchase_receipt(po.name)
|
self.assertEqual(len(pr.items), 2)
|
||||||
self.assertEqual(len(pr.items), 3)
|
self.assertEqual(pr.items[0].qty, 100)
|
||||||
self.assertEqual(pr.items[0].qty, 200)
|
|
||||||
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
||||||
# same rules applied to second item row
|
self.assertEqual(pr.items[0].putaway_rule, rule_1.name)
|
||||||
|
# same rule applied to second item row
|
||||||
# with previous assignment considered
|
# with previous assignment considered
|
||||||
self.assertEqual(pr.items[1].qty, 100)
|
self.assertEqual(pr.items[1].qty, 100) # 100 unassigned in second row from 200
|
||||||
self.assertEqual(pr.items[1].warehouse, warehouse_2)
|
self.assertEqual(pr.items[1].warehouse, warehouse_1)
|
||||||
# unassigned 200 Kg
|
self.assertEqual(pr.items[1].putaway_rule, rule_1.name)
|
||||||
self.assertEqual(pr.items[2].qty, 200)
|
|
||||||
self.assertEqual(pr.items[2].warehouse, '')
|
|
||||||
|
|
||||||
po.cancel()
|
pr.delete()
|
||||||
|
rule_1.delete()
|
||||||
|
|
||||||
|
def test_validate_over_receipt_in_warehouse(self):
|
||||||
|
"""Test if overreceipt is blocked in the presence of putaway rules."""
|
||||||
|
warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
||||||
|
warehouse_2 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 2"})
|
||||||
|
|
||||||
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_1, capacity=200,
|
||||||
|
uom="Kg")
|
||||||
|
|
||||||
|
pr = make_purchase_receipt(item_code="_Rice", qty=300, apply_putaway_rule=1,
|
||||||
|
do_not_submit=1)
|
||||||
|
self.assertEqual(len(pr.items), 1)
|
||||||
|
self.assertEqual(pr.items[0].qty, 200) # 100 is unassigned fro 300 Kg
|
||||||
|
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
||||||
|
self.assertEqual(pr.items[0].putaway_rule, rule_1.name)
|
||||||
|
|
||||||
|
# force overreceipt and disable apply putaway rule in PR
|
||||||
|
pr.items[0].qty = 300
|
||||||
|
pr.items[0].stock_qty = 300
|
||||||
|
pr.apply_putaway_rule = 0
|
||||||
|
self.assertRaises(frappe.ValidationError, pr.save)
|
||||||
|
|
||||||
|
pr.delete()
|
||||||
rule_1.delete()
|
rule_1.delete()
|
||||||
rule_2.delete()
|
|
||||||
|
|
||||||
def create_putaway_rule(**args):
|
def create_putaway_rule(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
@ -42,7 +42,7 @@ class StockEntry(StockController):
|
|||||||
for item in self.get("items"):
|
for item in self.get("items"):
|
||||||
item.update(get_bin_details(item.item_code, item.s_warehouse))
|
item.update(get_bin_details(item.item_code, item.s_warehouse))
|
||||||
|
|
||||||
def before_save(self):
|
def before_validate(self):
|
||||||
from erpnext.stock.doctype.putaway_rule.putaway_rule import apply_putaway_rule
|
from erpnext.stock.doctype.putaway_rule.putaway_rule import apply_putaway_rule
|
||||||
apply_rule = self.apply_putaway_rule and (self.purpose in ["Material Transfer", "Material Receipt"])
|
apply_rule = self.apply_putaway_rule and (self.purpose in ["Material Transfer", "Material Receipt"])
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user