def test_reserved_qty_for_over_delivery_with_packing_list(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100) # set over-delivery tolerance frappe.db.set_value('Item', "_Test Product Bundle Item", 'tolerance', 50) existing_reserved_qty_item1 = get_reserved_qty("_Test Item") existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100") so = make_sales_order(item_code="_Test Product Bundle Item") self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) dn = create_dn_against_so(so.name, 15) total_projected_qty = get_total_projected_qty('_Test Item') item_doc = frappe.get_doc('Item', '_Test Item') self.assertEqual(total_projected_qty, item_doc.total_projected_qty) self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2) dn.cancel() self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20)
def test_warehouse_merging(self): set_perpetual_inventory(1) create_warehouse("Test Warehouse for Merging 1") create_warehouse("Test Warehouse for Merging 2") make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 1 - _TC", qty=1, rate=100) make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 2 - _TC", qty=1, rate=100) existing_bin_qty = ( cint(frappe.db.get_value("Bin", {"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 1 - _TC"}, "actual_qty")) + cint(frappe.db.get_value("Bin", {"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty")) ) rename_doc("Warehouse", "Test Warehouse for Merging 1 - _TC", "Test Warehouse for Merging 2 - _TC", merge=True) self.assertFalse(frappe.db.exists("Warehouse", "Test Warehouse for Merging 1 - _TC")) bin_qty = frappe.db.get_value("Bin", {"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty") self.assertEqual(bin_qty, existing_bin_qty) self.assertTrue(frappe.db.get_value("Warehouse", filters={"account": "Test Warehouse for Merging 2 - _TC"}))
def test_material_issue_gl_entry(self): set_perpetual_inventory() make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", qty=40, expense_account="Stock Adjustment - _TC") self.check_stock_ledger_entries("Stock Entry", mi.name, [["_Test Item", "_Test Warehouse - _TC", -40.0]]) stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": "_Test Warehouse - _TC"}) 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 - _TC", stock_value_diff, 0.0] ]) ) mi.cancel() self.assertFalse(frappe.db.sql("""select name from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mi.name)) self.assertFalse(frappe.db.sql("""select name from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))
def test_reserved_qty_for_partial_delivery(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) existing_reserved_qty = get_reserved_qty() so = make_sales_order() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) dn = create_dn_against_so(so.name) self.assertEqual(get_reserved_qty(), existing_reserved_qty + 5) # close so so.load_from_db() so.update_status("Closed") self.assertEqual(get_reserved_qty(), existing_reserved_qty) # unclose so so.load_from_db() so.update_status('Draft') self.assertEqual(get_reserved_qty(), existing_reserved_qty + 5) dn.cancel() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) # cancel so.load_from_db() so.cancel() self.assertEqual(get_reserved_qty(), existing_reserved_qty)
def test_reserved_qty_for_over_delivery_via_sales_invoice(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) # set over-delivery tolerance frappe.db.set_value('Item', "_Test Item", 'tolerance', 50) existing_reserved_qty = get_reserved_qty() so = make_sales_order() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) si = make_sales_invoice(so.name) si.update_stock = 1 si.get("items")[0].qty = 12 si.insert() si.submit() self.assertEqual(get_reserved_qty(), existing_reserved_qty) so.load_from_db() self.assertEqual(so.get("items")[0].delivered_qty, 12) self.assertEqual(so.per_delivered, 100) si.cancel() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) so.load_from_db() self.assertEqual(so.get("items")[0].delivered_qty, 0) self.assertEqual(so.per_delivered, 0)
def test_production_order(self): from erpnext.manufacturing.doctype.production_order.production_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"]) production_order = frappe.new_doc("Production Order") production_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 }) production_order.insert() production_order.submit() make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100) stock_entry = _make_stock_entry(production_order.name, "Manufacture", 1) rm_cost = 0 for d in stock_entry.get("items"): if d.s_warehouse: rm_cost += flt(d.amount) fg_cost = 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 + production_order.additional_operating_cost, 2))
def test_reserved_qty_for_over_delivery(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) # set over-delivery tolerance frappe.db.set_value('Item', "_Test Item", 'tolerance', 50) existing_reserved_qty = get_reserved_qty() so = make_sales_order() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) dn = create_dn_against_so(so.name, 15) self.assertEqual(get_reserved_qty(), existing_reserved_qty) dn.cancel() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
def test_reserved_qty_for_partial_delivery_with_packing_list(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100) existing_reserved_qty_item1 = get_reserved_qty("_Test Item") existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100") so = make_sales_order(item_code="_Test Product Bundle Item") self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) dn = create_dn_against_so(so.name) self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10) # close so so.load_from_db() so.update_status("Closed") self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2) total_projected_qty = get_total_projected_qty('_Test Item') item_doc = frappe.get_doc('Item', '_Test Item') self.assertEqual(total_projected_qty, item_doc.total_projected_qty) # unclose so so.load_from_db() so.update_status('Draft') self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10) dn.cancel() self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) so.load_from_db() so.cancel() self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)
def test_hash_naming(self): # disable naming series for doctype in ("GL Entry", "Stock Ledger Entry"): make_property_setter( doctype=doctype, for_doctype=True, property="autoname", value="hash", property_type="Data", fieldname=None, ) se = make_stock_entry(item_code=self.item, to_warehouse=self.warehouse, qty=10, rate=100, company=self.company) gle, sle = self.get_gle_sles(se) rename_gle_sle_docs() renamed_gle, renamed_sle = self.get_gle_sles(se) self.assertEqual(gle, renamed_gle, msg="GLEs are renamed while using hash naming") self.assertEqual(sle, renamed_sle, msg="SLEs are renamed while using hash naming") se.cancel()
def test_serial_no_cancellation(self): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry item = create_item("Stock-Reco-Serial-Item-9", is_stock_item=1) if not item.has_serial_no: item.has_serial_no = 1 item.serial_no_series = "SRS9.####" item.save() item_code = item.name warehouse = "_Test Warehouse - _TC" se1 = make_stock_entry(item_code=item_code, target=warehouse, qty=10, basic_rate=700) serial_nos = get_serial_nos(se1.items[0].serial_no) # reduce 1 item serial_nos.pop() new_serial_nos = "\n".join(serial_nos) sr = create_stock_reconciliation( item_code=item.name, warehouse=warehouse, serial_no=new_serial_nos, qty=9 ) sr.cancel() active_sr_no = frappe.get_all( "Serial No", filters={"item_code": item_code, "warehouse": warehouse, "status": "Active"} ) self.assertEqual(len(active_sr_no), 10)
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_raise_extra_transfer_materials(self): from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse warehouse = "_Test Warehouse FG 1 - _TC" if not frappe.db.exists('Warehouse', warehouse): create_warehouse("_Test Warehouse FG 1") outward_entry = make_stock_entry(item_code="_Test Item", purpose="Send to Warehouse", source="_Test Warehouse - _TC", target="_Test Warehouse 1 - _TC", qty=50, basic_rate=100) inward_entry1 = make_stock_in_entry(outward_entry.name) inward_entry1.items[0].t_warehouse = warehouse inward_entry1.items[0].qty = 25 inward_entry1.submit() inward_entry2 = make_stock_in_entry(outward_entry.name) inward_entry2.items[0].t_warehouse = warehouse inward_entry2.items[0].qty = 35 self.assertRaises(ExtraMaterialReceived, inward_entry2.submit) print(inward_entry2.name)
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_material_receipt_gl_entry(self): set_perpetual_inventory() mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": mr.get("items")[0].t_warehouse}) self.check_stock_ledger_entries("Stock Entry", mr.name, [["_Test Item", "_Test Warehouse - _TC", 50.0]]) self.check_gl_entries("Stock Entry", mr.name, sorted([ [stock_in_hand_account, 5000.0, 0.0], ["Stock Adjustment - _TC", 0.0, 5000.0] ]) ) mr.cancel() self.assertFalse(frappe.db.sql("""select * from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mr.name)) self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
def set_opening_stock(self): '''set opening stock''' if not self.is_stock_item or self.has_serial_no or self.has_batch_no: return if not self.valuation_rate and self.standard_rate: self.valuation_rate = self.standard_rate if not self.valuation_rate: frappe.throw( _("Valuation Rate is mandatory if Opening Stock entered")) from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry # default warehouse, or Stores default_warehouse = (self.default_warehouse or frappe.db.get_single_value( 'Stock Settings', 'default_warehouse') or frappe.db.get_value( 'Warehouse', {'warehouse_name': _('Stores')})) if default_warehouse: stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock, rate=self.valuation_rate) stock_entry.add_comment("Comment", _("Opening Stock"))
def test_reserved_qty_for_over_delivery(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) # set over-delivery allowance frappe.db.set_value('Item', "_Test Item", 'over_delivery_receipt_allowance', 50) existing_reserved_qty = get_reserved_qty() so = make_sales_order() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10) dn = create_dn_against_so(so.name, 15) self.assertEqual(get_reserved_qty(), existing_reserved_qty) dn.cancel() self.assertEqual(get_reserved_qty(), existing_reserved_qty + 10)
def set_opening_stock(self): '''set opening stock''' if not self.is_stock_item or self.has_serial_no or self.has_batch_no: return if not self.valuation_rate and self.standard_rate: self.valuation_rate = self.standard_rate if not self.valuation_rate: frappe.throw(_("Valuation Rate is mandatory if Opening Stock entered")) from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry # default warehouse, or Stores for default in self.item_defaults or [frappe._dict({'company': frappe.defaults.get_defaults().company})]: default_warehouse = (default.default_warehouse or frappe.db.get_single_value('Stock Settings', 'default_warehouse')) if default_warehouse: warehouse_company = frappe.db.get_value("Warehouse", default_warehouse, "company") if not default_warehouse or warehouse_company != default.company: default_warehouse = frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores'), 'company': default.company}) if default_warehouse: stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock, rate=self.valuation_rate, company=default.company) stock_entry.add_comment("Comment", _("Opening Stock"))
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 erpnext.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_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_goods_in_transit(self): from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse warehouse = "_Test Warehouse FG 1 - _TC" if not frappe.db.exists('Warehouse', warehouse): create_warehouse("_Test Warehouse FG 1") outward_entry = make_stock_entry(item_code="_Test Item", purpose="Send to Warehouse", source="_Test Warehouse - _TC", target="_Test Warehouse 1 - _TC", qty=50, basic_rate=100) inward_entry1 = make_stock_in_entry(outward_entry.name) inward_entry1.items[0].t_warehouse = warehouse inward_entry1.items[0].qty = 25 inward_entry1.submit() doc = frappe.get_doc('Stock Entry', outward_entry.name) self.assertEqual(doc.per_transferred, 50) inward_entry2 = make_stock_in_entry(outward_entry.name) inward_entry2.items[0].t_warehouse = warehouse inward_entry2.items[0].qty = 25 inward_entry2.submit() doc = frappe.get_doc('Stock Entry', outward_entry.name) self.assertEqual(doc.per_transferred, 100)
def test_material_receipt_gl_entry(self): company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company') set_perpetual_inventory(1, company) mr = make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") 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", "_Test Warehouse - _TC", 50.0]]) self.check_gl_entries( "Stock Entry", mr.name, sorted([[stock_in_hand_account, 5000.0, 0.0], ["Stock Adjustment - _TC", 0.0, 5000.0]])) mr.cancel() self.assertFalse( frappe.db.sql( """select * from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mr.name)) self.assertFalse( frappe.db.sql( """select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mr.name))
def test_reserved_qty_for_partial_delivery_with_packing_list(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100) existing_reserved_qty_item1 = get_reserved_qty("_Test Item") existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100") so = make_sales_order(item_code="_Test Product Bundle Item") self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) dn = create_dn_against_so(so.name) self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10) # close so so.load_from_db() so.update_status("Closed") self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2) total_projected_qty = get_total_projected_qty('_Test Item') item_doc = frappe.get_doc('Item', '_Test Item') self.assertEqual(total_projected_qty, item_doc.total_projected_qty) # unclose so so.load_from_db() so.update_status('Draft') self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10) dn.cancel() self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20) so.load_from_db() so.cancel() self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1) self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2)
def test_work_order(self): from erpnext.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_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 try: user = frappe.get_doc("User", "*****@*****.**") frappe.set_user(user.name) 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) frappe.set_user("Administrator") user.add_roles("Stock Manager") frappe.set_user(user.name) # 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() finally: frappe.db.set_value( "Stock Settings", None, "role_allowed_to_create_edit_back_dated_transactions", None) frappe.set_user("Administrator") user.remove_roles("Stock Manager")
def on_submit(doc, method): """Handle sample item""" if frappe.flags.in_import or frappe.flags.in_test: return if not doc.is_sample: return valid_groups = [ _('Flower Lot'), _('CO2 Hash Oil'), _('Food Grade Solvent Extract'), _('Hydrocarbon Wax'), _('Marijuana Extract for Inhalation'), _('Solid Marijuana Infused Edible'), _('Usable Marijuana') ] item_group = frappe.get_value("Item", doc.item_code, "item_group") if not _(item_group) in valid_groups: frappe.throw( _("Item is not eligible for making sample."), title="Invalid Item") # Stock update had been handled by delivery_note if doc.inspection_type == "Outgoing" and doc.delivery_note_no: return inventories = get_data(item_code=doc.item_code) source_warehouse = None actual_qty = 0 for inventory in inventories: if inventory.actual_qty > actual_qty: actual_qty = inventory.actual_qty if inventory.actual_qty >= doc.sample_size: source_warehouse = inventory.warehouse break if not source_warehouse: frappe.throw( _("Qty is not available for provided sample size. Qty remaining <strong>{0}</strong>.").format(actual_qty), title="Insufficient Stock") make_stock_entry(item_code=doc.item_code, source=source_warehouse, qty=doc.sample_size)
def test_material_issue_gl_entry(self): set_perpetual_inventory() make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100, expense_account="Stock Adjustment - _TC") mi = make_stock_entry(item_code="_Test Item", source="_Test Warehouse - _TC", qty=40, expense_account="Stock Adjustment - _TC") self.check_stock_ledger_entries( "Stock Entry", mi.name, [["_Test Item", "_Test Warehouse - _TC", -40.0]]) stock_in_hand_account = frappe.db.get_value( "Account", { "account_type": "Stock", "warehouse": "_Test Warehouse - _TC" }) 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 - _TC", stock_value_diff, 0.0]])) mi.cancel() self.assertFalse( frappe.db.sql( """select name from `tabStock Ledger Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mi.name)) self.assertFalse( frappe.db.sql( """select name from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mi.name))
def test_picklist_with_multi_uom(self): warehouse = "_Test Warehouse - _TC" item = make_item(properties={ "uoms": [dict(uom="Box", conversion_factor=24)] }).name make_stock_entry(item=item, to_warehouse=warehouse, qty=1000) so = make_sales_order(item_code=item, qty=10, rate=42, uom="Box") pl = create_pick_list(so.name) # pick half the qty for loc in pl.locations: loc.picked_qty = loc.stock_qty / 2 pl.save() pl.submit() so.reload() self.assertEqual(so.per_picked, 50)
def _make_stock_entry(self, qty, rate=None): kwargs = { "item_code": self.ITEM_CODE, "from_warehouse" if qty < 0 else "to_warehouse": self.WAREHOUSE, "rate": rate, "qty": abs(qty), } return make_stock_entry(**kwargs)
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 test_website_item_stock_when_in_stock(self): """ Check if stock details are fetched correctly for available inventory when: 1) Showing stock availability enabled: - Warehouse set - Warehouse unset 2) Showing stock availability disabled """ from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry item_code = "Test Mobile Phone" create_regular_web_item() setup_e_commerce_settings({"show_stock_availability": 1}) frappe.local.shopping_cart_settings = None # set warehouse frappe.db.set_value("Website Item", {"item_code": item_code}, "website_warehouse", "_Test Warehouse - _TC") # stock up item stock_entry = make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=2, rate=100) # check if stock details are fetched and item is in stock with warehouse set data = get_product_info_for_website(item_code, skip_quotation_creation=True) self.assertTrue(bool(data.product_info["in_stock"])) self.assertEqual(data.product_info["stock_qty"][0][0], 2) # unset warehouse frappe.db.set_value("Website Item", {"item_code": item_code}, "website_warehouse", "") # check if stock details are fetched and item not in stock without warehouse set # (even though it has stock in some warehouse) data = get_product_info_for_website(item_code, skip_quotation_creation=True) self.assertFalse(bool(data.product_info["in_stock"])) self.assertFalse(bool(data.product_info["stock_qty"])) # disable show stock availability setup_e_commerce_settings({"show_stock_availability": 0}) frappe.local.shopping_cart_settings = None data = get_product_info_for_website(item_code, skip_quotation_creation=True) # check if stock detail attributes are not fetched if stock availability is hidden self.assertIsNone(data.product_info.get("in_stock")) self.assertIsNone(data.product_info.get("stock_qty")) self.assertIsNone(data.product_info.get("show_stock_qty")) # tear down stock_entry.cancel() frappe.get_cached_doc("Website Item", { "item_code": "Test Mobile Phone" }).delete()
def test_consolidation_rounding_adjustment(self): """ Test if the rounding adjustment is calculated correctly """ frappe.db.sql("delete from `tabPOS Invoice`") try: make_stock_entry( to_warehouse="_Test Warehouse - _TC", item_code="_Test Item", rate=8000, qty=10, ) init_user_and_profile() inv = create_pos_invoice(qty=1, rate=69.5, do_not_save=True) inv.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 70 }) inv.insert() inv.submit() inv2 = create_pos_invoice(qty=1, rate=59.5, do_not_save=True) inv2.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 60 }) inv2.insert() inv2.submit() consolidate_pos_invoices() inv.load_from_db() consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice) self.assertEqual(consolidated_invoice.rounding_adjustment, 1) finally: frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`") frappe.db.sql("delete from `tabPOS Invoice`")
def new_item(item_name, item_group, strain, actual_qty, default_warehouse, plant=None): item_group = frappe.get_doc("Item Group", item_group) location = frappe.get_value("BioTrack Settings", None, "location") call_data = { "invtype": item_group.external_id, "quantity": actual_qty, "strain": strain, } if plant: call_data["source_id"] = plant data = biotrackthc_call("inventory_new", data={ "data": call_data, "location": location }) barcode = data['barcode_id'][0] item = frappe.new_doc("Item") item.update({ "item_name": item_name, "item_code": barcode, "barcode": barcode, "item_group": item_group.name, "default_warehouse": default_warehouse, "strain": strain, "plant": plant, "stock_uom": "Gram", "is_stock_item": 1, "actual_qty": actual_qty, }) item.insert() make_stock_entry(item_code=barcode, target=default_warehouse, qty=actual_qty) return item
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_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) 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_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) 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_material_consumption(self): from erpnext.manufacturing.doctype.work_order.work_order \ import make_stock_entry as _make_stock_entry bom_no = frappe.db.get_value("BOM", { "item": "_Test FG Item 2", "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 FG Item 2", "bom_no": bom_no, "qty": 4.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 Serialized Item With Series", 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) item_quantity = { '_Test Item': 10.0, '_Test Item 2': 12.0, '_Test Serialized Item With Series': 6.0 } stock_entry = frappe.get_doc( _make_stock_entry(work_order.name, "Material Consumption for Manufacture", 10)) for d in stock_entry.get('items'): if (item_quantity.get(d.item_code)): self.assertEqual(item_quantity.get(d.item_code), d.qty)
def test_material_transfer_gl_entry(self): company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company') item_code = 'Hand Sanitizer - 001' create_item(item_code=item_code, is_stock_item=1, is_purchase_item=1, opening_stock=1000, valuation_rate=10, company=company, warehouse="Stores - TCP1") mtn = make_stock_entry(item_code=item_code, source="Stores - TCP1", target="Finished Goods - TCP1", qty=45, company=company) self.check_stock_ledger_entries( "Stock Entry", mtn.name, [[item_code, "Stores - TCP1", -45.0], [item_code, "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_multi_batch_value_diff(self): """Test value difference on stock entry in case of multi-batch. | Stock entry | batch | qty | rate | value diff on SE | | --- | --- | --- | --- | --- | | receipt | A | 1 | 10 | 30 | | receipt | B | 1 | 20 | | | issue | A | -1 | 10 | -30 (to assert after submit) | | issue | B | -1 | 20 | | """ from erpnext.stock.doctype.batch.test_batch import TestBatch batch_nos = [] item_code = "_TestMultibatchFifo" TestBatch.make_batch_item(item_code) warehouse = "_Test Warehouse - _TC" receipt = make_stock_entry( item_code=item_code, qty=1, rate=10, to_warehouse=warehouse, purpose="Material Receipt", do_not_save=True, ) receipt.append( "items", frappe.copy_doc(receipt.items[0], ignore_no_copy=False).update({"basic_rate": 20}) ) receipt.save() receipt.submit() batch_nos.extend(row.batch_no for row in receipt.items) self.assertEqual(receipt.value_difference, 30) issue = make_stock_entry( item_code=item_code, qty=1, from_warehouse=warehouse, purpose="Material Issue", do_not_save=True ) issue.append("items", frappe.copy_doc(issue.items[0], ignore_no_copy=False)) for row, batch_no in zip(issue.items, batch_nos): row.batch_no = batch_no issue.save() issue.submit() issue.reload() # reload because reposting current voucher updates rate self.assertEqual(issue.value_difference, -30)
def test_fifo_dependent_consumption(self): item = make_item("_TestFifoTransferRates") source = "_Test Warehouse - _TC" target = "Stores - _TC" rates = [10 * i for i in range(1, 20)] receipt = make_stock_entry(item_code=item.name, target=source, qty=10, do_not_save=True, rate=10) for rate in rates[1:]: row = frappe.copy_doc(receipt.items[0], ignore_no_copy=False) row.basic_rate = rate receipt.append("items", row) receipt.save() receipt.submit() expected_queues = [] for idx, rate in enumerate(rates, start=1): expected_queues.append( {"stock_queue": [[10, 10 * i] for i in range(1, idx + 1)]}) self.assertSLEs(receipt, expected_queues) transfer = make_stock_entry(item_code=item.name, source=source, target=target, qty=10, do_not_save=True, rate=10) for rate in rates[1:]: row = frappe.copy_doc(transfer.items[0], ignore_no_copy=False) transfer.append("items", row) transfer.save() transfer.submit() # same exact queue should be transferred self.assertSLEs(transfer, expected_queues, sle_filters={"warehouse": target})
def test_repack_multiple_fg(self): "Test `is_finished_item` for one item repacked into two items." make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=100, basic_rate=100) repack = frappe.copy_doc(test_records[3]) repack.posting_date = nowdate() repack.posting_time = nowtime() repack.items[0].qty = 100.0 repack.items[0].transfer_qty = 100.0 repack.items[1].qty = 50.0 repack.append( "items", { "conversion_factor": 1.0, "cost_center": "_Test Cost Center - _TC", "doctype": "Stock Entry Detail", "expense_account": "Stock Adjustment - _TC", "basic_rate": 150, "item_code": "_Test Item 2", "parentfield": "items", "qty": 50.0, "stock_uom": "_Test UOM", "t_warehouse": "_Test Warehouse - _TC", "transfer_qty": 50.0, "uom": "_Test UOM", }, ) repack.set_stock_entry_type() repack.insert() self.assertEqual(repack.items[1].is_finished_item, 1) self.assertEqual(repack.items[2].is_finished_item, 1) repack.items[1].is_finished_item = 0 repack.items[2].is_finished_item = 0 # must raise error if 0 fg in repack entry self.assertRaises(FinishedGoodError, repack.validate_finished_goods) repack.delete() # teardown
def test_repack_with_additional_costs(self): set_perpetual_inventory() make_stock_entry(item_code="_Test Item", 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("additional_costs", [ { "description": "Actual Oerating Cost", "amount": 1000 }, { "description": "additional operating costs", "amount": 200 }, ]) repack.insert() repack.submit() stock_in_hand_account = frappe.db.get_value("Account", {"account_type": "Warehouse", "warehouse": 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 - _TC", 0.0, 1200.0] ]) ) set_perpetual_inventory(0)
def set_opening_stock(self): '''set opening stock''' from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry # default warehouse, or Stores default_warehouse = (frappe.db.get_single_value('Stock Settings', 'default_warehouse') or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})) if default_warehouse: stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock) stock_entry.add_comment("Comment", _("Opening Stock"))
def test_repack_no_change_in_valuation(self): set_perpetual_inventory(0) 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.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) set_perpetual_inventory(0)
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 set_opening_stock(self): '''set opening stock''' if not self.is_stock_item or self.has_serial_no or self.has_batch_no: return if not self.valuation_rate: frappe.throw(_("Valuation Rate is mandatory if Opening Stock entered")) from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry # default warehouse, or Stores default_warehouse = (frappe.db.get_single_value('Stock Settings', 'default_warehouse') or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})) if default_warehouse: stock_entry = make_stock_entry(item_code=self.name, target=default_warehouse, qty=self.opening_stock, rate=self.valuation_rate) stock_entry.add_comment("Comment", _("Opening Stock"))
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_production_order(self): bom_no = frappe.db.get_value("BOM", {"item": "_Test Variant Item", "is_default": 1, "docstatus": 1}) production_order = frappe.new_doc("Production Order") production_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" }) production_order.insert() production_order.submit() from erpnext.manufacturing.doctype.production_order.production_order import make_stock_entry stock_entry = frappe.get_doc(make_stock_entry(production_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_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 test_serial_no_based_delivery(self): frappe.set_value("Stock Settings", None, "automatically_set_serial_nos_based_on_fifo", 1) from erpnext.stock.doctype.item.test_item import make_item item = make_item("_Reserved_Serialized_Item", {"is_stock_item": 1, "maintain_stock": 1, "has_serial_no": 1, "serial_no_series": "SI.####", "valuation_rate": 500, "item_defaults": [ { "default_warehouse": "_Test Warehouse - _TC", "company": "_Test Company" }] }) frappe.db.sql("""delete from `tabSerial No` where item_code=%s""", (item.item_code)) make_item("_Test Item A", {"maintain_stock": 1, "valuation_rate": 100, "item_defaults": [ { "default_warehouse": "_Test Warehouse - _TC", "company": "_Test Company" }] }) make_item("_Test Item B", {"maintain_stock": 1, "valuation_rate": 200, "item_defaults": [ { "default_warehouse": "_Test Warehouse - _TC", "company": "_Test Company" }] }) from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom make_bom(item=item.item_code, rate=1000, raw_materials = ['_Test Item A', '_Test Item B']) so = make_sales_order(**{ "item_list": [{ "item_code": item.item_code, "ensure_delivery_based_on_produced_serial_no": 1, "qty": 1, "rate":1000 }] }) so.submit() from erpnext.manufacturing.doctype.work_order.test_work_order import \ make_wo_order_test_record work_order = make_wo_order_test_record(item=item.item_code, qty=1, do_not_save=True) work_order.fg_warehouse = "_Test Warehouse - _TC" work_order.sales_order = so.name work_order.submit() make_stock_entry(item_code=item.item_code, target="_Test Warehouse - _TC", qty=1) item_serial_no = frappe.get_doc("Serial No", {"item_code": item.item_code}) from erpnext.manufacturing.doctype.work_order.work_order import \ make_stock_entry as make_production_stock_entry se = frappe.get_doc(make_production_stock_entry(work_order.name, "Manufacture", 1)) se.submit() reserved_serial_no = se.get("items")[2].serial_no serial_no_so = frappe.get_value("Serial No", reserved_serial_no, "sales_order") self.assertEqual(serial_no_so, so.name) dn = make_delivery_note(so.name) dn.save() self.assertEqual(reserved_serial_no, dn.get("items")[0].serial_no) item_line = dn.get("items")[0] item_line.serial_no = item_serial_no.name self.assertRaises(frappe.ValidationError, dn.submit) item_line = dn.get("items")[0] item_line.serial_no = reserved_serial_no self.assertTrue(dn.submit) dn.load_from_db() dn.cancel() si = make_sales_invoice(so.name) si.update_stock = 1 si.save() self.assertEqual(si.get("items")[0].serial_no, reserved_serial_no) item_line = si.get("items")[0] item_line.serial_no = item_serial_no.name self.assertRaises(frappe.ValidationError, dn.submit) item_line = si.get("items")[0] item_line.serial_no = reserved_serial_no self.assertTrue(si.submit) si.submit() si.load_from_db() si.cancel() si = make_sales_invoice(so.name) si.update_stock = 0 si.submit() from erpnext.accounts.doctype.sales_invoice.sales_invoice import \ make_delivery_note as make_delivery_note_from_invoice dn = make_delivery_note_from_invoice(si.name) dn.save() dn.submit() self.assertEqual(dn.get("items")[0].serial_no, reserved_serial_no) dn.load_from_db() dn.cancel() si.load_from_db() si.cancel() se.load_from_db() se.cancel() self.assertFalse(frappe.db.exists("Serial No", {"sales_order": so.name}))
def sync_item(data): barcode = str(data.get("id")) remaining_quantity = flt(data.get("remaining_quantity")) name = None item_values = get_item_values(barcode, ["name", "transaction_id"]) if item_values: name, transaction_id = item_values if not (frappe.flags.force_sync or False) and transaction_id == data.get("transactionid"): frappe.db.set_value("Item", name, "bio_last_sync", now(), update_modified=False) return False # inventory type item_group = find_item_group(data) warehouse = find_warehouse(data) current_remaining_quantity = 0 # product (Item) mapping if data.get("productname"): item_name = data.get("productname") else: item_name = " ".join(filter(None, [data.get("strain"), item_group.name])) if not name: item_code = barcode item = frappe.get_doc({ "doctype": "Item", "item_code": item_code, "item_name": item_name, "bio_barcode": barcode, "is_stock_item": 1, "stock_uom": "Gram", "item_group": item_group.name, "default_warehouse": warehouse.name, }) else: item = frappe.get_doc("Item", name) current_remaining_quantity = item.bio_remaining_quantity strain = "" if data.get("strain"): strain = find_strain(data.get("strain")) # Post task will do on biotrack_after_sync hook parent_ids = data.get("parentid") plant_ids = data.get("plantid") if not item.is_lot_item and (parent_ids or plant_ids): item.set("linking_data", json.dumps({"parent_ids": parent_ids, "plant_ids": plant_ids})) item.update({ "item_name": item_name, "bio_barcode": barcode, "strain": strain, "bio_remaining_quantity": remaining_quantity, "transaction_id": data.get("transactionid"), "bio_last_sync": now(), "disabled": 1 if remaining_quantity == 0 else 0, }) item.flags.ignore_links = True item.save() # adjust_stock if item.is_stock_item: if remaining_quantity > current_remaining_quantity: make_stock_entry(item_code=item.name, target=item.default_warehouse, qty=remaining_quantity - current_remaining_quantity) # Consider to not modified down item's balance because it's hard to figure out the correct warehouse and its balance to deduct # elif remaining_quantity < current_remaining_quantity: # posting_date, posting_time = nowdate(), nowtime() # balance = get_stock_balance_for(item.name, item.default_warehouse, posting_date, posting_time) # # if balance["qty"] >= remaining_quantity: # make_stock_entry(item_code=item.name, source=item.default_warehouse, # qty=current_remaining_quantity - remaining_quantity) # Disable Usable Marijuana item does not have product name if not data.get("productname") and item_group.external_id == 28: frappe.db.set_value("Item", item.name, "disabled", 1) log_invalid_item(item) frappe.db.commit() return True
def make_stock_entry(self): item = frappe.get_doc("Item", self.get("item_code")) ste = make_stock_entry(item_code=item.name, source=self.get_source_warehouse(), qty=self.qty, do_not_save=True) ste.plant = self.name ste.submit()
def test_drop_shipping(self): from erpnext.selling.doctype.sales_order.sales_order import make_purchase_order_for_drop_shipment from erpnext.stock.doctype.item.test_item import make_item from erpnext.buying.doctype.purchase_order.purchase_order import update_status make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1, 'default_supplier': '_Test Supplier', "expense_account": "_Test Account Cost for Goods Sold - _TC", "cost_center": "_Test Cost Center - _TC" }) dn_item = make_item("_Test Regular Item", {"is_stock_item": 1, "expense_account": "_Test Account Cost for Goods Sold - _TC", "cost_center": "_Test Cost Center - _TC"}) so_items = [ { "item_code": po_item.item_code, "warehouse": "", "qty": 2, "rate": 400, "delivered_by_supplier": 1, "supplier": '_Test Supplier' }, { "item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC", "qty": 2, "rate": 300, "conversion_factor": 1.0 } ] if frappe.db.get_value("Item", "_Test Regular Item", "is_stock_item")==1: make_stock_entry(item="_Test Regular Item", target="_Test Warehouse - _TC", qty=10, rate=100) #setuo existing qty from bin bin = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"}, fields=["ordered_qty", "reserved_qty"]) existing_ordered_qty = bin[0].ordered_qty if bin else 0.0 existing_reserved_qty = bin[0].reserved_qty if bin else 0.0 bin = frappe.get_all("Bin", filters={"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, fields=["reserved_qty"]) existing_reserved_qty_for_dn_item = bin[0].reserved_qty if bin else 0.0 #create so, po and partial dn so = make_sales_order(item_list=so_items, do_not_submit=True) so.submit() po = make_purchase_order_for_drop_shipment(so.name, '_Test Supplier') po.submit() dn = create_dn_against_so(so.name, delivered_qty=1) self.assertEquals(so.customer, po.customer) self.assertEquals(po.items[0].sales_order, so.name) self.assertEquals(po.items[0].item_code, po_item.item_code) self.assertEquals(dn.items[0].item_code, dn_item.item_code) #test ordered_qty and reserved_qty bin = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"}, fields=["ordered_qty", "reserved_qty"]) ordered_qty = bin[0].ordered_qty if bin else 0.0 reserved_qty = bin[0].reserved_qty if bin else 0.0 self.assertEquals(abs(flt(ordered_qty)), existing_ordered_qty) self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty) reserved_qty = frappe.db.get_value("Bin", {"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, "reserved_qty") self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item + 1) #test po_item length self.assertEquals(len(po.items), 1) #test per_delivered status update_status("Delivered", po.name) self.assertEquals(flt(frappe.db.get_value("Sales Order", so.name, "per_delivered"), 2), 75.00) #test reserved qty after complete delivery dn = create_dn_against_so(so.name, delivered_qty=1) reserved_qty = frappe.db.get_value("Bin", {"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, "reserved_qty") self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item) #test after closing so so.db_set('status', "Closed") so.update_reserved_qty() bin = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"}, fields=["ordered_qty", "reserved_qty"]) ordered_qty = bin[0].ordered_qty if bin else 0.0 reserved_qty = bin[0].reserved_qty if bin else 0.0 self.assertEquals(abs(flt(ordered_qty)), existing_ordered_qty) self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty) reserved_qty = frappe.db.get_value("Bin", {"item_code": dn_item.item_code, "warehouse": "_Test Warehouse - _TC"}, "reserved_qty") self.assertEquals(abs(flt(reserved_qty)), existing_reserved_qty_for_dn_item)