|
|
|
@@ -4,12 +4,11 @@
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
from __future__ import unicode_literals
|
|
|
|
import frappe
|
|
|
|
import frappe
|
|
|
|
import unittest
|
|
|
|
import unittest
|
|
|
|
from frappe.utils import add_days, nowdate
|
|
|
|
|
|
|
|
from erpnext.stock.doctype.item.test_item import make_item
|
|
|
|
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.test_purchase_order import create_purchase_order
|
|
|
|
from erpnext.stock.doctype.batch.test_batch import make_new_batch
|
|
|
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
|
|
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
|
|
|
|
|
|
|
|
|
|
|
class TestPutawayRule(unittest.TestCase):
|
|
|
|
class TestPutawayRule(unittest.TestCase):
|
|
|
|
@@ -27,6 +26,9 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
if not frappe.db.exists("Warehouse", {"warehouse_name": "Rack 2"}):
|
|
|
|
if not frappe.db.exists("Warehouse", {"warehouse_name": "Rack 2"}):
|
|
|
|
create_warehouse("Rack 2")
|
|
|
|
create_warehouse("Rack 2")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
|
|
|
|
|
|
|
self.warehouse_2 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 2"})
|
|
|
|
|
|
|
|
|
|
|
|
if not frappe.db.exists("UOM", "Bag"):
|
|
|
|
if not frappe.db.exists("UOM", "Bag"):
|
|
|
|
new_uom = frappe.new_doc("UOM")
|
|
|
|
new_uom = frappe.new_doc("UOM")
|
|
|
|
new_uom.uom_name = "Bag"
|
|
|
|
new_uom.uom_name = "Bag"
|
|
|
|
@@ -34,21 +36,18 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
|
|
def test_putaway_rules_priority(self):
|
|
|
|
def test_putaway_rules_priority(self):
|
|
|
|
"""Test if rule is applied by priority, irrespective of free space."""
|
|
|
|
"""Test if rule is applied by priority, irrespective of free space."""
|
|
|
|
warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200,
|
|
|
|
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")
|
|
|
|
uom="Kg")
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=300,
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=300,
|
|
|
|
uom="Kg", priority=2)
|
|
|
|
uom="Kg", priority=2)
|
|
|
|
|
|
|
|
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=300, apply_putaway_rule=1,
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=300, apply_putaway_rule=1,
|
|
|
|
do_not_submit=1)
|
|
|
|
do_not_submit=1)
|
|
|
|
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, self.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, self.warehouse_2)
|
|
|
|
|
|
|
|
|
|
|
|
pr.delete()
|
|
|
|
pr.delete()
|
|
|
|
rule_1.delete()
|
|
|
|
rule_1.delete()
|
|
|
|
@@ -57,26 +56,23 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
def test_putaway_rules_with_same_priority(self):
|
|
|
|
def test_putaway_rules_with_same_priority(self):
|
|
|
|
"""Test if rule with more free space is applied,
|
|
|
|
"""Test if rule with more free space is applied,
|
|
|
|
among two rules with same priority and capacity."""
|
|
|
|
among two rules with same priority and capacity."""
|
|
|
|
warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=500,
|
|
|
|
warehouse_2 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 2"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_1, capacity=500,
|
|
|
|
|
|
|
|
uom="Kg")
|
|
|
|
uom="Kg")
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=500,
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=500,
|
|
|
|
uom="Kg")
|
|
|
|
uom="Kg")
|
|
|
|
|
|
|
|
|
|
|
|
# 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=self.warehouse_1, qty=100, basic_rate=50)
|
|
|
|
|
|
|
|
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=700, apply_putaway_rule=1,
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=700, apply_putaway_rule=1,
|
|
|
|
do_not_submit=1)
|
|
|
|
do_not_submit=1)
|
|
|
|
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
|
|
|
|
self.assertEqual(pr.items[0].warehouse, warehouse_2)
|
|
|
|
self.assertEqual(pr.items[0].warehouse, self.warehouse_2)
|
|
|
|
self.assertEqual(pr.items[1].qty, 200)
|
|
|
|
self.assertEqual(pr.items[1].qty, 200)
|
|
|
|
# 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, self.warehouse_1)
|
|
|
|
|
|
|
|
|
|
|
|
stock_receipt.cancel()
|
|
|
|
stock_receipt.cancel()
|
|
|
|
pr.delete()
|
|
|
|
pr.delete()
|
|
|
|
@@ -85,21 +81,20 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
|
|
def test_putaway_rules_with_insufficient_capacity(self):
|
|
|
|
def test_putaway_rules_with_insufficient_capacity(self):
|
|
|
|
"""Test if qty exceeding capacity, is handled."""
|
|
|
|
"""Test if qty exceeding capacity, is handled."""
|
|
|
|
warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=100,
|
|
|
|
warehouse_2 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 2"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_1, capacity=100,
|
|
|
|
|
|
|
|
uom="Kg")
|
|
|
|
uom="Kg")
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=200,
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=200,
|
|
|
|
uom="Kg")
|
|
|
|
uom="Kg")
|
|
|
|
|
|
|
|
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=350, apply_putaway_rule=1,
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=350, apply_putaway_rule=1,
|
|
|
|
do_not_submit=1)
|
|
|
|
do_not_submit=1)
|
|
|
|
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_2)
|
|
|
|
self.assertEqual(pr.items[0].warehouse, self.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, self.warehouse_1)
|
|
|
|
|
|
|
|
# total 300 assigned, 50 unassigned
|
|
|
|
|
|
|
|
|
|
|
|
pr.delete()
|
|
|
|
pr.delete()
|
|
|
|
rule_1.delete()
|
|
|
|
rule_1.delete()
|
|
|
|
rule_2.delete()
|
|
|
|
rule_2.delete()
|
|
|
|
@@ -114,26 +109,23 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
})
|
|
|
|
})
|
|
|
|
item.save()
|
|
|
|
item.save()
|
|
|
|
|
|
|
|
|
|
|
|
warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=3,
|
|
|
|
warehouse_2 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 2"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_1, capacity=3,
|
|
|
|
|
|
|
|
uom="Bag")
|
|
|
|
uom="Bag")
|
|
|
|
self.assertEqual(rule_1.stock_capacity, 3000)
|
|
|
|
self.assertEqual(rule_1.stock_capacity, 3000)
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=4,
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=4,
|
|
|
|
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
|
|
|
|
# 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=self.warehouse_1, qty=1000, basic_rate=50)
|
|
|
|
|
|
|
|
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=6, uom="Bag", stock_uom="Kg",
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=6, uom="Bag", stock_uom="Kg",
|
|
|
|
conversion_factor=1000, apply_putaway_rule=1, do_not_submit=1)
|
|
|
|
conversion_factor=1000, apply_putaway_rule=1, do_not_submit=1)
|
|
|
|
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, self.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, self.warehouse_1)
|
|
|
|
|
|
|
|
|
|
|
|
stock_receipt.cancel()
|
|
|
|
stock_receipt.cancel()
|
|
|
|
pr.delete()
|
|
|
|
pr.delete()
|
|
|
|
@@ -152,15 +144,12 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
|
|
frappe.db.set_value("UOM", "Bag", "must_be_whole_number", 1)
|
|
|
|
frappe.db.set_value("UOM", "Bag", "must_be_whole_number", 1)
|
|
|
|
|
|
|
|
|
|
|
|
warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
|
|
|
|
|
|
|
warehouse_2 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 2"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Putaway Rule in different UOM
|
|
|
|
# Putaway Rule in different UOM
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_1, capacity=1,
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=1,
|
|
|
|
uom="Bag")
|
|
|
|
uom="Bag")
|
|
|
|
self.assertEqual(rule_1.stock_capacity, 1000)
|
|
|
|
self.assertEqual(rule_1.stock_capacity, 1000)
|
|
|
|
# Putaway Rule in Stock UOM
|
|
|
|
# Putaway Rule in Stock UOM
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=warehouse_2, capacity=500)
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=500)
|
|
|
|
self.assertEqual(rule_2.stock_capacity, 500)
|
|
|
|
self.assertEqual(rule_2.stock_capacity, 500)
|
|
|
|
# total capacity is 1500 Kg
|
|
|
|
# total capacity is 1500 Kg
|
|
|
|
|
|
|
|
|
|
|
|
@@ -168,7 +157,7 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
conversion_factor=1000, apply_putaway_rule=1, do_not_submit=1)
|
|
|
|
conversion_factor=1000, apply_putaway_rule=1, do_not_submit=1)
|
|
|
|
self.assertEqual(len(pr.items), 1)
|
|
|
|
self.assertEqual(len(pr.items), 1)
|
|
|
|
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, self.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
|
|
|
|
|
|
|
|
|
|
|
|
@@ -177,11 +166,8 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
rule_2.delete()
|
|
|
|
rule_2.delete()
|
|
|
|
|
|
|
|
|
|
|
|
def test_putaway_rules_with_reoccurring_item(self):
|
|
|
|
def test_putaway_rules_with_reoccurring_item(self):
|
|
|
|
"""Test rules on same item entered multiple times."""
|
|
|
|
"""Test rules on same item entered multiple times with different rate."""
|
|
|
|
warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200,
|
|
|
|
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")
|
|
|
|
uom="Kg")
|
|
|
|
# total capacity is 200 Kg
|
|
|
|
# total capacity is 200 Kg
|
|
|
|
|
|
|
|
|
|
|
|
@@ -201,12 +187,12 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
pr.save()
|
|
|
|
pr.save()
|
|
|
|
self.assertEqual(len(pr.items), 2)
|
|
|
|
self.assertEqual(len(pr.items), 2)
|
|
|
|
self.assertEqual(pr.items[0].qty, 100)
|
|
|
|
self.assertEqual(pr.items[0].qty, 100)
|
|
|
|
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
|
|
|
self.assertEqual(pr.items[0].warehouse, self.warehouse_1)
|
|
|
|
self.assertEqual(pr.items[0].putaway_rule, rule_1.name)
|
|
|
|
self.assertEqual(pr.items[0].putaway_rule, rule_1.name)
|
|
|
|
# same rule applied to second item row
|
|
|
|
# same rule applied to second item row
|
|
|
|
# with previous assignment considered
|
|
|
|
# with previous assignment considered
|
|
|
|
self.assertEqual(pr.items[1].qty, 100) # 100 unassigned in second row from 200
|
|
|
|
self.assertEqual(pr.items[1].qty, 100) # 100 unassigned in second row from 200
|
|
|
|
self.assertEqual(pr.items[1].warehouse, warehouse_1)
|
|
|
|
self.assertEqual(pr.items[1].warehouse, self.warehouse_1)
|
|
|
|
self.assertEqual(pr.items[1].putaway_rule, rule_1.name)
|
|
|
|
self.assertEqual(pr.items[1].putaway_rule, rule_1.name)
|
|
|
|
|
|
|
|
|
|
|
|
pr.delete()
|
|
|
|
pr.delete()
|
|
|
|
@@ -214,17 +200,14 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
|
|
def test_validate_over_receipt_in_warehouse(self):
|
|
|
|
def test_validate_over_receipt_in_warehouse(self):
|
|
|
|
"""Test if overreceipt is blocked in the presence of putaway rules."""
|
|
|
|
"""Test if overreceipt is blocked in the presence of putaway rules."""
|
|
|
|
warehouse_1 = frappe.db.get_value("Warehouse", {"warehouse_name": "Rack 1"})
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200,
|
|
|
|
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")
|
|
|
|
uom="Kg")
|
|
|
|
|
|
|
|
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=300, apply_putaway_rule=1,
|
|
|
|
pr = make_purchase_receipt(item_code="_Rice", qty=300, apply_putaway_rule=1,
|
|
|
|
do_not_submit=1)
|
|
|
|
do_not_submit=1)
|
|
|
|
self.assertEqual(len(pr.items), 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].qty, 200) # 100 is unassigned fro 300 Kg
|
|
|
|
self.assertEqual(pr.items[0].warehouse, warehouse_1)
|
|
|
|
self.assertEqual(pr.items[0].warehouse, self.warehouse_1)
|
|
|
|
self.assertEqual(pr.items[0].putaway_rule, rule_1.name)
|
|
|
|
self.assertEqual(pr.items[0].putaway_rule, rule_1.name)
|
|
|
|
|
|
|
|
|
|
|
|
# force overreceipt and disable apply putaway rule in PR
|
|
|
|
# force overreceipt and disable apply putaway rule in PR
|
|
|
|
@@ -236,6 +219,156 @@ class TestPutawayRule(unittest.TestCase):
|
|
|
|
pr.delete()
|
|
|
|
pr.delete()
|
|
|
|
rule_1.delete()
|
|
|
|
rule_1.delete()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_putaway_rule_on_stock_entry_material_transfer(self):
|
|
|
|
|
|
|
|
"""Test if source warehouse is considered while applying rules."""
|
|
|
|
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200,
|
|
|
|
|
|
|
|
uom="Kg") # higher priority
|
|
|
|
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=100,
|
|
|
|
|
|
|
|
uom="Kg", priority=2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry = make_stock_entry(item_code="_Rice", source=self.warehouse_1, qty=200,
|
|
|
|
|
|
|
|
target="_Test Warehouse - _TC", purpose="Material Transfer",
|
|
|
|
|
|
|
|
apply_putaway_rule=1, do_not_submit=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry_item = stock_entry.get("items")[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# since source warehouse is Rack 1, rule 1 (for Rack 1) will be avoided
|
|
|
|
|
|
|
|
# even though it has more free space and higher priority
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry_item.t_warehouse, self.warehouse_2)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry_item.qty, 100) # unassigned 100 out of 200 Kg
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry_item.putaway_rule, rule_2.name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry.delete()
|
|
|
|
|
|
|
|
rule_1.delete()
|
|
|
|
|
|
|
|
rule_2.delete()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_putaway_rule_on_stock_entry_material_transfer_reoccuring_item(self):
|
|
|
|
|
|
|
|
"""Test if reoccuring item is correctly considered."""
|
|
|
|
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=300,
|
|
|
|
|
|
|
|
uom="Kg")
|
|
|
|
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=600,
|
|
|
|
|
|
|
|
uom="Kg", priority=2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# create SE with first row having source warehouse as Rack 2
|
|
|
|
|
|
|
|
stock_entry = make_stock_entry(item_code="_Rice", source=self.warehouse_2, qty=200,
|
|
|
|
|
|
|
|
target="_Test Warehouse - _TC", purpose="Material Transfer",
|
|
|
|
|
|
|
|
apply_putaway_rule=1, do_not_submit=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Add rows with source warehouse as Rack 1
|
|
|
|
|
|
|
|
stock_entry.extend("items", [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
"item_code": "_Rice",
|
|
|
|
|
|
|
|
"s_warehouse": self.warehouse_1,
|
|
|
|
|
|
|
|
"t_warehouse": "_Test Warehouse - _TC",
|
|
|
|
|
|
|
|
"qty": 100,
|
|
|
|
|
|
|
|
"basic_rate": 50,
|
|
|
|
|
|
|
|
"conversion_factor": 1.0,
|
|
|
|
|
|
|
|
"transfer_qty": 100
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
"item_code": "_Rice",
|
|
|
|
|
|
|
|
"s_warehouse": self.warehouse_1,
|
|
|
|
|
|
|
|
"t_warehouse": "_Test Warehouse - _TC",
|
|
|
|
|
|
|
|
"qty": 200,
|
|
|
|
|
|
|
|
"basic_rate": 60,
|
|
|
|
|
|
|
|
"conversion_factor": 1.0,
|
|
|
|
|
|
|
|
"transfer_qty": 200
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry.save()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# since source warehouse was Rack 2, exclude rule_2
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[0].t_warehouse, self.warehouse_1)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[0].qty, 200)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[0].putaway_rule, rule_1.name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# since source warehouse was Rack 1, exclude rule_1 even though it has
|
|
|
|
|
|
|
|
# higher priority
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[1].t_warehouse, self.warehouse_2)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[1].qty, 100)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[1].putaway_rule, rule_2.name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[2].t_warehouse, self.warehouse_2)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[2].qty, 200)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[2].putaway_rule, rule_2.name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry.delete()
|
|
|
|
|
|
|
|
rule_1.delete()
|
|
|
|
|
|
|
|
rule_2.delete()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_putaway_rule_on_stock_entry_material_transfer_batch_serial_item(self):
|
|
|
|
|
|
|
|
"""Test if batch and serial items are split correctly."""
|
|
|
|
|
|
|
|
if not frappe.db.exists("Item", "Water Bottle"):
|
|
|
|
|
|
|
|
make_item("Water Bottle", {
|
|
|
|
|
|
|
|
"is_stock_item": 1,
|
|
|
|
|
|
|
|
"has_batch_no" : 1,
|
|
|
|
|
|
|
|
"create_new_batch": 1,
|
|
|
|
|
|
|
|
"has_serial_no": 1,
|
|
|
|
|
|
|
|
"serial_no_series": "BOTTL-.####",
|
|
|
|
|
|
|
|
"stock_uom": "Nos"
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rule_1 = create_putaway_rule(item_code="Water Bottle", warehouse=self.warehouse_1, capacity=3,
|
|
|
|
|
|
|
|
uom="Nos")
|
|
|
|
|
|
|
|
rule_2 = create_putaway_rule(item_code="Water Bottle", warehouse=self.warehouse_2, capacity=2,
|
|
|
|
|
|
|
|
uom="Nos")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
make_new_batch(batch_id="BOTTL-BATCH-1", item_code="Water Bottle")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pr = make_purchase_receipt(item_code="Water Bottle", qty=5, do_not_submit=1)
|
|
|
|
|
|
|
|
pr.items[0].batch_no = "BOTTL-BATCH-1"
|
|
|
|
|
|
|
|
pr.save()
|
|
|
|
|
|
|
|
pr.submit()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serial_nos = frappe.get_list("Serial No", filters={"purchase_document_no": pr.name, "status": "Active"})
|
|
|
|
|
|
|
|
serial_nos = [d.name for d in serial_nos]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry = make_stock_entry(item_code="Water Bottle", source="_Test Warehouse - _TC", qty=5,
|
|
|
|
|
|
|
|
target="Finished Goods - _TC", purpose="Material Transfer",
|
|
|
|
|
|
|
|
apply_putaway_rule=1, do_not_save=1)
|
|
|
|
|
|
|
|
stock_entry.items[0].batch_no = "BOTTL-BATCH-1"
|
|
|
|
|
|
|
|
stock_entry.items[0].serial_no = "\n".join(serial_nos)
|
|
|
|
|
|
|
|
stock_entry.save()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[0].t_warehouse, self.warehouse_1)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[0].qty, 3)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[0].putaway_rule, rule_1.name)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[0].serial_no, "\n".join(serial_nos[:3]))
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[0].batch_no, "BOTTL-BATCH-1")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[1].t_warehouse, self.warehouse_2)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[1].qty, 2)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[1].putaway_rule, rule_2.name)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[1].serial_no, "\n".join(serial_nos[3:]))
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry.items[1].batch_no, "BOTTL-BATCH-1")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry.delete()
|
|
|
|
|
|
|
|
pr.cancel()
|
|
|
|
|
|
|
|
rule_1.delete()
|
|
|
|
|
|
|
|
rule_2.delete()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_putaway_rule_on_stock_entry_material_receipt(self):
|
|
|
|
|
|
|
|
"""Test if rules are applied in Stock Entry of type Receipt."""
|
|
|
|
|
|
|
|
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200,
|
|
|
|
|
|
|
|
uom="Kg") # more capacity
|
|
|
|
|
|
|
|
rule_2 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_2, capacity=100,
|
|
|
|
|
|
|
|
uom="Kg")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry = make_stock_entry(item_code="_Rice", qty=100,
|
|
|
|
|
|
|
|
target="_Test Warehouse - _TC", purpose="Material Receipt",
|
|
|
|
|
|
|
|
apply_putaway_rule=1, do_not_submit=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry_item = stock_entry.get("items")[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry_item.t_warehouse, self.warehouse_1)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry_item.qty, 100)
|
|
|
|
|
|
|
|
self.assertEqual(stock_entry_item.putaway_rule, rule_1.name)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stock_entry.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)
|
|
|
|
putaway = frappe.new_doc("Putaway Rule")
|
|
|
|
putaway = frappe.new_doc("Putaway Rule")
|
|
|
|
|