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
diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js
index 5463448..2dabb9a 100644
--- a/erpnext/public/js/controllers/transaction.js
+++ b/erpnext/public/js/controllers/transaction.js
@@ -2030,7 +2030,7 @@
});
}
-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 @@
doctype: frm.doctype,
items: frm.doc.items,
company: frm.doc.company,
- sync: true
+ sync: true,
+ purpose: purpose
},
callback: (result) => {
if (!result.exc && result.message) {
diff --git a/erpnext/stock/doctype/putaway_rule/putaway_rule.py b/erpnext/stock/doctype/putaway_rule/putaway_rule.py
index 4ed4daf..5675258 100644
--- a/erpnext/stock/doctype/putaway_rule/putaway_rule.py
+++ b/erpnext/stock/doctype/putaway_rule/putaway_rule.py
@@ -64,11 +64,14 @@
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 @@
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
diff --git a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py
index 17619e0..86f7dc3 100644
--- a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py
+++ b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
})
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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")
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js
index fd920a5..5d9ea8d 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.js
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.js
@@ -574,7 +574,7 @@
},
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);
}
});
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py
index aed69e1..e37e122 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry.py
@@ -47,7 +47,8 @@
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()
diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py
index b78c6be..b12a854 100644
--- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py
+++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py
@@ -53,6 +53,8 @@
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 @@
"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,