def test_item_merging(self): create_item("Test Item for Merging 1") create_item("Test Item for Merging 2") make_stock_entry(item_code="Test Item for Merging 1", target="_Test Warehouse - _TC", qty=1, rate=100) make_stock_entry(item_code="Test Item for Merging 2", target="_Test Warehouse 1 - _TC", qty=1, rate=100) frappe.rename_doc("Item", "Test Item for Merging 1", "Test Item for Merging 2", merge=True) self.assertFalse(frappe.db.exists("Item", "Test Item for Merging 1")) self.assertTrue( frappe.db.get_value( "Bin", { "item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse - _TC" })) self.assertTrue( frappe.db.get_value( "Bin", { "item_code": "Test Item for Merging 2", "warehouse": "_Test Warehouse 1 - _TC" }))
def test_repack_no_change_in_valuation(self): company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=50, basic_rate=100) repack = frappe.copy_doc(test_records[3]) repack.posting_date = nowdate() repack.posting_time = nowtime() repack.set_stock_entry_type() repack.insert() repack.submit() self.check_stock_ledger_entries( "Stock Entry", repack.name, [["_Test Item", "_Test Warehouse - _TC", -50.0], ["_Test Item Home Desktop 100", "_Test Warehouse - _TC", 1]]) gl_entries = frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s order by account desc""", repack.name, as_dict=1) self.assertFalse(gl_entries)
def test_material_issue_gl_entry(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company=company, qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1") mi = make_stock_entry(item_code="_Test Item", source="Stores - TCP1", company=company, qty=40, expense_account="Stock Adjustment - TCP1") self.check_stock_ledger_entries( "Stock Entry", mi.name, [["_Test Item", "Stores - TCP1", -40.0]]) stock_in_hand_account = get_inventory_account(mi.company, "Stores - TCP1") stock_value_diff = abs( frappe.db.get_value("Stock Ledger Entry", { "voucher_type": "Stock Entry", "voucher_no": mi.name }, "stock_value_difference")) self.check_gl_entries( "Stock Entry", mi.name, sorted([[stock_in_hand_account, 0.0, stock_value_diff], ["Stock Adjustment - TCP1", stock_value_diff, 0.0]])) mi.cancel()
def test_warehouse_merging(self): company = "_Test Company with perpetual inventory" create_warehouse( "Test Warehouse for Merging 1", company=company, properties={"parent_warehouse": "All Warehouses - TCP1"}) create_warehouse( "Test Warehouse for Merging 2", company=company, properties={"parent_warehouse": "All Warehouses - TCP1"}) make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 1 - TCP1", qty=1, rate=100, company=company) make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 2 - TCP1", qty=1, rate=100, company=company) existing_bin_qty = (cint( frappe.db.get_value( "Bin", { "item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 1 - TCP1" }, "actual_qty")) + cint( frappe.db.get_value( "Bin", { "item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - TCP1" }, "actual_qty"))) frappe.rename_doc("Warehouse", "Test Warehouse for Merging 1 - TCP1", "Test Warehouse for Merging 2 - TCP1", merge=True) self.assertFalse( frappe.db.exists("Warehouse", "Test Warehouse for Merging 1 - TCP1")) bin_qty = frappe.db.get_value( "Bin", { "item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - TCP1" }, "actual_qty") self.assertEqual(bin_qty, existing_bin_qty) self.assertTrue( frappe.db.get_value( "Warehouse", filters={"account": "Test Warehouse for Merging 2 - TCP1"}))
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_same_serial_nos_in_repack_or_manufacture_entries(self): s1 = make_serialized_item(target_warehouse="_Test Warehouse - _TC") serial_nos = s1.get("items")[0].serial_no s2 = make_stock_entry(item_code="_Test Serialized Item With Series", source="_Test Warehouse - _TC", qty=2, basic_rate=100, purpose="Repack", serial_no=serial_nos, do_not_save=True) s2.append( "items", { "item_code": "_Test Serialized Item", "t_warehouse": "_Test Warehouse - _TC", "qty": 2, "basic_rate": 120, "expense_account": "Stock Adjustment - _TC", "conversion_factor": 1.0, "cost_center": "_Test Cost Center - _TC", "serial_no": serial_nos }) s2.submit() s2.cancel()
def test_variant_work_order(self): bom_no = frappe.db.get_value("BOM", { "item": "_Test Variant Item", "is_default": 1, "docstatus": 1 }) work_order = frappe.new_doc("Work Order") work_order.update({ "company": "_Test Company", "fg_warehouse": "_Test Warehouse 1 - _TC", "production_item": "_Test Variant Item-S", "bom_no": bom_no, "qty": 1.0, "stock_uom": "_Test UOM", "wip_warehouse": "_Test Warehouse - _TC", "skip_transfer": 1 }) work_order.insert() work_order.submit() from erpbee.manufacturing.doctype.work_order.work_order import make_stock_entry stock_entry = frappe.get_doc( make_stock_entry(work_order.name, "Manufacture", 1)) stock_entry.insert() self.assertTrue( "_Test Variant Item-S" in [d.item_code for d in stock_entry.items])
def test_material_receipt_gl_entry(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company=company, qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1") stock_in_hand_account = get_inventory_account( mr.company, mr.get("items")[0].t_warehouse) self.check_stock_ledger_entries( "Stock Entry", mr.name, [["_Test Item", "Stores - TCP1", 50.0]]) self.check_gl_entries( "Stock Entry", mr.name, sorted([[stock_in_hand_account, 5000.0, 0.0], ["Stock Adjustment - TCP1", 0.0, 5000.0]])) mr.cancel() self.assertTrue( frappe.db.sql( """select * from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mr.name)) self.assertTrue( frappe.db.sql( """select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
def test_work_order(self): from erpbee.manufacturing.doctype.work_order.work_order \ import make_stock_entry as _make_stock_entry bom_no, bom_operation_cost = frappe.db.get_value( "BOM", { "item": "_Test FG Item 2", "is_default": 1, "docstatus": 1 }, ["name", "operating_cost"]) work_order = frappe.new_doc("Work Order") work_order.update({ "company": "_Test Company", "fg_warehouse": "_Test Warehouse 1 - _TC", "production_item": "_Test FG Item 2", "bom_no": bom_no, "qty": 1.0, "stock_uom": "_Test UOM", "wip_warehouse": "_Test Warehouse - _TC", "additional_operating_cost": 1000 }) work_order.insert() work_order.submit() make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) make_stock_entry(item_code="_Test Item 2", target="_Test Warehouse - _TC", qty=50, basic_rate=20) stock_entry = _make_stock_entry(work_order.name, "Manufacture", 1) rm_cost = 0 for d in stock_entry.get("items"): if d.item_code != "_Test FG Item 2": rm_cost += flt(d.amount) fg_cost = list( filter(lambda x: x.item_code == "_Test FG Item 2", stock_entry.get("items")))[0].amount self.assertEqual( fg_cost, flt( rm_cost + bom_operation_cost + work_order.additional_operating_cost, 2))
def test_customer_provided_parts_se(self): create_item('CUST-0987', is_customer_provided_item=1, customer='_Test Customer', is_purchase_item=0) se = make_stock_entry(item_code='CUST-0987', purpose='Material Receipt', qty=4, to_warehouse="_Test Warehouse - _TC") self.assertEqual(se.get("items")[0].allow_zero_valuation_rate, 1) self.assertEqual(se.get("items")[0].amount, 0)
def test_back_dated_entry_not_allowed(self): # Back dated stock transactions are only allowed to stock managers frappe.db.set_value( "Stock Settings", None, "role_allowed_to_create_edit_back_dated_transactions", "Stock Manager") # Set User with Stock User role but not Stock Manager frappe.set_user("*****@*****.**") user = frappe.get_doc("User", "*****@*****.**") user.add_roles("Stock User") user.remove_roles("Stock Manager") stock_entry_on_today = make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100) back_dated_se_1 = make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100, posting_date=add_days(today(), -1), do_not_submit=True) # Block back-dated entry self.assertRaises(BackDatedStockTransaction, back_dated_se_1.submit) user.add_roles("Stock Manager") # Back dated entry allowed to Stock Manager back_dated_se_2 = make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100, posting_date=add_days(today(), -1)) back_dated_se_2.cancel() stock_entry_on_today.cancel() frappe.db.set_value( "Stock Settings", None, "role_allowed_to_create_edit_back_dated_transactions", None) frappe.set_user("Administrator")
def test_material_transfer_gl_entry(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') mtn = make_stock_entry(item_code="_Test Item", source="Stores - TCP1", target="Finished Goods - TCP1", qty=45, company=company) self.check_stock_ledger_entries( "Stock Entry", mtn.name, [["_Test Item", "Stores - TCP1", -45.0], ["_Test Item", "Finished Goods - TCP1", 45.0]]) source_warehouse_account = get_inventory_account( mtn.company, mtn.get("items")[0].s_warehouse) target_warehouse_account = get_inventory_account( mtn.company, mtn.get("items")[0].t_warehouse) if source_warehouse_account == target_warehouse_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, as_dict=1)) 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([ [source_warehouse_account, 0.0, stock_value_diff], [target_warehouse_account, stock_value_diff, 0.0], ])) mtn.cancel()
def test_gle_for_opening_stock_entry(self): mr = make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company="_Test Company with perpetual inventory", qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1", is_opening="Yes", do_not_save=True) self.assertRaises(OpeningEntryAccountError, mr.save) mr.items[0].expense_account = "Temporary Opening - TCP1" mr.save() mr.submit() is_opening = frappe.db.get_value("GL Entry", filters={ "voucher_type": "Stock Entry", "voucher_no": mr.name }, fieldname="is_opening") self.assertEqual(is_opening, "Yes")
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", 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", posting_date='2020-04-20', posting_time='14:00') # _Test Item for Reposting transferred from Stores to FG warehouse on 30-04-2020 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", posting_date='2020-04-30', posting_time='14:00') 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("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 = get_previous_sle({ "item_code": "_Test Finished Item for Reposting", "warehouse": "Finished Goods - _TC", "posting_date": '2020-05-05', "posting_time": '14:00' }) 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 create_stock_reconciliation(item_code="_Test Item for Reposting", warehouse="Stores - _TC", qty=50, rate=150, company=company, expense_account="Stock Adjustment - _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 = get_previous_sle({ "item_code": "_Test Finished Item for Reposting", "warehouse": "Finished Goods - _TC", "posting_date": '2020-05-05', "posting_time": '14:00' }) 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)
def test_repack_with_additional_costs(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') make_stock_entry(item_code="_Test Item", target="Stores - TCP1", company=company, qty=50, basic_rate=100, expense_account="Stock Adjustment - TCP1") repack = make_stock_entry(company=company, purpose="Repack", do_not_save=True) repack.posting_date = nowdate() repack.posting_time = nowtime() expenses_included_in_valuation = frappe.get_value( "Company", company, "expenses_included_in_valuation") items = get_multiple_items() repack.items = [] for item in items: repack.append("items", item) repack.set("additional_costs", [ { "expense_account": expenses_included_in_valuation, "description": "Actual Operating Cost", "amount": 1000 }, { "expense_account": expenses_included_in_valuation, "description": "Additional Operating Cost", "amount": 200 }, ]) repack.set_stock_entry_type() repack.insert() repack.submit() stock_in_hand_account = get_inventory_account( repack.company, repack.get("items")[1].t_warehouse) rm_stock_value_diff = abs( frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Stock Entry", "voucher_no": repack.name, "item_code": "_Test Item" }, "stock_value_difference")) fg_stock_value_diff = abs( frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Stock Entry", "voucher_no": repack.name, "item_code": "_Test Item Home Desktop 100" }, "stock_value_difference")) stock_value_diff = flt(fg_stock_value_diff - rm_stock_value_diff, 2) self.assertEqual(stock_value_diff, 1200) self.check_gl_entries( "Stock Entry", repack.name, sorted([[stock_in_hand_account, 1200, 0.0], ["Expenses Included In Valuation - TCP1", 0.0, 1200.0]]))