diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 54634482b0..2dabb9a647 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -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) { diff --git a/erpnext/stock/doctype/putaway_rule/putaway_rule.py b/erpnext/stock/doctype/putaway_rule/putaway_rule.py index 4ed4dafac7..56752583fa 100644 --- a/erpnext/stock/doctype/putaway_rule/putaway_rule.py +++ b/erpnext/stock/doctype/putaway_rule/putaway_rule.py @@ -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 diff --git a/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py b/erpnext/stock/doctype/putaway_rule/test_putaway_rule.py index 17619e01bc..86f7dc3e08 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 @@ 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") diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index fd920a585a..5d9ea8daee 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -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); } }); diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index aed69e11dd..e37e1223bc 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -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() diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py index b78c6be983..b12a8547fe 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 @@ 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,