def test_fifo(self): frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) item_code = "_Test Item 2" warehouse = "_Test Warehouse - _TC" create_stock_reconciliation(item_code="_Test Item 2", warehouse="_Test Warehouse - _TC", qty=0, rate=100) make_stock_entry(item_code=item_code, target=warehouse, qty=1, basic_rate=10) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 10]], eval(sle.stock_queue)) # negative qty make_stock_entry(item_code=item_code, source=warehouse, qty=2, basic_rate=10) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[-1, 10]], eval(sle.stock_queue)) # further negative make_stock_entry(item_code=item_code, source=warehouse, qty=1) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[-2, 10]], eval(sle.stock_queue)) # move stock to positive make_stock_entry(item_code=item_code, target=warehouse, qty=3, basic_rate=20) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 20]], eval(sle.stock_queue)) # incoming entry with diff rate make_stock_entry(item_code=item_code, target=warehouse, qty=1, basic_rate=30) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 20], [1, 30]], eval(sle.stock_queue)) frappe.db.set_default("allow_negative_stock", 0)
def _test_auto_material_request(self, item_code, material_request_type="Purchase", warehouse="_Test Warehouse - _TC"): variant = frappe.get_doc("Item", item_code) projected_qty, actual_qty = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, ["projected_qty", "actual_qty"]) or [0, 0] # stock entry reqd for auto-reorder create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty = actual_qty + abs(projected_qty) + 10, rate=100) projected_qty = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "projected_qty") or 0 frappe.db.set_value("Stock Settings", None, "auto_indent", 1) # update re-level qty so that it is more than projected_qty if projected_qty >= variant.reorder_levels[0].warehouse_reorder_level: variant.reorder_levels[0].warehouse_reorder_level += projected_qty variant.reorder_levels[0].material_request_type = material_request_type variant.save() from erpnext.stock.reorder_item import reorder_item mr_list = reorder_item() frappe.db.set_value("Stock Settings", None, "auto_indent", 0) items = [] for mr in mr_list: for d in mr.items: items.append(d.item_code) self.assertTrue(item_code in items)
def test_return_entire_bundled_items(self): set_perpetual_inventory() create_stock_reconciliation(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, rate=100) create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=50, rate=100) dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500) # return bundled item dn1 = create_delivery_note(item_code='_Test Product Bundle Item', is_return=1, return_against=dn.name, qty=-2, rate=500) # qty after return actual_qty = get_qty_after_transaction() self.assertEquals(actual_qty, 35) # Check incoming rate for return entry incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name}, ["incoming_rate", "stock_value_difference"]) self.assertEquals(incoming_rate, 100) # Check gl entry for warehouse gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name, "account": "_Test Warehouse - _TC"}, "debit") self.assertEquals(gle_warehouse_amount, 1400) set_perpetual_inventory(0)
def test_material_transfer_gl_entry(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') create_stock_reconciliation(qty=100, rate=100) mtn = make_stock_entry(item_code="_Test Item", source="Stores - TCP1", target="Finished Goods - TCP1", qty=45) self.check_stock_ledger_entries("Stock Entry", mtn.name, [["_Test Item", "Stores - TCP1", -45.0], ["_Test Item", "Finished Goods - TCP1", 45.0]]) stock_in_hand_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse) fixed_asset_account = get_inventory_account(mtn.company, mtn.get("items")[0].t_warehouse) if stock_in_hand_account == fixed_asset_account: # no gl entry as both source and target warehouse has linked to same account. self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) else: stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", "voucher_no": mtn.name, "warehouse": "Stores - TCP1"}, "stock_value_difference")) self.check_gl_entries("Stock Entry", mtn.name, sorted([ [stock_in_hand_account, 0.0, stock_value_diff], [fixed_asset_account, stock_value_diff, 0.0], ]) ) mtn.cancel()
def test_alternative_item_for_production_rm(self): create_stock_reconciliation(item_code='Alternate Item For A RW 1', warehouse='_Test Warehouse - _TC',qty=5, rate=2000) create_stock_reconciliation(item_code='Test FG A RW 2', warehouse='_Test Warehouse - _TC', qty=5, rate=2000) pro_order = make_wo_order_test_record(production_item='Test Finished Goods - A', qty=5, source_warehouse='_Test Warehouse - _TC', wip_warehouse='Test Supplier Warehouse - _TC') reserved_qty_for_production = frappe.db.get_value('Bin', {'item_code': 'Test FG A RW 1', 'warehouse': '_Test Warehouse - _TC'}, 'reserved_qty_for_production') ste = frappe.get_doc(make_stock_entry(pro_order.name, "Material Transfer for Manufacture", 5)) ste.insert() for item in ste.items: if item.item_code == 'Test FG A RW 1': item.item_code = 'Alternate Item For A RW 1' item.item_name = 'Alternate Item For A RW 1' item.description = 'Alternate Item For A RW 1' item.original_item = 'Test FG A RW 1' ste.submit() reserved_qty_for_production_after_transfer = frappe.db.get_value('Bin', {'item_code': 'Test FG A RW 1', 'warehouse': '_Test Warehouse - _TC'}, 'reserved_qty_for_production') self.assertEqual(reserved_qty_for_production_after_transfer, flt(reserved_qty_for_production - 5)) ste1 = frappe.get_doc(make_stock_entry(pro_order.name, "Manufacture", 5)) status = False for d in ste1.items: if d.item_code == 'Alternate Item For A RW 1': status = True self.assertEqual(status, True) ste1.submit()
def _test_auto_material_request(self, item_code): item = frappe.get_doc("Item", item_code) if item.variant_of: template = frappe.get_doc("Item", item.variant_of) else: template = item # stock entry reqd for auto-reorder create_stock_reconciliation(item_code=item_code, warehouse="_Test Warehouse - _TC", qty=10, rate=100) frappe.db.set_value("Stock Settings", None, "auto_indent", 1) projected_qty = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": "_Test Warehouse - _TC"}, "projected_qty") or 0 # update re-level qty so that it is more than projected_qty if projected_qty > template.reorder_levels[0].warehouse_reorder_level: template.reorder_levels[0].warehouse_reorder_level += projected_qty template.save() from erpnext.stock.reorder_item import reorder_item mr_list = reorder_item() frappe.db.set_value("Stock Settings", None, "auto_indent", 0) items = [] for mr in mr_list: for d in mr.items: items.append(d.item_code) self.assertTrue(item_code in items)
def test_return_entire_bundled_items(self): set_perpetual_inventory() create_stock_reconciliation(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, rate=100) create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=50, rate=100) dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500) # return bundled item dn1 = create_delivery_note(item_code='_Test Product Bundle Item', is_return=1, return_against=dn.name, qty=-2, rate=500) # qty after return actual_qty = get_qty_after_transaction() self.assertEquals(actual_qty, 35) # Check incoming rate for return entry incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name}, ["incoming_rate", "stock_value_difference"]) self.assertEquals(incoming_rate, 100) # Check gl entry for warehouse gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name, "account": "_Test Warehouse - _TC"}, "debit") self.assertEquals(gle_warehouse_amount, 1400) set_perpetual_inventory(0)
def make_items(): items = ['Test Finished Goods - A', 'Test FG A RW 1', 'Test FG A RW 2', 'Alternate Item For A RW 1'] for item_code in items: if not frappe.db.exists('Item', item_code): create_item(item_code) create_stock_reconciliation(item_code="Test FG A RW 1", warehouse='_Test Warehouse - _TC', qty=10, rate=2000) if frappe.db.exists('Item', 'Test FG A RW 1'): doc = frappe.get_doc('Item', 'Test FG A RW 1') doc.allow_alternative_item = 1 doc.save() if frappe.db.exists('Item', 'Test Finished Goods - A'): doc = frappe.get_doc('Item', 'Test Finished Goods - A') doc.is_sub_contracted_item = 1 doc.save() if not frappe.db.get_value('BOM', {'item': 'Test Finished Goods - A', 'docstatus': 1}): make_bom(item = 'Test Finished Goods - A', raw_materials = ['Test FG A RW 1', 'Test FG A RW 2']) if not frappe.db.get_value('Warehouse', {'warehouse_name': 'Test Supplier Warehouse'}): frappe.get_doc({ 'doctype': 'Warehouse', 'warehouse_name': 'Test Supplier Warehouse', 'company': '_Test Company' }).insert(ignore_permissions=True)
def test_material_transfer_gl_entry(self): set_perpetual_inventory() create_stock_reconciliation(qty=100, rate=100) mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", target="_Test Warehouse 1 - _TC", qty=45) self.check_stock_ledger_entries("Stock Entry", mtn.name, [["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]]) stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": mtn.get("items")[0].s_warehouse}) fixed_asset_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": mtn.get("items")[0].t_warehouse}) stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", "voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference")) self.check_gl_entries("Stock Entry", mtn.name, sorted([ [stock_in_hand_account, 0.0, stock_value_diff], [fixed_asset_account, stock_value_diff, 0.0], ]) ) mtn.cancel() self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
def test_alternative_item_for_production_rm(self): create_stock_reconciliation(item_code='Alternate Item For A RW 1', warehouse='_Test Warehouse - _TC',qty=5, rate=2000) create_stock_reconciliation(item_code='Test FG A RW 2', warehouse='_Test Warehouse - _TC', qty=5, rate=2000) pro_order = make_wo_order_test_record(production_item='Test Finished Goods - A', qty=5, source_warehouse='_Test Warehouse - _TC', wip_warehouse='Test Supplier Warehouse - _TC') reserved_qty_for_production = frappe.db.get_value('Bin', {'item_code': 'Test FG A RW 1', 'warehouse': '_Test Warehouse - _TC'}, 'reserved_qty_for_production') ste = frappe.get_doc(make_stock_entry(pro_order.name, "Material Transfer for Manufacture", 5)) ste.insert() for item in ste.items: if item.item_code == 'Test FG A RW 1': item.item_code = 'Alternate Item For A RW 1' item.item_name = 'Alternate Item For A RW 1' item.description = 'Alternate Item For A RW 1' item.original_item = 'Test FG A RW 1' ste.submit() reserved_qty_for_production_after_transfer = frappe.db.get_value('Bin', {'item_code': 'Test FG A RW 1', 'warehouse': '_Test Warehouse - _TC'}, 'reserved_qty_for_production') self.assertEqual(reserved_qty_for_production_after_transfer, flt(reserved_qty_for_production - 5)) ste1 = frappe.get_doc(make_stock_entry(pro_order.name, "Manufacture", 5)) status = False for d in ste1.items: if d.item_code == 'Alternate Item For A RW 1': status = True self.assertEqual(status, True) ste1.submit()
def make_items(): items = ['Test Finished Goods - A', 'Test FG A RW 1', 'Test FG A RW 2', 'Alternate Item For A RW 1'] for item_code in items: if not frappe.db.exists('Item', item_code): create_item(item_code) create_stock_reconciliation(item_code="Test FG A RW 1", warehouse='_Test Warehouse - _TC', qty=10, rate=2000) if frappe.db.exists('Item', 'Test FG A RW 1'): doc = frappe.get_doc('Item', 'Test FG A RW 1') doc.allow_alternative_item = 1 doc.save() if frappe.db.exists('Item', 'Test Finished Goods - A'): doc = frappe.get_doc('Item', 'Test Finished Goods - A') doc.is_sub_contracted_item = 1 doc.save() if not frappe.db.get_value('BOM', {'item': 'Test Finished Goods - A', 'docstatus': 1}): make_bom(item = 'Test Finished Goods - A', raw_materials = ['Test FG A RW 1', 'Test FG A RW 2']) if not frappe.db.get_value('Warehouse', {'warehouse_name': 'Test Supplier Warehouse'}): frappe.get_doc({ 'doctype': 'Warehouse', 'warehouse_name': 'Test Supplier Warehouse', 'company': '_Test Company' }).insert(ignore_permissions=True)
def _test_auto_material_request(self, item_code): item = frappe.get_doc("Item", item_code) if item.variant_of: template = frappe.get_doc("Item", item.variant_of) else: template = item # stock entry reqd for auto-reorder create_stock_reconciliation(item_code=item_code, warehouse="_Test Warehouse - _TC", qty=10, rate=100) frappe.db.set_value("Stock Settings", None, "auto_indent", 1) projected_qty = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": "_Test Warehouse - _TC"}, "projected_qty") or 0 # update re-level qty so that it is more than projected_qty if projected_qty > template.reorder_levels[0].warehouse_reorder_level: template.reorder_levels[0].warehouse_reorder_level += projected_qty template.save() from erpnext.stock.reorder_item import reorder_item mr_list = reorder_item() frappe.db.set_value("Stock Settings", None, "auto_indent", 0) items = [] for mr in mr_list: for d in mr.items: items.append(d.item_code) self.assertTrue(item_code in items)
def _test_auto_material_request(self, item_code, material_request_type="Purchase", warehouse="_Test Warehouse - _TC"): variant = frappe.get_doc("Item", item_code) projected_qty, actual_qty = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, ["projected_qty", "actual_qty"]) or [0, 0] # stock entry reqd for auto-reorder create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty = actual_qty + abs(projected_qty) + 10, rate=100) projected_qty = frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "projected_qty") or 0 frappe.db.set_value("Stock Settings", None, "auto_indent", 1) # update re-level qty so that it is more than projected_qty if projected_qty >= variant.reorder_levels[0].warehouse_reorder_level: variant.reorder_levels[0].warehouse_reorder_level += projected_qty variant.reorder_levels[0].material_request_type = material_request_type variant.save() from erpnext.stock.reorder_item import reorder_item mr_list = reorder_item() frappe.db.set_value("Stock Settings", None, "auto_indent", 0) items = [] for mr in mr_list: for d in mr.items: items.append(d.item_code) self.assertTrue(item_code in items)
def test_material_transfer_gl_entry(self): set_perpetual_inventory() create_stock_reconciliation(qty=100, rate=100) mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", target="_Test Warehouse 1 - _TC", qty=45) self.check_stock_ledger_entries("Stock Entry", mtn.name, [["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]]) stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": mtn.get("items")[0].s_warehouse}) fixed_asset_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": mtn.get("items")[0].t_warehouse}) stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", "voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference")) self.check_gl_entries("Stock Entry", mtn.name, sorted([ [stock_in_hand_account, 0.0, stock_value_diff], [fixed_asset_account, stock_value_diff, 0.0], ]) ) mtn.cancel() self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
def test_update_bom_cost_in_all_boms(self): # get current rate for '_Test Item 2' rm_rate = frappe.db.sql("""select rate from `tabBOM Item` where parent='BOM-_Test Item Home Desktop Manufactured-001' and item_code='_Test Item 2' and docstatus=1 and parenttype='BOM'""") rm_rate = rm_rate[0][0] if rm_rate else 0 # update valuation rate of item '_Test Item 2' warehouse_list = frappe.db.sql_list("""select warehouse from `tabBin` where item_code='_Test Item 2' and actual_qty > 0""") if not warehouse_list: warehouse_list.append("_Test Warehouse - _TC") for warehouse in warehouse_list: create_stock_reconciliation(item_code="_Test Item 2", warehouse=warehouse, qty=200, rate=rm_rate + 10) # update cost of all BOMs based on latest valuation rate update_cost() # check if new valuation rate updated in all BOMs for d in frappe.db.sql("""select rate from `tabBOM Item` where item_code='_Test Item 2' and docstatus=1 and parenttype='BOM'""", as_dict=1): self.assertEqual(d.rate, rm_rate + 10)
def test_update_bom_cost_in_all_boms(self): # get current rate for '_Test Item 2' rm_rate = frappe.db.sql("""select rate from `tabBOM Item` where parent='BOM-_Test Item Home Desktop Manufactured-001' and item_code='_Test Item 2' and docstatus=1""") rm_rate = rm_rate[0][0] if rm_rate else 0 # update valuation rate of item '_Test Item 2' warehouse_list = frappe.db.sql_list("""select warehouse from `tabBin` where item_code='_Test Item 2' and actual_qty > 0""") if not warehouse_list: warehouse_list.append("_Test Warehouse - _TC") for warehouse in warehouse_list: create_stock_reconciliation(item_code="_Test Item 2", warehouse=warehouse, qty=200, rate=rm_rate + 10) # update cost of all BOMs based on latest valuation rate update_cost() # check if new valuation rate updated in all BOMs for d in frappe.db.sql("""select rate from `tabBOM Item` where item_code='_Test Item 2' and docstatus=1""", as_dict=1): self.assertEqual(d.rate, rm_rate + 10)
def test_alternative_item_for_production_rm(self): create_stock_reconciliation(item_code="Alternate Item For A RW 1", warehouse="_Test Warehouse - _TC", qty=5, rate=2000) create_stock_reconciliation(item_code="Test FG A RW 2", warehouse="_Test Warehouse - _TC", qty=5, rate=2000) pro_order = make_wo_order_test_record( production_item="Test Finished Goods - A", qty=5, source_warehouse="_Test Warehouse - _TC", wip_warehouse="Test Supplier Warehouse - _TC", ) reserved_qty_for_production = frappe.db.get_value( "Bin", { "item_code": "Test FG A RW 1", "warehouse": "_Test Warehouse - _TC" }, "reserved_qty_for_production", ) ste = frappe.get_doc( make_stock_entry(pro_order.name, "Material Transfer for Manufacture", 5)) ste.insert() for item in ste.items: if item.item_code == "Test FG A RW 1": item.item_code = "Alternate Item For A RW 1" item.item_name = "Alternate Item For A RW 1" item.description = "Alternate Item For A RW 1" item.original_item = "Test FG A RW 1" ste.submit() reserved_qty_for_production_after_transfer = frappe.db.get_value( "Bin", { "item_code": "Test FG A RW 1", "warehouse": "_Test Warehouse - _TC" }, "reserved_qty_for_production", ) self.assertEqual(reserved_qty_for_production_after_transfer, flt(reserved_qty_for_production - 5)) ste1 = frappe.get_doc( make_stock_entry(pro_order.name, "Manufacture", 5)) status = False for d in ste1.items: if d.item_code == "Alternate Item For A RW 1": status = True self.assertEqual(status, True) ste1.submit()
def test_return_single_item_from_bundled_items(self): set_perpetual_inventory() create_stock_reconciliation(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, rate=100) create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=50, rate=100) dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500) # Qty after delivery actual_qty_1 = get_qty_after_transaction() self.assertEquals(actual_qty_1, 25) # outgoing_rate outgoing_rate = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item" }, "stock_value_difference") / 25 # return 'test item' from packed items dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500) # qty after return actual_qty_2 = get_qty_after_transaction() self.assertEquals(actual_qty_2, 35) # Check incoming rate for return entry incoming_rate, stock_value_difference = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Delivery Note", "voucher_no": dn1.name }, ["incoming_rate", "stock_value_difference"]) self.assertEquals(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) # Check gl entry for warehouse gle_warehouse_amount = frappe.db.get_value( "GL Entry", { "voucher_type": "Delivery Note", "voucher_no": dn1.name, "account": "_Test Warehouse - _TC" }, "debit") self.assertEquals(gle_warehouse_amount, stock_value_difference) set_perpetual_inventory(0)
def test_delivery_of_bundled_items_to_target_warehouse(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item Home Desktop 100", "FIFO") target_warehouse=get_warehouse(company=company, abbr="TCP1", warehouse_name="_Test Customer Warehouse").name for warehouse in ("Stores - TCP1", target_warehouse): create_stock_reconciliation(item_code="_Test Item", warehouse=warehouse, company = company, expense_account = "Stock Adjustment - TCP1", qty=500, rate=100) create_stock_reconciliation(item_code="_Test Item Home Desktop 100", company = company, expense_account = "Stock Adjustment - TCP1", warehouse=warehouse, qty=500, rate=100) dn = create_delivery_note(item_code="_Test Product Bundle Item", company='_Test Company with perpetual inventory', cost_center = 'Main - TCP1', expense_account = "Cost of Goods Sold - TCP1", do_not_submit=True, qty=5, rate=500, warehouse="Stores - TCP1", target_warehouse=target_warehouse) dn.submit() # qty after delivery actual_qty_at_source = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty_at_source, 475) actual_qty_at_target = get_qty_after_transaction(warehouse=target_warehouse) self.assertEqual(actual_qty_at_target, 525) # stock value diff for source warehouse for "_Test Item" stock_value_difference = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item", "warehouse": "Stores - TCP1"}, "stock_value_difference") # stock value diff for target warehouse stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item", "warehouse": target_warehouse}, "stock_value_difference") self.assertEqual(abs(stock_value_difference), stock_value_difference1) # Check gl entries gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) stock_value_difference = abs(frappe.db.sql("""select sum(stock_value_difference) from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s and warehouse='Stores - TCP1'""", dn.name)[0][0]) expected_values = { "Stock In Hand - TCP1": [0.0, stock_value_difference], target_warehouse: [stock_value_difference, 0.0] } for i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account))
def test_delivery_of_bundled_items_to_target_warehouse(self): set_perpetual_inventory() frappe.db.set_value("Item", "_Test Item", "valuation_method", "FIFO") for warehouse in ("_Test Warehouse - _TC", "_Test Warehouse 1 - _TC"): create_stock_reconciliation(item_code="_Test Item", target=warehouse, qty=50, rate=100) create_stock_reconciliation(item_code="_Test Item Home Desktop 100", target=warehouse, qty=50, rate=100) opening_qty_test_warehouse_1 = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC") dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500, target_warehouse="_Test Warehouse 1 - _TC", do_not_submit=True) dn.submit() # qty after delivery actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse - _TC") self.assertEquals(actual_qty, 25) actual_qty = get_qty_after_transaction(warehouse="_Test Warehouse 1 - _TC") self.assertEquals(actual_qty, opening_qty_test_warehouse_1 + 25) # stock value diff for source warehouse stock_value_difference = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference") # stock value diff for target warehouse stock_value_difference1 = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse 1 - _TC"}, "stock_value_difference") self.assertEquals(abs(stock_value_difference), stock_value_difference1) # Check gl entries gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) stock_value_difference = abs(frappe.db.sql("""select sum(stock_value_difference) from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s and warehouse='_Test Warehouse - _TC'""", dn.name)[0][0]) expected_values = { "_Test Warehouse - _TC": [0.0, stock_value_difference], "_Test Warehouse 1 - _TC": [stock_value_difference, 0.0] } for i, gle in enumerate(gl_entries): self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) set_perpetual_inventory(0)
def test_production_plan_for_existing_ordered_qty(self): sr1 = create_stock_reconciliation(item_code="Raw Material Item 1", target="_Test Warehouse - _TC", qty=1, rate=100) sr2 = create_stock_reconciliation(item_code="Raw Material Item 2", target="_Test Warehouse - _TC", qty=1, rate=100) pln = create_production_plan(item_code='Test Production Item 1', ignore_existing_ordered_qty=0) self.assertTrue(len(pln.mr_items), 1) self.assertTrue(flt(pln.mr_items[0].quantity), 1.0) sr1.cancel() sr2.cancel() pln.cancel()
def test_production_plan_without_multi_level_for_existing_ordered_qty(self): sr1 = create_stock_reconciliation(item_code="Raw Material Item 1", target="_Test Warehouse - _TC", qty=1, rate=100) sr2 = create_stock_reconciliation(item_code="Subassembly Item 1", target="_Test Warehouse - _TC", qty=1, rate=100) pln = create_production_plan(item_code='Test Production Item 1', use_multi_level_bom=0, ignore_existing_ordered_qty=0) self.assertTrue(len(pln.mr_items), 0) sr1.cancel() sr2.cancel() pln.cancel()
def test_production_plan_for_existing_ordered_qty(self): sr1 = create_stock_reconciliation(item_code="Raw Material Item 1", target="_Test Warehouse - _TC", qty=1, rate=100) sr2 = create_stock_reconciliation(item_code="Raw Material Item 2", target="_Test Warehouse - _TC", qty=1, rate=100) pln = create_production_plan(item_code='Test Production Item 1', ignore_existing_ordered_qty=0) self.assertTrue(len(pln.mr_items), 1) self.assertTrue(flt(pln.mr_items[0].quantity), 1.0) sr1.cancel() sr2.cancel() pln.cancel()
def test_production_plan_without_multi_level_for_existing_ordered_qty(self): sr1 = create_stock_reconciliation(item_code="Raw Material Item 1", target="_Test Warehouse - _TC", qty=1, rate=100) sr2 = create_stock_reconciliation(item_code="Subassembly Item 1", target="_Test Warehouse - _TC", qty=1, rate=100) pln = create_production_plan(item_code='Test Production Item 1', use_multi_level_bom=0, ignore_existing_ordered_qty=0) self.assertTrue(len(pln.mr_items), 0) sr1.cancel() sr2.cancel() pln.cancel()
def test_fifo(self): frappe.db.set_value("Stock Settings", None, "allow_negative_stock", 1) item_code = "_Test Item 2" warehouse = "_Test Warehouse - _TC" create_stock_reconciliation(item_code="_Test Item 2", warehouse="_Test Warehouse - _TC", qty=0, rate=100) make_stock_entry(item_code=item_code, target=warehouse, qty=1, basic_rate=10) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 10]], frappe.safe_eval(sle.stock_queue)) # negative qty make_stock_entry(item_code=item_code, source=warehouse, qty=2, basic_rate=10) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[-1, 10]], frappe.safe_eval(sle.stock_queue)) # further negative make_stock_entry(item_code=item_code, source=warehouse, qty=1) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[-2, 10]], frappe.safe_eval(sle.stock_queue)) # move stock to positive make_stock_entry(item_code=item_code, target=warehouse, qty=3, basic_rate=20) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 20]], frappe.safe_eval(sle.stock_queue)) # incoming entry with diff rate make_stock_entry(item_code=item_code, target=warehouse, qty=1, basic_rate=30) sle = get_sle(item_code=item_code, warehouse=warehouse)[0] self.assertEqual([[1, 20], [1, 30]], frappe.safe_eval(sle.stock_queue)) frappe.db.set_default("allow_negative_stock", 0)
def test_return_single_item_from_bundled_items(self): set_perpetual_inventory() create_stock_reconciliation(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, rate=100) create_stock_reconciliation( item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=50, rate=100 ) dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500) # Qty after delivery actual_qty_1 = get_qty_after_transaction() self.assertEquals(actual_qty_1, 25) # outgoing_rate outgoing_rate = ( frappe.db.get_value( "Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item"}, "stock_value_difference", ) / 25 ) # return 'test item' from packed items dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500) # qty after return actual_qty_2 = get_qty_after_transaction() self.assertEquals(actual_qty_2, 35) # Check incoming rate for return entry incoming_rate, stock_value_difference = frappe.db.get_value( "Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name}, ["incoming_rate", "stock_value_difference"], ) self.assertEquals(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) # Check gl entry for warehouse gle_warehouse_amount = frappe.db.get_value( "GL Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name, "account": "_Test Warehouse - _TC"}, "debit", ) self.assertEquals(gle_warehouse_amount, stock_value_difference) set_perpetual_inventory(0)
def reset_item_valuation_rate(item_code, warehouse_list=None, qty=None, rate=None): if warehouse_list and isinstance(warehouse_list, string_types): warehouse_list = [warehouse_list] if not warehouse_list: warehouse_list = frappe.db.sql_list(""" select warehouse from `tabBin` where item_code=%s and actual_qty > 0 """, item_code) if not warehouse_list: warehouse_list.append("_Test Warehouse - _TC") for warehouse in warehouse_list: create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=qty, rate=rate)
def test_alternative_item_for_subcontract_rm(self): create_stock_reconciliation(item_code='Alternate Item For A RW 1', warehouse='_Test Warehouse - _TC', qty=5, rate=2000) create_stock_reconciliation(item_code='Test FG A RW 2', warehouse='_Test Warehouse - _TC', qty=5, rate=2000) supplier_warehouse = "Test Supplier Warehouse - _TC" po = create_purchase_order(item = "Test Finished Goods - A", is_subcontracted='Yes', qty=5, rate=3000, supplier_warehouse=supplier_warehouse) rm_item = [{"item_code": "Test Finished Goods - A", "rm_item_code": "Test FG A RW 1", "item_name":"Test FG A RW 1", "qty":5, "warehouse":"_Test Warehouse - _TC", "rate":2000, "amount":10000, "stock_uom":"Nos"}, {"item_code": "Test Finished Goods - A", "rm_item_code": "Test FG A RW 2", "item_name":"Test FG A RW 2", "qty":5, "warehouse":"_Test Warehouse - _TC", "rate":2000, "amount":10000, "stock_uom":"Nos"}] rm_item_string = json.dumps(rm_item) reserved_qty_for_sub_contract = frappe.db.get_value('Bin', {'item_code': 'Test FG A RW 1', 'warehouse': '_Test Warehouse - _TC'}, 'reserved_qty_for_sub_contract') se = frappe.get_doc(make_rm_stock_entry(po.name, rm_item_string)) se.to_warehouse = supplier_warehouse se.insert() doc = frappe.get_doc('Stock Entry', se.name) for item in doc.items: if item.item_code == 'Test FG A RW 1': item.item_code = 'Alternate Item For A RW 1' item.item_name = 'Alternate Item For A RW 1' item.description = 'Alternate Item For A RW 1' item.original_item = 'Test FG A RW 1' doc.save() doc.submit() after_transfer_reserved_qty_for_sub_contract = frappe.db.get_value('Bin', {'item_code': 'Test FG A RW 1', 'warehouse': '_Test Warehouse - _TC'}, 'reserved_qty_for_sub_contract') self.assertEqual(after_transfer_reserved_qty_for_sub_contract, flt(reserved_qty_for_sub_contract - 5)) pr = make_purchase_receipt(po.name) pr.save() pr = frappe.get_doc('Purchase Receipt', pr.name) status = False for d in pr.supplied_items: if d.rm_item_code == 'Alternate Item For A RW 1': status = True self.assertEqual(status, True)
def test_alternative_item_for_subcontract_rm(self): create_stock_reconciliation(item_code='Alternate Item For A RW 1', warehouse='_Test Warehouse - _TC', qty=5, rate=2000) create_stock_reconciliation(item_code='Test FG A RW 2', warehouse='_Test Warehouse - _TC', qty=5, rate=2000) supplier_warehouse = "Test Supplier Warehouse - _TC" po = create_purchase_order(item = "Test Finished Goods - A", is_subcontracted='Yes', qty=5, rate=3000, supplier_warehouse=supplier_warehouse) rm_item = [{"item_code": "Test Finished Goods - A", "rm_item_code": "Test FG A RW 1", "item_name":"Test FG A RW 1", "qty":5, "warehouse":"_Test Warehouse - _TC", "rate":2000, "amount":10000, "stock_uom":"Nos"}, {"item_code": "Test Finished Goods - A", "rm_item_code": "Test FG A RW 2", "item_name":"Test FG A RW 2", "qty":5, "warehouse":"_Test Warehouse - _TC", "rate":2000, "amount":10000, "stock_uom":"Nos"}] rm_item_string = json.dumps(rm_item) reserved_qty_for_sub_contract = frappe.db.get_value('Bin', {'item_code': 'Test FG A RW 1', 'warehouse': '_Test Warehouse - _TC'}, 'reserved_qty_for_sub_contract') se = frappe.get_doc(make_rm_stock_entry(po.name, rm_item_string)) se.to_warehouse = supplier_warehouse se.insert() doc = frappe.get_doc('Stock Entry', se.name) for item in doc.items: if item.item_code == 'Test FG A RW 1': item.item_code = 'Alternate Item For A RW 1' item.item_name = 'Alternate Item For A RW 1' item.description = 'Alternate Item For A RW 1' item.original_item = 'Test FG A RW 1' doc.save() doc.submit() after_transfer_reserved_qty_for_sub_contract = frappe.db.get_value('Bin', {'item_code': 'Test FG A RW 1', 'warehouse': '_Test Warehouse - _TC'}, 'reserved_qty_for_sub_contract') self.assertEqual(after_transfer_reserved_qty_for_sub_contract, flt(reserved_qty_for_sub_contract - 5)) pr = make_purchase_receipt(po.name) pr.save() pr = frappe.get_doc('Purchase Receipt', pr.name) status = False for d in pr.supplied_items: if d.rm_item_code == 'Alternate Item For A RW 1': status = True self.assertEqual(status, True)
def test_return_single_item_from_bundled_items(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') create_stock_reconciliation(item_code="_Test Item", warehouse="Stores - TCP1", qty=50, rate=100, company=company, expense_account = "Stock Adjustment - TCP1") create_stock_reconciliation(item_code="_Test Item Home Desktop 100", warehouse="Stores - TCP1", qty=50, rate=100, company=company, expense_account = "Stock Adjustment - TCP1") dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") # Qty after delivery actual_qty_1 = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty_1, 25) # outgoing_rate outgoing_rate = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item"}, "stock_value_difference") / 25 # return 'test item' from packed items dn1 = create_delivery_note(is_return=1, return_against=dn.name, qty=-10, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") # qty after return actual_qty_2 = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty_2, 35) # Check incoming rate for return entry incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name}, ["incoming_rate", "stock_value_difference"]) self.assertEqual(flt(incoming_rate, 3), abs(flt(outgoing_rate, 3))) stock_in_hand_account = get_inventory_account(company, dn1.items[0].warehouse) # Check gl entry for warehouse gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name, "account": stock_in_hand_account}, "debit") self.assertEqual(gle_warehouse_amount, stock_value_difference)
def make_items(): items = [ "Test Finished Goods - A", "Test FG A RW 1", "Test FG A RW 2", "Alternate Item For A RW 1", ] for item_code in items: if not frappe.db.exists("Item", item_code): create_item(item_code) try: create_stock_reconciliation(item_code="Test FG A RW 1", warehouse="_Test Warehouse - _TC", qty=10, rate=2000) except EmptyStockReconciliationItemsError: pass if frappe.db.exists("Item", "Test FG A RW 1"): doc = frappe.get_doc("Item", "Test FG A RW 1") doc.allow_alternative_item = 1 doc.save() if frappe.db.exists("Item", "Test Finished Goods - A"): doc = frappe.get_doc("Item", "Test Finished Goods - A") doc.is_sub_contracted_item = 1 doc.save() if not frappe.db.get_value("BOM", { "item": "Test Finished Goods - A", "docstatus": 1 }): make_bom(item="Test Finished Goods - A", raw_materials=["Test FG A RW 1", "Test FG A RW 2"]) if not frappe.db.get_value("Warehouse", {"warehouse_name": "Test Supplier Warehouse"}): frappe.get_doc({ "doctype": "Warehouse", "warehouse_name": "Test Supplier Warehouse", "company": "_Test Company", }).insert(ignore_permissions=True)
def test_return_entire_bundled_items(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') create_stock_reconciliation(item_code="_Test Item", warehouse="Stores - TCP1", qty=50, rate=100, company=company, expense_account = "Stock Adjustment - TCP1") create_stock_reconciliation(item_code="_Test Item Home Desktop 100", warehouse="Stores - TCP1", qty=50, rate=100, company=company, expense_account = "Stock Adjustment - TCP1") actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty, 50) dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") # qty after return actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty, 25) # return bundled item dn1 = create_delivery_note(item_code='_Test Product Bundle Item', is_return=1, return_against=dn.name, qty=-2, rate=500, company=company, warehouse="Stores - TCP1", expense_account="Cost of Goods Sold - TCP1", cost_center="Main - TCP1") # qty after return actual_qty = get_qty_after_transaction(warehouse="Stores - TCP1") self.assertEqual(actual_qty, 35) # Check incoming rate for return entry incoming_rate, stock_value_difference = frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name}, ["incoming_rate", "stock_value_difference"]) self.assertEqual(incoming_rate, 100) stock_in_hand_account = get_inventory_account('_Test Company', dn1.items[0].warehouse) # Check gl entry for warehouse gle_warehouse_amount = frappe.db.get_value("GL Entry", {"voucher_type": "Delivery Note", "voucher_no": dn1.name, "account": stock_in_hand_account}, "debit") self.assertEqual(gle_warehouse_amount, 1400)
def test_production_plan_for_existing_ordered_qty(self): """ - Enable 'ignore_existing_ordered_qty'. - Test if MR Planning table pulls Raw Material Qty even if it is in stock. """ sr1 = create_stock_reconciliation(item_code="Raw Material Item 1", target="_Test Warehouse - _TC", qty=1, rate=110) sr2 = create_stock_reconciliation(item_code="Raw Material Item 2", target="_Test Warehouse - _TC", qty=1, rate=120) pln = create_production_plan(item_code="Test Production Item 1", ignore_existing_ordered_qty=1) self.assertTrue(len(pln.mr_items), 1) self.assertTrue(flt(pln.mr_items[0].quantity), 1.0) sr1.cancel() sr2.cancel() pln.cancel()
def test_material_transfer_gl_entry(self): company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') set_perpetual_inventory(1, company) create_stock_reconciliation(qty=100, rate=100) mtn = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", target="_Test Warehouse 1 - _TC", qty=45) self.check_stock_ledger_entries("Stock Entry", mtn.name, [["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]]) stock_in_hand_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse) fixed_asset_account = get_inventory_account(mtn.company, mtn.get("items")[0].t_warehouse) if stock_in_hand_account == fixed_asset_account: # no gl entry as both source and target warehouse has linked to same account. self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) else: stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", "voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference")) self.check_gl_entries("Stock Entry", mtn.name, sorted([ [stock_in_hand_account, 0.0, stock_value_diff], [fixed_asset_account, stock_value_diff, 0.0], ]) ) mtn.cancel() self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name))
def initialize_records_for_future_negative_sle_test( item_code, batch_no, warehouses, opening_qty, posting_date ): from erpnext.stock.doctype.batch.test_batch import TestBatch, make_new_batch from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import ( create_stock_reconciliation, ) from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse TestBatch.make_batch_item(item_code) make_new_batch(item_code=item_code, batch_id=batch_no) warehouse_names = [create_warehouse(w) for w in warehouses] create_stock_reconciliation( purpose="Opening Stock", posting_date=posting_date, posting_time="20:00:20", item_code=item_code, warehouse=warehouse_names[0], valuation_rate=100, qty=opening_qty, batch_no=batch_no, ) return warehouse_names
def test_pick_list_shows_serial_no_for_serialized_item(self): create_stock_reconciliation( item_code="_Test Serialized Item", target="_Test Warehouse - _TC", qty=5, rate=100, serial_no='123450\n123451\n123452\n123453\n123454') pick_list = frappe.get_doc({ 'doctype': 'Pick List', 'company': '_Test Company', 'customer': '_Test Customer', 'items_based_on': 'Sales Order', 'locations': [{ 'item_code': '_Test Serialized Item', 'qty': 1000, 'stock_qty': 1000, 'conversion_factor': 1, 'sales_order': '_T-Sales Order-1', 'sales_order_item': '_T-Sales Order-1_item', }] }) pick_list.set_item_locations() self.assertEqual( pick_list.get("locations")[0].item_code, '_Test Serialized Item') self.assertEqual( pick_list.get("locations")[0].warehouse, '_Test Warehouse - _TC') self.assertEqual(pick_list.get("locations")[0].qty, 5) self.assertEqual( pick_list.get("locations")[0].serial_no, '123450\n123451\n123452\n123453\n123454')
def test_production_plan_without_multi_level_for_existing_ordered_qty( self): """ - Disable 'ignore_existing_ordered_qty'. - Test if MR Planning table avoids pulling Raw Material Qty as it is in stock for non exploded BOM. """ sr1 = create_stock_reconciliation(item_code="Raw Material Item 1", target="_Test Warehouse - _TC", qty=1, rate=130) sr2 = create_stock_reconciliation(item_code="Subassembly Item 1", target="_Test Warehouse - _TC", qty=1, rate=140) pln = create_production_plan(item_code="Test Production Item 1", use_multi_level_bom=0, ignore_existing_ordered_qty=0) self.assertTrue(len(pln.mr_items), 0) sr1.cancel() sr2.cancel() pln.cancel()
def test_delivery_of_bundled_items_to_target_warehouse(self): company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') set_perpetual_inventory(1, company) set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item Home Desktop 100", "FIFO") for warehouse in ("_Test Warehouse - _TC", "_Test Warehouse 1 - _TC"): create_stock_reconciliation(item_code="_Test Item", target=warehouse, qty=100, rate=100) create_stock_reconciliation( item_code="_Test Item Home Desktop 100", target=warehouse, qty=100, rate=100) opening_qty_test_warehouse_1 = get_qty_after_transaction( warehouse="_Test Warehouse 1 - _TC") dn = create_delivery_note(item_code="_Test Product Bundle Item", qty=5, rate=500, target_warehouse="_Test Warehouse 1 - _TC", do_not_submit=True) dn.submit() # qty after delivery actual_qty = get_qty_after_transaction( warehouse="_Test Warehouse - _TC") self.assertEquals(actual_qty, 75) actual_qty = get_qty_after_transaction( warehouse="_Test Warehouse 1 - _TC") self.assertEquals(actual_qty, opening_qty_test_warehouse_1 + 25) # stock value diff for source warehouse # for "_Test Item" stock_value_difference = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC" }, "stock_value_difference") # stock value diff for target warehouse stock_value_difference1 = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item", "warehouse": "_Test Warehouse 1 - _TC" }, "stock_value_difference") self.assertEquals(abs(stock_value_difference), stock_value_difference1) # for "_Test Item Home Desktop 100" stock_value_difference = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse - _TC" }, "stock_value_difference") # stock value diff for target warehouse stock_value_difference1 = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item Home Desktop 100", "warehouse": "_Test Warehouse 1 - _TC" }, "stock_value_difference") self.assertEquals(abs(stock_value_difference), stock_value_difference1) # Check gl entries gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) stock_value_difference = abs( frappe.db.sql( """select sum(stock_value_difference) from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s and warehouse='_Test Warehouse - _TC'""", dn.name)[0][0]) expected_values = { "Stock In Hand - _TC": [0.0, stock_value_difference], "_Test Warehouse 1 - _TC": [stock_value_difference, 0.0] } for i, gle in enumerate(gl_entries): self.assertEquals([gle.debit, gle.credit], expected_values.get(gle.account)) set_perpetual_inventory(0, company)
def test_alternative_item_for_subcontract_rm(self): frappe.db.set_value("Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", "BOM") create_stock_reconciliation(item_code="Alternate Item For A RW 1", warehouse="_Test Warehouse - _TC", qty=5, rate=2000) create_stock_reconciliation(item_code="Test FG A RW 2", warehouse="_Test Warehouse - _TC", qty=5, rate=2000) supplier_warehouse = "Test Supplier Warehouse - _TC" po = create_purchase_order( item="Test Finished Goods - A", is_subcontracted="Yes", qty=5, rate=3000, supplier_warehouse=supplier_warehouse, ) rm_item = [ { "item_code": "Test Finished Goods - A", "rm_item_code": "Test FG A RW 1", "item_name": "Test FG A RW 1", "qty": 5, "warehouse": "_Test Warehouse - _TC", "rate": 2000, "amount": 10000, "stock_uom": "Nos", }, { "item_code": "Test Finished Goods - A", "rm_item_code": "Test FG A RW 2", "item_name": "Test FG A RW 2", "qty": 5, "warehouse": "_Test Warehouse - _TC", "rate": 2000, "amount": 10000, "stock_uom": "Nos", }, ] rm_item_string = json.dumps(rm_item) reserved_qty_for_sub_contract = frappe.db.get_value( "Bin", { "item_code": "Test FG A RW 1", "warehouse": "_Test Warehouse - _TC" }, "reserved_qty_for_sub_contract", ) se = frappe.get_doc(make_rm_stock_entry(po.name, rm_item_string)) se.to_warehouse = supplier_warehouse se.insert() doc = frappe.get_doc("Stock Entry", se.name) for item in doc.items: if item.item_code == "Test FG A RW 1": item.item_code = "Alternate Item For A RW 1" item.item_name = "Alternate Item For A RW 1" item.description = "Alternate Item For A RW 1" item.original_item = "Test FG A RW 1" doc.save() doc.submit() after_transfer_reserved_qty_for_sub_contract = frappe.db.get_value( "Bin", { "item_code": "Test FG A RW 1", "warehouse": "_Test Warehouse - _TC" }, "reserved_qty_for_sub_contract", ) self.assertEqual(after_transfer_reserved_qty_for_sub_contract, flt(reserved_qty_for_sub_contract - 5)) pr = make_purchase_receipt(po.name) pr.save() pr = frappe.get_doc("Purchase Receipt", pr.name) status = False for d in pr.supplied_items: if d.rm_item_code == "Alternate Item For A RW 1": status = True self.assertEqual(status, True) frappe.db.set_value( "Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", "Material Transferred for Subcontract", )
def test_delivery_of_bundled_items_to_target_warehouse(self): from erpnext.selling.doctype.customer.test_customer import create_internal_customer company = frappe.db.get_value("Warehouse", "Stores - TCP1", "company") customer_name = create_internal_customer( customer_name="_Test Internal Customer 2", represents_company="_Test Company with perpetual inventory", allowed_to_interact_with="_Test Company with perpetual inventory", ) set_valuation_method("_Test Item", "FIFO") set_valuation_method("_Test Item Home Desktop 100", "FIFO") target_warehouse = get_warehouse( company=company, abbr="TCP1", warehouse_name="_Test Customer Warehouse").name for warehouse in ("Stores - TCP1", target_warehouse): create_stock_reconciliation( item_code="_Test Item", warehouse=warehouse, company=company, expense_account="Stock Adjustment - TCP1", qty=500, rate=100, ) create_stock_reconciliation( item_code="_Test Item Home Desktop 100", company=company, expense_account="Stock Adjustment - TCP1", warehouse=warehouse, qty=500, rate=100, ) dn = create_delivery_note( item_code="_Test Product Bundle Item", company="_Test Company with perpetual inventory", customer=customer_name, cost_center="Main - TCP1", expense_account="Cost of Goods Sold - TCP1", qty=5, rate=500, warehouse="Stores - TCP1", target_warehouse=target_warehouse, ) # qty after delivery actual_qty_at_source = get_qty_after_transaction( warehouse="Stores - TCP1") self.assertEqual(actual_qty_at_source, 475) actual_qty_at_target = get_qty_after_transaction( warehouse=target_warehouse) self.assertEqual(actual_qty_at_target, 525) # stock value diff for source warehouse for "_Test Item" stock_value_difference = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item", "warehouse": "Stores - TCP1", }, "stock_value_difference", ) # stock value diff for target warehouse stock_value_difference1 = frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Delivery Note", "voucher_no": dn.name, "item_code": "_Test Item", "warehouse": target_warehouse, }, "stock_value_difference", ) self.assertEqual(abs(stock_value_difference), stock_value_difference1) # Check gl entries gl_entries = get_gl_entries("Delivery Note", dn.name) self.assertTrue(gl_entries) stock_value_difference = abs( frappe.db.sql( """select sum(stock_value_difference) from `tabStock Ledger Entry` where voucher_type='Delivery Note' and voucher_no=%s and warehouse='Stores - TCP1'""", dn.name, )[0][0]) expected_values = { "Stock In Hand - TCP1": [0.0, stock_value_difference], target_warehouse: [stock_value_difference, 0.0], } for i, gle in enumerate(gl_entries): self.assertEqual([gle.debit, gle.credit], expected_values.get(gle.account)) # tear down frappe.db.rollback()
def test_item_cost_reposting(self): company = "_Test Company" # _Test Item for Reposting at Stores warehouse on 10-04-2020: Qty = 50, Rate = 100 create_stock_reconciliation(item_code="_Test Item for Reposting", warehouse="Stores - _TC", qty=50, rate=100, company=company, expense_account="Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC", posting_date='2020-04-10', posting_time='14:00') # _Test Item for Reposting at FG warehouse on 20-04-2020: Qty = 10, Rate = 200 create_stock_reconciliation(item_code="_Test Item for Reposting", warehouse="Finished Goods - _TC", qty=10, rate=200, company=company, expense_account="Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC", posting_date='2020-04-20', posting_time='14:00') # _Test Item for Reposting transferred from Stores to FG warehouse on 30-04-2020 se = make_stock_entry(item_code="_Test Item for Reposting", source="Stores - _TC", target="Finished Goods - _TC", company=company, qty=10, expense_account="Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC", posting_date='2020-04-30', posting_time='14:00') target_wh_sle = frappe.db.get_value('Stock Ledger Entry', { "item_code": "_Test Item for Reposting", "warehouse": "Finished Goods - _TC", "voucher_type": "Stock Entry", "voucher_no": se.name }, ["valuation_rate"], as_dict=1) self.assertEqual(target_wh_sle.get("valuation_rate"), 150) # Repack entry on 5-5-2020 repack = create_repack_entry(company=company, posting_date='2020-05-05', posting_time='14:00') finished_item_sle = frappe.db.get_value('Stock Ledger Entry', { "item_code": "_Test Finished Item for Reposting", "warehouse": "Finished Goods - _TC", "voucher_type": "Stock Entry", "voucher_no": repack.name }, ["incoming_rate", "valuation_rate"], as_dict=1) self.assertEqual(finished_item_sle.get("incoming_rate"), 540) self.assertEqual(finished_item_sle.get("valuation_rate"), 540) # Reconciliation for _Test Item for Reposting at Stores on 12-04-2020: Qty = 50, Rate = 150 sr = create_stock_reconciliation( item_code="_Test Item for Reposting", warehouse="Stores - _TC", qty=50, rate=150, company=company, expense_account="Stock Adjustment - _TC" if frappe.get_all("Stock Ledger Entry") else "Temporary Opening - _TC", posting_date='2020-04-12', posting_time='14:00') # Check valuation rate of finished goods warehouse after back-dated entry at Stores target_wh_sle = get_previous_sle({ "item_code": "_Test Item for Reposting", "warehouse": "Finished Goods - _TC", "posting_date": '2020-04-30', "posting_time": '14:00' }) self.assertEqual(target_wh_sle.get("incoming_rate"), 150) self.assertEqual(target_wh_sle.get("valuation_rate"), 175) # Check valuation rate of repacked item after back-dated entry at Stores finished_item_sle = frappe.db.get_value('Stock Ledger Entry', { "item_code": "_Test Finished Item for Reposting", "warehouse": "Finished Goods - _TC", "voucher_type": "Stock Entry", "voucher_no": repack.name }, ["incoming_rate", "valuation_rate"], as_dict=1) self.assertEqual(finished_item_sle.get("incoming_rate"), 790) self.assertEqual(finished_item_sle.get("valuation_rate"), 790) # Check updated rate in Repack entry repack.reload() self.assertEqual(repack.items[0].get("basic_rate"), 150) self.assertEqual(repack.items[1].get("basic_rate"), 750)