chore: Stock Entry Tests and fixes
- Maintain item-warehouse wise rules for Stock Entry Material Transfer - Test cases for Stock Entry with more use cases - Sider fixes
This commit is contained in:
parent
a5d8d32775
commit
c47d38dc18
@ -2030,7 +2030,7 @@ erpnext.show_serial_batch_selector = function (frm, d, callback, on_close, show_
|
||||
});
|
||||
}
|
||||
|
||||
erpnext.apply_putaway_rule = (frm) => {
|
||||
erpnext.apply_putaway_rule = (frm, purpose=null) => {
|
||||
if (!frm.doc.company) {
|
||||
frappe.throw({message: __("Please select a Company first."), title: __("Mandatory")});
|
||||
}
|
||||
@ -2042,7 +2042,8 @@ erpnext.apply_putaway_rule = (frm) => {
|
||||
doctype: frm.doctype,
|
||||
items: frm.doc.items,
|
||||
company: frm.doc.company,
|
||||
sync: true
|
||||
sync: true,
|
||||
purpose: purpose
|
||||
},
|
||||
callback: (result) => {
|
||||
if (!result.exc && result.message) {
|
||||
|
@ -64,11 +64,14 @@ def get_putaway_capacity(rule):
|
||||
return free_space if free_space > 0 else 0
|
||||
|
||||
@frappe.whitelist()
|
||||
def apply_putaway_rule(doctype, items, company, sync=None):
|
||||
def apply_putaway_rule(doctype, items, company, sync=None, purpose=None):
|
||||
""" Applies Putaway Rule on line items.
|
||||
|
||||
items: List of Purchase Receipt Item objects
|
||||
company: Company in the Purchase Receipt
|
||||
items: List of Purchase Receipt/Stock Entry Items
|
||||
company: Company in the Purchase Receipt/Stock Entry
|
||||
doctype: Doctype to apply rule on
|
||||
purpose: Purpose of Stock Entry
|
||||
sync (optional): Sync with client side only for client side calls
|
||||
"""
|
||||
if isinstance(items, string_types):
|
||||
items = json.loads(items)
|
||||
@ -82,31 +85,36 @@ def apply_putaway_rule(doctype, items, company, sync=None):
|
||||
|
||||
source_warehouse = item.get("s_warehouse")
|
||||
serial_nos = get_serial_nos(item.get("serial_no"))
|
||||
item.conversion_factor = flt(item.conversion_factor) or 1
|
||||
item.conversion_factor = flt(item.conversion_factor) or 1.0
|
||||
pending_qty, item_code = flt(item.qty), item.item_code
|
||||
pending_stock_qty = flt(item.transfer_qty) if doctype == "Stock Entry" else flt(item.stock_qty)
|
||||
if not pending_qty or not item_code:
|
||||
updated_table = add_row(item, pending_qty, item.warehouse, updated_table)
|
||||
continue
|
||||
|
||||
uom_must_be_whole_number = frappe.db.get_value('UOM', item.uom, 'must_be_whole_number')
|
||||
|
||||
if not pending_qty or not item_code:
|
||||
updated_table = add_row(item, pending_qty, source_warehouse or item.warehouse, updated_table)
|
||||
continue
|
||||
|
||||
at_capacity, rules = get_ordered_putaway_rules(item_code, company, source_warehouse=source_warehouse)
|
||||
|
||||
if not rules:
|
||||
warehouse = item.warehouse
|
||||
warehouse = source_warehouse or item.warehouse
|
||||
if at_capacity:
|
||||
warehouse = '' # rules available, but no free space
|
||||
# rules available, but no free space
|
||||
items_not_accomodated.append([item_code, pending_qty])
|
||||
updated_table = add_row(item, pending_qty, warehouse, updated_table)
|
||||
else:
|
||||
updated_table = add_row(item, pending_qty, warehouse, updated_table)
|
||||
continue
|
||||
|
||||
# maintain item wise rules, to handle if item is entered twice
|
||||
# maintain item/item-warehouse wise rules, to handle if item is entered twice
|
||||
# in the table, due to different price, etc.
|
||||
if not item_wise_rules[item_code]:
|
||||
item_wise_rules[item_code] = rules
|
||||
key = item_code
|
||||
if doctype == "Stock Entry" and purpose == "Material Transfer" and source_warehouse:
|
||||
key = (item_code, source_warehouse)
|
||||
|
||||
for rule in item_wise_rules[item_code]:
|
||||
if not item_wise_rules[key]:
|
||||
item_wise_rules[key] = rules
|
||||
|
||||
for rule in item_wise_rules[key]:
|
||||
if pending_stock_qty > 0 and rule.free_space:
|
||||
stock_qty_to_allocate = flt(rule.free_space) if pending_stock_qty >= flt(rule.free_space) else pending_stock_qty
|
||||
qty_to_allocate = stock_qty_to_allocate / item.conversion_factor
|
||||
|
@ -4,12 +4,11 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
import unittest
|
||||
from frappe.utils import add_days, nowdate
|
||||
from erpnext.stock.doctype.item.test_item import make_item
|
||||
from erpnext.stock.get_item_details import get_conversion_factor
|
||||
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.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
|
||||
|
||||
class TestPutawayRule(unittest.TestCase):
|
||||
@ -27,6 +26,9 @@ class TestPutawayRule(unittest.TestCase):
|
||||
if not frappe.db.exists("Warehouse", {"warehouse_name": "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"):
|
||||
new_uom = frappe.new_doc("UOM")
|
||||
new_uom.uom_name = "Bag"
|
||||
@ -34,21 +36,18 @@ class TestPutawayRule(unittest.TestCase):
|
||||
|
||||
def test_putaway_rules_priority(self):
|
||||
"""Test if rule is applied by priority, irrespective of free space."""
|
||||
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,
|
||||
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200,
|
||||
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)
|
||||
|
||||
pr = make_purchase_receipt(item_code="_Rice", qty=300, apply_putaway_rule=1,
|
||||
do_not_submit=1)
|
||||
self.assertEqual(len(pr.items), 2)
|
||||
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].warehouse, warehouse_2)
|
||||
self.assertEqual(pr.items[1].warehouse, self.warehouse_2)
|
||||
|
||||
pr.delete()
|
||||
rule_1.delete()
|
||||
@ -57,26 +56,23 @@ class TestPutawayRule(unittest.TestCase):
|
||||
def test_putaway_rules_with_same_priority(self):
|
||||
"""Test if rule with more free space is applied,
|
||||
among two rules with same priority and capacity."""
|
||||
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=500,
|
||||
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=500,
|
||||
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")
|
||||
|
||||
# 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,
|
||||
do_not_submit=1)
|
||||
self.assertEqual(len(pr.items), 2)
|
||||
self.assertEqual(pr.items[0].qty, 500)
|
||||
# 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)
|
||||
# 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()
|
||||
pr.delete()
|
||||
@ -85,21 +81,20 @@ class TestPutawayRule(unittest.TestCase):
|
||||
|
||||
def test_putaway_rules_with_insufficient_capacity(self):
|
||||
"""Test if qty exceeding capacity, is handled."""
|
||||
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=100,
|
||||
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=100,
|
||||
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")
|
||||
|
||||
pr = make_purchase_receipt(item_code="_Rice", qty=350, apply_putaway_rule=1,
|
||||
do_not_submit=1)
|
||||
self.assertEqual(len(pr.items), 2)
|
||||
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].warehouse, warehouse_1)
|
||||
self.assertEqual(pr.items[1].warehouse, self.warehouse_1)
|
||||
# total 300 assigned, 50 unassigned
|
||||
|
||||
pr.delete()
|
||||
rule_1.delete()
|
||||
rule_2.delete()
|
||||
@ -114,26 +109,23 @@ class TestPutawayRule(unittest.TestCase):
|
||||
})
|
||||
item.save()
|
||||
|
||||
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=3,
|
||||
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=3,
|
||||
uom="Bag")
|
||||
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")
|
||||
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=self.warehouse_1, qty=1000, basic_rate=50)
|
||||
|
||||
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)
|
||||
self.assertEqual(len(pr.items), 2)
|
||||
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].warehouse, warehouse_1)
|
||||
self.assertEqual(pr.items[1].warehouse, self.warehouse_1)
|
||||
|
||||
stock_receipt.cancel()
|
||||
pr.delete()
|
||||
@ -152,15 +144,12 @@ class TestPutawayRule(unittest.TestCase):
|
||||
|
||||
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
|
||||
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")
|
||||
self.assertEqual(rule_1.stock_capacity, 1000)
|
||||
# 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)
|
||||
# total capacity is 1500 Kg
|
||||
|
||||
@ -168,7 +157,7 @@ class TestPutawayRule(unittest.TestCase):
|
||||
conversion_factor=1000, apply_putaway_rule=1, do_not_submit=1)
|
||||
self.assertEqual(len(pr.items), 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)
|
||||
# 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()
|
||||
|
||||
def test_putaway_rules_with_reoccurring_item(self):
|
||||
"""Test rules on same item entered multiple times."""
|
||||
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,
|
||||
"""Test rules on same item entered multiple times with different rate."""
|
||||
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.warehouse_1, capacity=200,
|
||||
uom="Kg")
|
||||
# total capacity is 200 Kg
|
||||
|
||||
@ -201,12 +187,12 @@ class TestPutawayRule(unittest.TestCase):
|
||||
pr.save()
|
||||
self.assertEqual(len(pr.items), 2)
|
||||
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)
|
||||
# same rule applied to second item row
|
||||
# with previous assignment considered
|
||||
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)
|
||||
|
||||
pr.delete()
|
||||
@ -214,17 +200,14 @@ class TestPutawayRule(unittest.TestCase):
|
||||
|
||||
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,
|
||||
rule_1 = create_putaway_rule(item_code="_Rice", warehouse=self.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].warehouse, self.warehouse_1)
|
||||
self.assertEqual(pr.items[0].putaway_rule, rule_1.name)
|
||||
|
||||
# force overreceipt and disable apply putaway rule in PR
|
||||
@ -236,6 +219,156 @@ class TestPutawayRule(unittest.TestCase):
|
||||
pr.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):
|
||||
args = frappe._dict(args)
|
||||
putaway = frappe.new_doc("Putaway Rule")
|
||||
|
@ -574,7 +574,7 @@ frappe.ui.form.on('Stock Entry', {
|
||||
},
|
||||
|
||||
apply_putaway_rule: function (frm) {
|
||||
if (frm.doc.apply_putaway_rule) erpnext.apply_putaway_rule(frm);
|
||||
if (frm.doc.apply_putaway_rule) erpnext.apply_putaway_rule(frm, frm.doc.purpose);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -47,7 +47,8 @@ class StockEntry(StockController):
|
||||
apply_rule = self.apply_putaway_rule and (self.purpose in ["Material Transfer", "Material Receipt"])
|
||||
|
||||
if self.get("items") and apply_rule:
|
||||
apply_putaway_rule(self.doctype, self.get("items"), self.company)
|
||||
apply_putaway_rule(self.doctype, self.get("items"), self.company,
|
||||
purpose=self.purpose)
|
||||
|
||||
def validate(self):
|
||||
self.pro_doc = frappe._dict()
|
||||
|
@ -53,6 +53,8 @@ def make_stock_entry(**args):
|
||||
args.target = args.to_warehouse
|
||||
if args.item_code:
|
||||
args.item = args.item_code
|
||||
if args.apply_putaway_rule:
|
||||
s.apply_putaway_rule = args.apply_putaway_rule
|
||||
|
||||
if isinstance(args.qty, string_types):
|
||||
if '.' in args.qty:
|
||||
@ -118,7 +120,8 @@ def make_stock_entry(**args):
|
||||
"t_warehouse": args.target,
|
||||
"qty": args.qty,
|
||||
"basic_rate": args.rate or args.basic_rate,
|
||||
"conversion_factor": 1.0,
|
||||
"conversion_factor": args.conversion_factor or 1.0,
|
||||
"transfer_qty": flt(args.qty) * (flt(args.conversion_factor) or 1.0),
|
||||
"serial_no": args.serial_no,
|
||||
'batch_no': args.batch_no,
|
||||
'cost_center': args.cost_center,
|
||||
|
Loading…
x
Reference in New Issue
Block a user