def test_create_two_quotations(self): from erpnext.stock.doctype.item.test_item import make_item first_item = make_item("_Test Laptop", {"is_stock_item": 1}) second_item = make_item("_Test CPU", {"is_stock_item": 1}) qo_item1 = [ { "item_code": first_item.item_code, "warehouse": "", "qty": 2, "rate": 400, "delivered_by_supplier": 1, "supplier": '_Test Supplier' } ] qo_item2 = [ { "item_code": second_item.item_code, "warehouse": "_Test Warehouse - _TC", "qty": 2, "rate": 300, "conversion_factor": 1.0 } ] first_qo = make_quotation(item_list=qo_item1, do_not_submit=True) first_qo.submit() sec_qo = make_quotation(item_list=qo_item2, do_not_submit=True) sec_qo.submit()
def test_auto_insert_price(self): from erpnext.stock.doctype.item.test_item import make_item make_item("_Test Item for Auto Price List", {"is_stock_item": 0}) frappe.db.set_value("Stock Settings", None, "auto_insert_price_list_rate_if_missing", 1) item_price = frappe.db.get_value("Item Price", {"price_list": "_Test Price List", "item_code": "_Test Item for Auto Price List"}) if item_price: frappe.delete_doc("Item Price", item_price) make_sales_order(item_code = "_Test Item for Auto Price List", selling_price_list="_Test Price List", rate=100) self.assertEquals(frappe.db.get_value("Item Price", {"price_list": "_Test Price List", "item_code": "_Test Item for Auto Price List"}, "price_list_rate"), 100) # do not update price list frappe.db.set_value("Stock Settings", None, "auto_insert_price_list_rate_if_missing", 0) item_price = frappe.db.get_value("Item Price", {"price_list": "_Test Price List", "item_code": "_Test Item for Auto Price List"}) if item_price: frappe.delete_doc("Item Price", item_price) make_sales_order(item_code = "_Test Item for Auto Price List", selling_price_list="_Test Price List", rate=100) self.assertEquals(frappe.db.get_value("Item Price", {"price_list": "_Test Price List", "item_code": "_Test Item for Auto Price List"}, "price_list_rate"), None) frappe.db.set_value("Stock Settings", None, "auto_insert_price_list_rate_if_missing", 1)
def test_work_order_with_non_stock_item(self): items = {'Finished Good Test Item For non stock': 1, '_Test FG Item': 1, '_Test FG Non Stock Item': 0} for item, is_stock_item in items.items(): make_item(item, { 'is_stock_item': is_stock_item }) if not frappe.db.get_value('Item Price', {'item_code': '_Test FG Non Stock Item'}): frappe.get_doc({ 'doctype': 'Item Price', 'item_code': '_Test FG Non Stock Item', 'price_list_rate': 1000, 'price_list': 'Standard Buying' }).insert(ignore_permissions=True) fg_item = 'Finished Good Test Item For non stock' test_stock_entry.make_stock_entry(item_code="_Test FG Item", target="_Test Warehouse - _TC", qty=1, basic_rate=100) if not frappe.db.get_value('BOM', {'item': fg_item}): make_bom(item=fg_item, rate=1000, raw_materials = ['_Test FG Item', '_Test FG Non Stock Item']) wo = make_wo_order_test_record(production_item = fg_item) se = frappe.get_doc(make_stock_entry(wo.name, "Material Transfer for Manufacture", 1)) se.insert() se.submit() ste = frappe.get_doc(make_stock_entry(wo.name, "Manufacture", 1)) ste.insert() self.assertEqual(len(ste.additional_costs), 1) self.assertEqual(ste.total_additional_costs, 1000)
def make_serialized_item(): asset_item = "Test Serialized Asset Item" if not frappe.db.exists('Item', asset_item): asset_category = frappe.get_all('Asset Category') if asset_category: asset_category = asset_category[0].name if not asset_category: doc = frappe.get_doc({ 'doctype': 'Asset Category', 'asset_category_name': 'Test Asset Category', 'depreciation_method': 'Straight Line', 'total_number_of_depreciations': 12, 'frequency_of_depreciation': 1, 'accounts': [{ 'company_name': '_Test Company', 'fixed_asset_account': '_Test Fixed Asset - _TC', 'accumulated_depreciation_account': 'Depreciation - _TC', 'depreciation_expense_account': 'Depreciation - _TC' }] }).insert() asset_category = doc.name make_item(asset_item, {'is_stock_item':0, 'stock_uom': 'Box', 'is_fixed_asset': 1, 'has_serial_no': 1, 'asset_category': asset_category, 'serial_no_series': 'ABC.###'})
def test_get_items(self): create_warehouse("_Test Warehouse Group 1", {"is_group": 1}) create_warehouse("_Test Warehouse Ledger 1", {"is_group": 0, "parent_warehouse": "_Test Warehouse Group 1 - _TC"}) make_item("_Test Stock Reco Item", {"default_warehouse": "_Test Warehouse Ledger 1 - _TC", "is_stock_item": 1, "opening_stock": 100, "valuation_rate": 100}) items = get_items("_Test Warehouse Group 1 - _TC", nowdate(), nowtime()) self.assertEqual(["_Test Stock Reco Item", "_Test Warehouse Ledger 1 - _TC", 100], [items[0]["item_code"], items[0]["warehouse"], items[0]["qty"]])
def test_request_for_raw_materials(self): from erpnext.stock.doctype.item.test_item import make_item item = make_item("_Test Finished Item", {"is_stock_item": 1, "maintain_stock": 1, "valuation_rate": 500, "item_defaults": [ { "default_warehouse": "_Test Warehouse - _TC", "company": "_Test Company" }] }) make_item("_Test Raw Item A", {"maintain_stock": 1, "valuation_rate": 100, "item_defaults": [ { "default_warehouse": "_Test Warehouse - _TC", "company": "_Test Company" }] }) make_item("_Test Raw 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 Raw Item A', '_Test Raw Item B']) so = make_sales_order(**{ "item_list": [{ "item_code": item.item_code, "qty": 1, "rate":1000 }] }) so.submit() mr_dict = frappe._dict() items = so.get_work_order_items(1) mr_dict['items'] = items mr_dict['include_exploded_items'] = 0 mr_dict['ignore_existing_ordered_qty'] = 1 make_raw_material_request(mr_dict, so.company, so.name) mr = frappe.db.sql("""select name from `tabMaterial Request` ORDER BY creation DESC LIMIT 1""", as_dict=1)[0] mr_doc = frappe.get_doc('Material Request',mr.get('name')) self.assertEqual(mr_doc.items[0].sales_order, so.name)
def test_work_order_with_non_transfer_item(self): items = {'Finished Good Transfer Item': 1, '_Test FG Item': 1, '_Test FG Item 1': 0} for item, allow_transfer in items.items(): make_item(item, { 'include_item_in_manufacturing': allow_transfer }) fg_item = 'Finished Good Transfer Item' test_stock_entry.make_stock_entry(item_code="_Test FG Item", target="_Test Warehouse - _TC", qty=1, basic_rate=100) test_stock_entry.make_stock_entry(item_code="_Test FG Item 1", target="_Test Warehouse - _TC", qty=1, basic_rate=100) if not frappe.db.get_value('BOM', {'item': fg_item}): make_bom(item=fg_item, raw_materials = ['_Test FG Item', '_Test FG Item 1']) wo = make_wo_order_test_record(production_item = fg_item) ste = frappe.get_doc(make_stock_entry(wo.name, "Material Transfer for Manufacture", 1)) ste.insert() ste.submit() self.assertEqual(len(ste.items), 1) ste1 = frappe.get_doc(make_stock_entry(wo.name, "Manufacture", 1)) self.assertEqual(len(ste1.items), 3)
def test_purchase_return_for_multi_uom(self): item_code = "_Test Purchase Return For Multi-UOM" if not frappe.db.exists('Item', item_code): item = make_item(item_code, {'stock_uom': 'Box'}) row = item.append('uoms', { 'uom': 'Unit', 'conversion_factor': 0.1 }) row.db_update() pr = make_purchase_receipt(item_code=item_code, qty=1, uom="Box", conversion_factor=1.0) return_pr = make_purchase_receipt(item_code=item_code, qty=-10, uom="Unit", stock_uom="Box", conversion_factor=0.1, is_return=1, return_against=pr.name) self.assertEquals(abs(return_pr.items[0].stock_qty), 1.0)
def test_mix_type_product_bundle(self): from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle from erpnext.stock.doctype.item.test_item import make_item make_item("_Test Mix Product Bundle", {"is_stock_item": 0}) make_item("_Test Mix Product Bundle Item 1", {"is_stock_item": 1}) make_item("_Test Mix Product Bundle Item 2", {"is_stock_item": 0}) make_product_bundle("_Test Mix Product Bundle", ["_Test Mix Product Bundle Item 1", "_Test Mix Product Bundle Item 2"]) self.assertRaises(WarehouseRequired, make_sales_order, item_code = "_Test Mix Product Bundle", warehouse="")
def test_serialized_asset_item(self): asset_item = "Test Serialized Asset Item" if not frappe.db.exists('Item', asset_item): asset_category = frappe.get_all('Asset Category') if asset_category: asset_category = asset_category[0].name if not asset_category: doc = frappe.get_doc({ 'doctype': 'Asset Category', 'asset_category_name': 'Test Asset Category', 'depreciation_method': 'Straight Line', 'total_number_of_depreciations': 12, 'frequency_of_depreciation': 1, 'accounts': [{ 'company_name': '_Test Company', 'fixed_asset_account': '_Test Fixed Asset - _TC', 'accumulated_depreciation_account': 'Depreciation - _TC', 'depreciation_expense_account': 'Depreciation - _TC' }] }).insert() asset_category = doc.name item_data = make_item(asset_item, {'is_stock_item':0, 'stock_uom': 'Box', 'is_fixed_asset': 1, 'has_serial_no': 1, 'asset_category': asset_category, 'serial_no_series': 'ABC.###'}) asset_item = item_data.item_code pr = make_purchase_receipt(item_code=asset_item, qty=3) asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name}, 'name') asset_movement = frappe.db.get_value('Asset Movement', {'reference_name': pr.name}, 'name') serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') self.assertEquals(len(serial_nos), 3) location = frappe.db.get_value('Serial No', serial_nos[0].name, 'location') self.assertEquals(location, "Test Location") pr.cancel() serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or [] self.assertEquals(len(serial_nos), 0) #frappe.db.sql("delete from `tabLocation") frappe.db.sql("delete from `tabAsset`")
def test_not_accept_duplicate_serial_no(self): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note item_code = frappe.db.get_value('Item', {'has_serial_no': 1}) if not item_code: item = make_item("Test Serial Item 1", dict(has_serial_no=1)) item_code = item.name serial_no = random_string(5) make_purchase_receipt(item_code=item_code, qty=1, serial_no=serial_no) create_delivery_note(item_code=item_code, qty=1, serial_no=serial_no) pr = make_purchase_receipt(item_code=item_code, qty=1, serial_no=serial_no, do_not_submit=True) self.assertRaises(SerialNoDuplicateError, pr.submit) se = make_stock_entry(item_code=item_code, target="_Test Warehouse - _TC", qty=1, serial_no=serial_no, basic_rate=100, do_not_submit=True) self.assertRaises(SerialNoDuplicateError, se.submit)
def test_service_type_product_bundle(self): from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle from erpnext.stock.doctype.item.test_item import make_item make_item("_Test Service Product Bundle", {"is_stock_item": 0}) make_item("_Test Service Product Bundle Item 1", {"is_stock_item": 0}) make_item("_Test Service Product Bundle Item 2", {"is_stock_item": 0}) make_product_bundle("_Test Service Product Bundle", ["_Test Service Product Bundle Item 1", "_Test Service Product Bundle Item 2"]) so = make_sales_order(item_code = "_Test Service Product Bundle", warehouse=None) self.assertTrue("_Test Service Product Bundle Item 1" in [d.item_code for d in so.packed_items]) self.assertTrue("_Test Service Product Bundle Item 2" in [d.item_code for d in so.packed_items])
def test_make_pos_invoice_in_draft(self): from erpnext.accounts.doctype.sales_invoice.pos import make_invoice from erpnext.stock.doctype.item.test_item import make_item set_perpetual_inventory() allow_negative_stock = frappe.db.get_single_value('Stock Settings', 'allow_negative_stock') if allow_negative_stock: frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 0) make_pos_profile() timestamp = cint(time.time()) item = make_item("_Test POS Item") pos = copy.deepcopy(test_records[1]) pos['items'][0]['item_code'] = item.name pos["is_pos"] = 1 pos["offline_pos_name"] = timestamp pos["update_stock"] = 1 pos["payments"] = [{'mode_of_payment': 'Bank Draft', 'account': '_Test Bank - _TC', 'amount': 300}, {'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 330}] invoice_data = [{timestamp: pos}] si = make_invoice(invoice_data).get('invoice') self.assertEquals(si[0], timestamp) sales_invoice = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp}) self.assertEquals(sales_invoice[0].docstatus, 0) timestamp = cint(time.time()) pos["offline_pos_name"] = timestamp invoice_data = [{timestamp: pos}] si1 = make_invoice(invoice_data).get('invoice') self.assertEquals(si1[0], timestamp) sales_invoice1 = frappe.get_all('Sales Invoice', fields =["*"], filters = {'offline_pos_name': timestamp}) self.assertEquals(sales_invoice1[0].docstatus, 0) if allow_negative_stock: frappe.db.set_value('Stock Settings', None, 'allow_negative_stock', 1)
def make_subcontracted_item(item_code): from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom if not frappe.db.exists('Item', item_code): make_item(item_code, { 'is_stock_item': 1, 'is_sub_contracted_item': 1 }) if not frappe.db.exists('Item', "Test Extra Item 1"): make_item("Test Extra Item 1", { 'is_stock_item': 1, }) if not frappe.db.exists('Item', "Test Extra Item 2"): make_item("Test Extra Item 2", { 'is_stock_item': 1, }) if not frappe.db.get_value('BOM', {'item': item_code}, 'name'): make_bom(item = item_code, raw_materials = ['_Test FG Item', 'Test Extra Item 1'])
def _test_reco_sle_gle(self, valuation_method): item_code = make_item(properties={ "valuation_method": valuation_method }).name se1, se2, se3 = insert_existing_sle(warehouse="Stores - TCP1", item_code=item_code) company = frappe.db.get_value("Warehouse", "Stores - TCP1", "company") # [[qty, valuation_rate, posting_date, # posting_time, expected_stock_value, bin_qty, bin_valuation]] input_data = [ [50, 1000, "2012-12-26", "12:00"], [25, 900, "2012-12-26", "12:00"], ["", 1000, "2012-12-20", "12:05"], [20, "", "2012-12-26", "12:05"], [0, "", "2012-12-31", "12:10"], ] for d in input_data: last_sle = get_previous_sle({ "item_code": item_code, "warehouse": "Stores - TCP1", "posting_date": d[2], "posting_time": d[3], }) # submit stock reconciliation stock_reco = create_stock_reconciliation( item_code=item_code, qty=d[0], rate=d[1], posting_date=d[2], posting_time=d[3], warehouse="Stores - TCP1", company=company, expense_account="Stock Adjustment - TCP1", ) # check stock value sle = frappe.db.sql( """select * from `tabStock Ledger Entry` where voucher_type='Stock Reconciliation' and voucher_no=%s""", stock_reco.name, as_dict=1, ) qty_after_transaction = flt(d[0]) if d[0] != "" else flt( last_sle.get("qty_after_transaction")) valuation_rate = flt(d[1]) if d[1] != "" else flt( last_sle.get("valuation_rate")) if qty_after_transaction == last_sle.get( "qty_after_transaction" ) and valuation_rate == last_sle.get("valuation_rate"): self.assertFalse(sle) else: self.assertEqual(flt(sle[0].qty_after_transaction, 1), flt(qty_after_transaction, 1)) self.assertEqual( flt(sle[0].stock_value, 1), flt(qty_after_transaction * valuation_rate, 1)) # no gl entries self.assertTrue( frappe.db.get_value( "Stock Ledger Entry", { "voucher_type": "Stock Reconciliation", "voucher_no": stock_reco.name })) acc_bal, stock_bal, wh_list = get_stock_and_account_balance( "Stock In Hand - TCP1", stock_reco.posting_date, stock_reco.company) self.assertEqual(flt(acc_bal, 1), flt(stock_bal, 1)) stock_reco.cancel() se3.cancel() se2.cancel() se1.cancel()
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)
def test_serialized_asset_item(self): asset_item = "Test Serialized Asset Item" if not frappe.db.exists('Item', asset_item): asset_category = frappe.get_all('Asset Category') if asset_category: asset_category = asset_category[0].name if not asset_category: doc = frappe.get_doc({ 'doctype': 'Asset Category', 'asset_category_name': 'Test Asset Category', 'depreciation_method': 'Straight Line', 'total_number_of_depreciations': 12, 'frequency_of_depreciation': 1, 'accounts': [{ 'company_name': '_Test Company', 'fixed_asset_account': '_Test Fixed Asset - _TC', 'accumulated_depreciation_account': 'Depreciation - _TC', 'depreciation_expense_account': 'Depreciation - _TC' }] }).insert() asset_category = doc.name item_data = make_item( asset_item, { 'is_stock_item': 0, 'stock_uom': 'Box', 'is_fixed_asset': 1, 'has_serial_no': 1, 'asset_category': asset_category, 'serial_no_series': 'ABC.###' }) asset_item = item_data.item_code pr = make_purchase_receipt(item_code=asset_item, qty=3) asset = frappe.db.get_value('Asset', {'purchase_receipt': pr.name}, 'name') asset_movement = frappe.db.get_value('Asset Movement', {'reference_name': pr.name}, 'name') serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') self.assertEquals(len(serial_nos), 3) location = frappe.db.get_value('Serial No', serial_nos[0].name, 'location') self.assertEquals(location, "Test Location") pr.cancel() serial_nos = frappe.get_all('Serial No', {'asset': asset}, 'name') or [] self.assertEquals(len(serial_nos), 0) #frappe.db.sql("delete from `tabLocation") frappe.db.sql("delete from `tabAsset`")
def test_subcontracted_pr_for_multi_transfer_batches(self): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.buying.doctype.purchase_order.purchase_order import make_rm_stock_entry, make_purchase_receipt from erpnext.buying.doctype.purchase_order.test_purchase_order import (update_backflush_based_on, create_purchase_order) update_backflush_based_on("Material Transferred for Subcontract") item_code = "_Test Subcontracted FG Item 3" make_item('Sub Contracted Raw Material 3', { 'is_stock_item': 1, 'is_sub_contracted_item': 1, 'has_batch_no': 1, 'create_new_batch': 1 }) create_subcontracted_item(item_code=item_code, has_batch_no=1, raw_materials=["Sub Contracted Raw Material 3"]) order_qty = 500 po = create_purchase_order(item_code=item_code, qty=order_qty, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC") ste1=make_stock_entry(target="_Test Warehouse - _TC", item_code = "Sub Contracted Raw Material 3", qty=300, basic_rate=100) ste2=make_stock_entry(target="_Test Warehouse - _TC", item_code = "Sub Contracted Raw Material 3", qty=200, basic_rate=100) transferred_batch = { ste1.items[0].batch_no : 300, ste2.items[0].batch_no : 200 } rm_items = [ {"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 3","item_name":"_Test Item", "qty":300,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos", "name": po.supplied_items[0].name}, {"item_code":item_code,"rm_item_code":"Sub Contracted Raw Material 3","item_name":"_Test Item", "qty":200,"warehouse":"_Test Warehouse - _TC", "stock_uom":"Nos", "name": po.supplied_items[0].name} ] rm_item_string = json.dumps(rm_items) se = frappe.get_doc(make_rm_stock_entry(po.name, rm_item_string)) self.assertEqual(len(se.items), 2) se.items[0].batch_no = ste1.items[0].batch_no se.items[1].batch_no = ste2.items[0].batch_no se.submit() supplied_qty = frappe.db.get_value("Purchase Order Item Supplied", {"parent": po.name, "rm_item_code": "Sub Contracted Raw Material 3"}, "supplied_qty") self.assertEqual(supplied_qty, 500.00) pr = make_purchase_receipt(po.name) pr.save() self.assertEqual(len(pr.supplied_items), 2) for row in pr.supplied_items: self.assertEqual(transferred_batch.get(row.batch_no), row.consumed_qty) update_backflush_based_on("BOM") pr.delete() se.cancel() ste2.cancel() ste1.cancel() po.cancel()
def test_drop_shipping(self): from erpnext.selling.doctype.sales_order.sales_order import make_purchase_order_for_default_supplier, \ update_status as so_update_status from erpnext.buying.doctype.purchase_order.purchase_order import update_status # make items po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1}) dn_item = make_item("_Test Regular Item", {"is_stock_item": 1}) 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=2, rate=100) #create so, po and dn so = make_sales_order(item_list=so_items, do_not_submit=True) so.submit() po = make_purchase_order_for_default_supplier(so.name, selected_items=[so_items[0]]) po.submit() dn = create_dn_against_so(so.name, delivered_qty=2) self.assertEqual(so.customer, po.customer) self.assertEqual(po.items[0].sales_order, so.name) self.assertEqual(po.items[0].item_code, po_item.item_code) self.assertEqual(dn.items[0].item_code, dn_item.item_code) #test po_item length self.assertEqual(len(po.items), 1) # test ordered_qty and reserved_qty for drop ship item bin_po_item = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"}, fields=["ordered_qty", "reserved_qty"]) ordered_qty = bin_po_item[0].ordered_qty if bin_po_item else 0.0 reserved_qty = bin_po_item[0].reserved_qty if bin_po_item else 0.0 # drop ship PO should not impact bin, test the same self.assertEqual(abs(flt(ordered_qty)), 0) self.assertEqual(abs(flt(reserved_qty)), 0) # test per_delivered status update_status("Delivered", po.name) self.assertEqual(flt(frappe.db.get_value("Sales Order", so.name, "per_delivered"), 2), 100.00) po.load_from_db() # test after closing so so.db_set('status', "Closed") so.update_reserved_qty() # test ordered_qty and reserved_qty for drop ship item after closing so bin_po_item = frappe.get_all("Bin", filters={"item_code": po_item.item_code, "warehouse": "_Test Warehouse - _TC"}, fields=["ordered_qty", "reserved_qty"]) ordered_qty = bin_po_item[0].ordered_qty if bin_po_item else 0.0 reserved_qty = bin_po_item[0].reserved_qty if bin_po_item else 0.0 self.assertEqual(abs(flt(ordered_qty)), 0) self.assertEqual(abs(flt(reserved_qty)), 0) # teardown so_update_status("Draft", so.name) dn.load_from_db() dn.cancel() po.cancel() so.load_from_db() so.cancel()
def test_subcontractor_sourced_item(self): item_code = "_Test Subcontracted FG Item 1" if not frappe.db.exists('Item', item_code): make_item( item_code, { 'is_stock_item': 1, 'is_sub_contracted_item': 1, 'stock_uom': 'Nos' }) if not frappe.db.exists('Item', "Test Extra Item 1"): make_item("Test Extra Item 1", { 'is_stock_item': 1, 'stock_uom': 'Nos' }) if not frappe.db.exists('Item', "Test Extra Item 2"): make_item("Test Extra Item 2", { 'is_stock_item': 1, 'stock_uom': 'Nos' }) if not frappe.db.exists('Item', "Test Extra Item 3"): make_item("Test Extra Item 3", { 'is_stock_item': 1, 'stock_uom': 'Nos' }) bom = frappe.get_doc({ 'doctype': 'BOM', 'is_default': 1, 'item': item_code, 'currency': 'USD', 'quantity': 1, 'company': '_Test Company' }) for item in ["Test Extra Item 1", "Test Extra Item 2"]: item_doc = frappe.get_doc('Item', item) bom.append( 'items', { 'item_code': item, 'qty': 1, 'uom': item_doc.stock_uom, 'stock_uom': item_doc.stock_uom, 'rate': item_doc.valuation_rate }) bom.append( 'items', { 'item_code': "Test Extra Item 3", 'qty': 1, 'uom': item_doc.stock_uom, 'stock_uom': item_doc.stock_uom, 'rate': 0, 'sourced_by_supplier': 1 }) bom.insert(ignore_permissions=True) bom.update_cost() bom.submit() # test that sourced_by_supplier rate is zero even after updating cost self.assertEqual(bom.items[2].rate, 0) # test in Purchase Order sourced_by_supplier is not added to Supplied Item po = create_purchase_order( item_code=item_code, qty=1, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC") bom_items = sorted( [d.item_code for d in bom.items if d.sourced_by_supplier != 1]) supplied_items = sorted([d.rm_item_code for d in po.supplied_items]) self.assertEquals(bom_items, supplied_items)
def test_internal_transfer_with_valuation_only(self): from erpnext.selling.doctype.customer.test_customer import create_internal_customer item = make_item().name warehouse = "_Test Warehouse - _TC" target = "Stores - _TC" company = "_Test Company" customer = create_internal_customer(represents_company=company) rate = 42 # Create item price and pricing rule frappe.get_doc({ "item_code": item, "price_list": "Standard Selling", "price_list_rate": 1000, "doctype": "Item Price", }).insert() frappe.get_doc({ "doctype": "Pricing Rule", "title": frappe.generate_hash(), "apply_on": "Item Code", "price_or_product_discount": "Price", "selling": 1, "company": company, "margin_type": "Percentage", "margin_rate_or_amount": 10, "apply_discount_on": "Grand Total", "items": [{ "item_code": item, }], }).insert() make_stock_entry(target=warehouse, qty=5, basic_rate=rate, item_code=item) dn = create_delivery_note( item_code=item, company=company, customer=customer, qty=5, rate=500, warehouse=warehouse, target_warehouse=target, ignore_pricing_rule=0, do_not_save=True, do_not_submit=True, ) self.assertEqual(dn.items[0].rate, 500) # haven't saved yet dn.save() self.assertEqual(dn.ignore_pricing_rule, 1) # rate should reset to incoming rate self.assertEqual(dn.items[0].rate, rate) # rate should reset again if discounts are fiddled with dn.items[0].margin_type = "Amount" dn.items[0].margin_rate_or_amount = 50 dn.save() self.assertEqual(dn.items[0].rate, rate)
def test_batch_size_for_fg_item(self): fg_item = "Test Batch Size Item For BOM 3" rm1 = "Test Batch Size Item RM 1 For BOM 3" frappe.db.set_value('Manufacturing Settings', None, 'make_serial_no_batch_from_work_order', 0) for item in [ "Test Batch Size Item For BOM 3", "Test Batch Size Item RM 1 For BOM 3" ]: item_args = { "include_item_in_manufacturing": 1, "is_stock_item": 1 } if item == fg_item: item_args['has_batch_no'] = 1 item_args['create_new_batch'] = 1 item_args['batch_number_series'] = 'TBSI3.#####' make_item(item, item_args) bom_name = frappe.db.get_value("BOM", { "item": fg_item, "is_active": 1, "with_operations": 1 }, "name") if not bom_name: bom = make_bom(item=fg_item, rate=1000, raw_materials=[rm1], do_not_save=True) bom.save() bom.submit() bom_name = bom.name work_order = make_wo_order_test_record(item=fg_item, skip_transfer=True, planned_start_date=now(), qty=1) ste1 = frappe.get_doc( make_stock_entry(work_order.name, "Manufacture", 1)) for row in ste1.get('items'): if row.is_finished_item: self.assertEqual(row.item_code, fg_item) work_order = make_wo_order_test_record(item=fg_item, skip_transfer=True, planned_start_date=now(), qty=1) frappe.db.set_value('Manufacturing Settings', None, 'make_serial_no_batch_from_work_order', 1) ste1 = frappe.get_doc( make_stock_entry(work_order.name, "Manufacture", 1)) for row in ste1.get('items'): if row.is_finished_item: self.assertEqual(row.item_code, fg_item) work_order = make_wo_order_test_record(item=fg_item, skip_transfer=True, planned_start_date=now(), qty=30, do_not_save=True) work_order.batch_size = 10 work_order.insert() work_order.submit() self.assertEqual(work_order.has_batch_no, 1) ste1 = frappe.get_doc( make_stock_entry(work_order.name, "Manufacture", 30)) for row in ste1.get('items'): if row.is_finished_item: self.assertEqual(row.item_code, fg_item) self.assertEqual(row.qty, 10) frappe.db.set_value('Manufacturing Settings', None, 'make_serial_no_batch_from_work_order', 0)
def test_auto_fetch(self): item_code = make_item( properties={ "has_serial_no": 1, "has_batch_no": 1, "create_new_batch": 1, "serial_no_series": "TEST.#######", }).name warehouse = "_Test Warehouse - _TC" in1 = make_stock_entry(item_code=item_code, to_warehouse=warehouse, qty=5) in2 = make_stock_entry(item_code=item_code, to_warehouse=warehouse, qty=5) in1.reload() in2.reload() batch1 = in1.items[0].batch_no batch2 = in2.items[0].batch_no batch_wise_serials = { batch1: get_serial_nos(in1.items[0].serial_no), batch2: get_serial_nos(in2.items[0].serial_no), } # Test FIFO first_fetch = auto_fetch_serial_number(5, item_code, warehouse) self.assertEqual(first_fetch, batch_wise_serials[batch1]) # partial FIFO partial_fetch = auto_fetch_serial_number(2, item_code, warehouse) self.assertTrue( set(partial_fetch).issubset(set(first_fetch)), msg=f"{partial_fetch} should be subset of {first_fetch}", ) # exclusion remaining = auto_fetch_serial_number( 3, item_code, warehouse, exclude_sr_nos=json.dumps(partial_fetch)) self.assertEqual(sorted(remaining + partial_fetch), first_fetch) # batchwise for batch, expected_serials in batch_wise_serials.items(): fetched_sr = auto_fetch_serial_number(5, item_code, warehouse, batch_nos=batch) self.assertEqual(fetched_sr, sorted(expected_serials)) # non existing warehouse self.assertEqual( auto_fetch_serial_number(10, item_code, warehouse="Nonexisting"), []) # multi batch all_serials = [ sr for sr_list in batch_wise_serials.values() for sr in sr_list ] fetched_serials = auto_fetch_serial_number( 10, item_code, warehouse, batch_nos=list(batch_wise_serials.keys())) self.assertEqual(sorted(all_serials), fetched_serials) # expiry date frappe.db.set_value("Batch", batch1, "expiry_date", "1980-01-01") non_expired_serials = auto_fetch_serial_number( 5, item_code, warehouse, posting_date="2021-01-01", batch_nos=batch1) self.assertEqual(non_expired_serials, [])
def create_process_loss_bom_item(item_tuple): item_code, stock_uom = item_tuple if frappe.db.exists("Item", item_code) is None: return make_item(item_code, {"stock_uom": stock_uom, "valuation_rate": 100}) else: return frappe.get_doc("Item", item_code)
def test_backdated_stock_reco_qty_reposting(self): """ Test if a backdated stock reco recalculates future qty until next reco. ------------------------------------------- Var | Doc | Qty | Balance ------------------------------------------- PR5 | PR | 10 | 10 (posting date: today-4) [backdated] SR5 | Reco | 0 | 8 (posting date: today-4) [backdated] PR1 | PR | 10 | 18 (posting date: today-3) PR2 | PR | 1 | 19 (posting date: today-2) SR4 | Reco | 0 | 6 (posting date: today-1) [backdated] PR3 | PR | 1 | 7 (posting date: today) # can't post future PR """ item_code = make_item().name warehouse = "_Test Warehouse - _TC" frappe.flags.dont_execute_stock_reposts = True def assertBalance(doc, qty_after_transaction): sle_balance = frappe.db.get_value("Stock Ledger Entry", { "voucher_no": doc.name, "is_cancelled": 0 }, "qty_after_transaction") self.assertEqual(sle_balance, qty_after_transaction) pr1 = make_purchase_receipt(item_code=item_code, warehouse=warehouse, qty=10, rate=100, posting_date=add_days(nowdate(), -3)) pr2 = make_purchase_receipt(item_code=item_code, warehouse=warehouse, qty=1, rate=100, posting_date=add_days(nowdate(), -2)) pr3 = make_purchase_receipt(item_code=item_code, warehouse=warehouse, qty=1, rate=100, posting_date=nowdate()) assertBalance(pr1, 10) assertBalance(pr3, 12) # post backdated stock reco in between sr4 = create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=6, rate=100, posting_date=add_days(nowdate(), -1)) assertBalance(pr3, 7) # post backdated stock reco at the start sr5 = create_stock_reconciliation(item_code=item_code, warehouse=warehouse, qty=8, rate=100, posting_date=add_days(nowdate(), -4)) assertBalance(pr1, 18) assertBalance(pr2, 19) assertBalance(sr4, 6) # check if future stock reco is unaffected # Make a backdated receipt and check only entries till first SR are affected pr5 = make_purchase_receipt(item_code=item_code, warehouse=warehouse, qty=10, rate=100, posting_date=add_days(nowdate(), -5)) assertBalance(pr5, 10) # check if future stock reco is unaffected assertBalance(sr4, 6) assertBalance(sr5, 8) # cancel backdated stock reco and check future impact sr5.cancel() assertBalance(pr1, 10) assertBalance(pr2, 11) assertBalance(sr4, 6) # check if future stock reco is unaffected
def test_packed_items_indices_are_reset_when_product_bundle_is_deleted_from_items_table(self): from erpnext.selling.doctype.product_bundle.test_product_bundle import make_product_bundle from erpnext.stock.doctype.item.test_item import make_item make_item("_Test Product Bundle 1", {"is_stock_item": 0}) make_item("_Test Product Bundle 2", {"is_stock_item": 0}) make_item("_Test Product Bundle 3", {"is_stock_item": 0}) make_item("_Test Bundle Item 1", {"is_stock_item": 1}) make_item("_Test Bundle Item 2", {"is_stock_item": 1}) make_item("_Test Bundle Item 3", {"is_stock_item": 1}) make_product_bundle("_Test Product Bundle 1", ["_Test Bundle Item 1", "_Test Bundle Item 2"]) make_product_bundle("_Test Product Bundle 2", ["_Test Bundle Item 2", "_Test Bundle Item 3"]) make_product_bundle("_Test Product Bundle 3", ["_Test Bundle Item 3", "_Test Bundle Item 1"]) item_list = [ { "item_code": "_Test Product Bundle 1", "warehouse": "", "qty": 1, "rate": 400, "delivered_by_supplier": 1, "supplier": "_Test Supplier", }, { "item_code": "_Test Product Bundle 2", "warehouse": "", "qty": 1, "rate": 400, "delivered_by_supplier": 1, "supplier": "_Test Supplier", }, { "item_code": "_Test Product Bundle 3", "warehouse": "", "qty": 1, "rate": 400, "delivered_by_supplier": 1, "supplier": "_Test Supplier", }, ] quotation = make_quotation(item_list=item_list, do_not_submit=1) del quotation.items[1] quotation.save() for id, item in enumerate(quotation.packed_items): expected_index = id + 1 self.assertEqual(item.idx, expected_index)
def test_gstr_3b_report(self): month_number_mapping = { 1: "January", 2: "February", 3: "March", 4: "April", 5: "May", 6: "June", 7: "July", 8: "August", 9: "September", 10: "October", 11: "November", 12: "December" } frappe.set_user("Administrator") frappe.db.sql( "delete from `tabSales Invoice` where company='_Test Company GST'") frappe.db.sql( "delete from `tabPurchase Invoice` where company='_Test Company GST'" ) frappe.db.sql( "delete from `tabGSTR 3B Report` where company='_Test Company GST'" ) make_company() make_item("Milk", properties={ "is_nil_exempt": 1, "standard_rate": 0.000000 }) set_account_heads() make_customers() make_suppliers() make_sales_invoice() create_purchase_invoices() if frappe.db.exists("GSTR 3B Report", "GSTR3B-March-2019-_Test Address-Billing"): report = frappe.get_doc("GSTR 3B Report", "GSTR3B-March-2019-_Test Address-Billing") report.save() else: report = frappe.get_doc({ "doctype": "GSTR 3B Report", "company": "_Test Company GST", "company_address": "_Test Address-Billing", "year": getdate().year, "month": month_number_mapping.get(getdate().month) }).insert() output = json.loads(report.json_output) self.assertEqual(output["sup_details"]["osup_det"]["iamt"], 36), self.assertEqual(output["sup_details"]["osup_zero"]["iamt"], 18), self.assertEqual(output["inter_sup"]["unreg_details"][0]["iamt"], 18), self.assertEqual(output["sup_details"]["osup_nil_exmp"]["txval"], 100), self.assertEqual(output["inward_sup"]["isup_details"][0]["inter"], 250) self.assertEqual(output["itc_elg"]["itc_avl"][4]["iamt"], 45)
def setUp(self) -> None: self.item = make_item().name self.warehouse = "Stores - TCP1" self.company = "_Test Company with perpetual inventory"
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 test_putaway_rule_on_stock_entry_material_transfer_batch_serial_item( self): """Test if batch and serial items are split correctly.""" if not frappe.db.exists("Item", "Water Bottle"): make_item( "Water Bottle", { "is_stock_item": 1, "has_batch_no": 1, "create_new_batch": 1, "has_serial_no": 1, "serial_no_series": "BOTTL-.####", "stock_uom": "Nos", }, ) rule_1 = create_putaway_rule(item_code="Water Bottle", warehouse=self.warehouse_1, capacity=3, uom="Nos") rule_2 = create_putaway_rule(item_code="Water Bottle", warehouse=self.warehouse_2, capacity=2, uom="Nos") make_new_batch(batch_id="BOTTL-BATCH-1", item_code="Water Bottle") pr = make_purchase_receipt(item_code="Water Bottle", qty=5, do_not_submit=1) pr.items[0].batch_no = "BOTTL-BATCH-1" pr.save() pr.submit() serial_nos = frappe.get_list("Serial No", filters={ "purchase_document_no": pr.name, "status": "Active" }) serial_nos = [d.name for d in serial_nos] stock_entry = make_stock_entry( item_code="Water Bottle", source="_Test Warehouse - _TC", qty=5, target="Finished Goods - _TC", purpose="Material Transfer", apply_putaway_rule=1, do_not_save=1, ) stock_entry.items[0].batch_no = "BOTTL-BATCH-1" stock_entry.items[0].serial_no = "\n".join(serial_nos) stock_entry.save() self.assertEqual(stock_entry.items[0].t_warehouse, self.warehouse_1) self.assertEqual(stock_entry.items[0].qty, 3) self.assertEqual(stock_entry.items[0].putaway_rule, rule_1.name) self.assertEqual(stock_entry.items[0].serial_no, "\n".join(serial_nos[:3])) self.assertEqual(stock_entry.items[0].batch_no, "BOTTL-BATCH-1") self.assertEqual(stock_entry.items[1].t_warehouse, self.warehouse_2) self.assertEqual(stock_entry.items[1].qty, 2) self.assertEqual(stock_entry.items[1].putaway_rule, rule_2.name) self.assertEqual(stock_entry.items[1].serial_no, "\n".join(serial_nos[3:])) self.assertEqual(stock_entry.items[1].batch_no, "BOTTL-BATCH-1") self.assertUnchangedItemsOnResave(stock_entry) stock_entry.delete() pr.cancel() rule_1.delete() rule_2.delete()
def test_backflushed_based_on_for_multiple_batches(self): item_code = "_Test Subcontracted FG Item 2" make_item('Sub Contracted Raw Material 2', { 'is_stock_item': 1, 'is_sub_contracted_item': 1 }) make_subcontracted_item( item_code=item_code, has_batch_no=1, create_new_batch=1, raw_materials=["Sub Contracted Raw Material 2"]) update_backflush_based_on("Material Transferred for Subcontract") order_qty = 500 po = create_purchase_order( item_code=item_code, qty=order_qty, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC") make_stock_entry(target="_Test Warehouse - _TC", item_code="Sub Contracted Raw Material 2", qty=552, basic_rate=100) rm_items = [{ "item_code": item_code, "rm_item_code": "Sub Contracted Raw Material 2", "item_name": "_Test Item", "qty": 552, "warehouse": "_Test Warehouse - _TC", "stock_uom": "Nos" }] rm_item_string = json.dumps(rm_items) se = frappe.get_doc( make_subcontract_transfer_entry(po.name, rm_item_string)) se.submit() for batch in ["ABCD1", "ABCD2", "ABCD3", "ABCD4"]: make_new_batch(batch_id=batch, item_code=item_code) pr = make_purchase_receipt(po.name) # partial receipt pr.get('items')[0].qty = 30 pr.get('items')[0].batch_no = "ABCD1" purchase_order = po.name purchase_order_item = po.items[0].name for batch_no, qty in {"ABCD2": 60, "ABCD3": 70, "ABCD4": 40}.items(): pr.append( "items", { "item_code": pr.get('items')[0].item_code, "item_name": pr.get('items')[0].item_name, "uom": pr.get('items')[0].uom, "stock_uom": pr.get('items')[0].stock_uom, "warehouse": pr.get('items')[0].warehouse, "conversion_factor": pr.get('items')[0].conversion_factor, "cost_center": pr.get('items')[0].cost_center, "rate": pr.get('items')[0].rate, "qty": qty, "batch_no": batch_no, "purchase_order": purchase_order, "purchase_order_item": purchase_order_item }) pr.submit() pr1 = make_purchase_receipt(po.name) pr1.get('items')[0].qty = 300 pr1.get('items')[0].batch_no = "ABCD1" pr1.save() pr_key = ("Sub Contracted Raw Material 2", po.name) consumed_qty = get_backflushed_subcontracted_raw_materials( [po.name]).get(pr_key) self.assertTrue(pr1.supplied_items[0].consumed_qty > 0) self.assertTrue(pr1.supplied_items[0].consumed_qty, flt(552.0) - flt(consumed_qty)) update_backflush_based_on("BOM")
def create_test_records(): from erpnext.stock.doctype.item.test_item import make_item subA = make_item( "_Test PPT Item Sub A", { "item_code": "_Test PPT Item Sub A", "item_name": "_Test PPT Item Sub A", "description": "A manufactured _Test PPT Item Sub Assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) subB = make_item( "_Test PPT Item Sub B", { "item_code": "_Test PPT Item Sub B", "item_name": "_Test PPT Item Sub B", "description": "A manufactured _Test PPT Item Sub Assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) subC = make_item( "_Test PPT Item Sub C", { "item_code": "_Test PPT Item Sub C", "item_name": "_Test PPT Item Sub C", "description": "A manufactured _Test PPT Item Sub Assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) sCA = make_item( "_Test PPT Item SC A", { "item_code": "_Test PPT Item SC A", "item_name": "_Test PPT Item SC A", "description": "A subcontracted part with raw materials", "default_material_request_type": "Purchase", "is_sub_contracted_item": 1, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) subA = make_item( "_Test PPT Item Sub A", { "item_code": "_Test PPT Item Sub A", "item_name": "_Test PPT Item Sub A", "description": "A manufactured _Test PPT Item Sub Assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) sCB = make_item( "_Test PPT Item SC B", { "item_code": "_Test PPT Item SC B", "item_name": "_Test PPT Item SC B", "description": "A subcontracted part with raw materials", "default_material_request_type": "Purchase", "is_sub_contracted_item": 1, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) rawA = make_item( "_Test PPT Item Raw A", { "item_code": "_Test PPT Item Raw A", "item_name": "_Test PPT Item Raw A", "description": "A raw material", "default_material_request_type": "Purchase", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) rawB = make_item( "_Test PPT Item Raw B", { "item_code": "_Test PPT Item Raw B", "item_name": "_Test PPT Item Raw B", "description": "A raw material", "default_material_request_type": "Purchase", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) rawC = make_item( "_Test PPT Item Raw C", { "item_code": "_Test PPT Item Raw C", "item_name": "_Test PPT Item Raw C", "description": "A raw material", "default_material_request_type": "Purchase", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) rawD = make_item( "_Test PPT Item Raw D", { "item_code": "_Test PPT Item Raw D", "item_name": "_Test PPT Item Raw D", "description": "A raw material", "default_material_request_type": "Purchase", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) master = make_item( "_Test PPT Item Master", { "item_code": "_Test PPT Item Master", "item_name": "_Test PPT Item Master", "description": "The final assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC" }) bom_subB = make_bom( "BOM-_Test PPT Item Sub B-001", { "quantity": 1.0, "item": "_Test PPT Item Sub B", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0 }, [{ "item_code": "_Test PPT Item Raw B", "doctype": "BOM Item", "qty": 1, "rate": 100, "amount": 100, "stock_uom": "_Test UOM" }, { "item_code": "_Test PPT Item Raw C", "doctype": "BOM Item", "qty": 4, "rate": 100, "amount": 400, "stock_uom": "_Test UOM" }]) bom_subC = make_bom( "BOM-_Test PPT Item Sub C-001", { "quantity": 1, "item": "_Test PPT Item Sub C", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0 }, [{ "item_code": "_Test PPT Item Raw A", "item_name": "_Test PPT Item Raw A", "doctype": "BOM Item", "qty": 6, "rate": 100, "amount": 600 }, { "item_code": "_Test PPT Item Sub B", "item_name": "_Test PPT Item Sub B", "bom_no": "BOM-_Test PPT Item Sub B-001", "doctype": "BOM Item", "qty": 2, "rate": 100, "amount": 200 }]) bom_sCA = make_bom( "BOM-_Test PPT Item SC A-001", { "quantity": 1, "item": "_Test PPT Item SC A", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0 }, [{ "item_code": "_Test PPT Item Raw D", "item_name": "_Test PPT Item Raw D", "doctype": "BOM Item", "qty": 1, "rate": 100, "amount": 100 }]) bom_sCB = make_bom( "BOM-_Test PPT Item SC B-001", { "quantity": 1, "item": "_Test PPT Item SC B", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0 }, [{ "item_code": "_Test PPT Item Raw B", "item_name": "_Test PPT Item Raw B", "doctype": "BOM Item", "qty": 1, "rate": 100, "amount": 100 }, { "item_code": "_Test PPT Item Raw C", "item_name": "_Test PPT Item Raw C", "doctype": "BOM Item", "qty": 4, "rate": 100, "amount": 400 }]) bom_subA = make_bom( "BOM-_Test PPT Item Sub A-001", { "quantity": 1, "item": "_Test PPT Item Sub A", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0 }, [{ "item_code": "_Test PPT Item Sub C", "item_name": "_Test PPT Item Sub C", "bom_no": "BOM-_Test PPT Item Sub C-001", "doctype": "BOM Item", "qty": 1, "rate": 100, "amount": 100 }, { "item_code": "_Test PPT Item SC B", "item_name": "_Test PPT Item SC B", "bom_no": "BOM-_Test PPT Item SC B-001", "doctype": "BOM Item", "qty": 2, "rate": 100, "amount": 200 }]) bom_master = make_bom( "BOM-_Test PPT Item Master-001", { "quantity": 1, "item": "_Test PPT Item Master", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0 }, [{ "item_code": "_Test PPT Item Sub A", "item_name": "_Test PPT Item Sub A", "bom_no": "BOM-_Test PPT Item Sub A-001", "doctype": "BOM Item", "qty": 2, "rate": 100, "amount": 200 }, { "item_code": "_Test PPT Item Sub B", "item_name": "_Test PPT Item Sub B", "bom_no": "BOM-_Test PPT Item Sub B-001", "doctype": "BOM Item", "qty": 1, "rate": 100, "amount": 100 }, { "item_code": "_Test PPT Item Raw A", "item_name": "_Test PPT Item Raw A", "doctype": "BOM Item", "qty": 2, "rate": 100, "amount": 200 }, { "item_code": "_Test PPT Item SC A", "item_name": "_Test PPT Item SC A", "bom_no": "BOM-_Test PPT Item SC A-001", "doctype": "BOM Item", "qty": 1, "rate": 100, "amount": 100 }])
def test_update_child_with_tax_template(self): """ Test Action: Create a PO with one item having its tax account head already in the PO. Add the same item + new item with tax template via Update Items. Expected result: First Item's tax row is updated. New tax row is added for second Item. """ if not frappe.db.exists("Item", "Test Item with Tax"): make_item("Test Item with Tax", { 'is_stock_item': 1, }) if not frappe.db.exists("Item Tax Template", {"title": 'Test Update Items Template'}): frappe.get_doc({ 'doctype': 'Item Tax Template', 'title': 'Test Update Items Template', 'company': '_Test Company', 'taxes': [{ 'tax_type': "_Test Account Service Tax - _TC", 'tax_rate': 10, }] }).insert() new_item_with_tax = frappe.get_doc("Item", "Test Item with Tax") new_item_with_tax.append( "taxes", { "item_tax_template": "Test Update Items Template - _TC", "valid_from": nowdate() }) new_item_with_tax.save() tax_template = "_Test Account Excise Duty @ 10 - _TC" item = "_Test Item Home Desktop 100" if not frappe.db.exists("Item Tax", { "parent": item, "item_tax_template": tax_template }): item_doc = frappe.get_doc("Item", item) item_doc.append("taxes", { "item_tax_template": tax_template, "valid_from": nowdate() }) item_doc.save() else: # update valid from frappe.db.sql( """UPDATE `tabItem Tax` set valid_from = CURDATE() where parent = %(item)s and item_tax_template = %(tax)s""", { "item": item, "tax": tax_template }) po = create_purchase_order(item_code=item, qty=1, do_not_save=1) po.append( "taxes", { "account_head": "_Test Account Excise Duty - _TC", "charge_type": "On Net Total", "cost_center": "_Test Cost Center - _TC", "description": "Excise Duty", "doctype": "Purchase Taxes and Charges", "rate": 10 }) po.insert() po.submit() self.assertEqual(po.taxes[0].tax_amount, 50) self.assertEqual(po.taxes[0].total, 550) items = json.dumps([ { 'item_code': item, 'rate': 500, 'qty': 1, 'docname': po.items[0].name }, { 'item_code': item, 'rate': 100, 'qty': 1 }, # added item whose tax account head already exists in PO { 'item_code': new_item_with_tax.name, 'rate': 100, 'qty': 1 } # added item whose tax account head is missing in PO ]) update_child_qty_rate('Purchase Order', items, po.name) po.reload() self.assertEqual(po.taxes[0].tax_amount, 70) self.assertEqual(po.taxes[0].total, 770) self.assertEqual(po.taxes[1].account_head, "_Test Account Service Tax - _TC") self.assertEqual(po.taxes[1].tax_amount, 70) self.assertEqual(po.taxes[1].total, 840) # teardown frappe.db.sql( """UPDATE `tabItem Tax` set valid_from = NULL where parent = %(item)s and item_tax_template = %(tax)s""", { "item": item, "tax": tax_template }) po.cancel() po.delete() new_item_with_tax.delete() frappe.get_doc("Item Tax Template", "Test Update Items Template - _TC").delete()
def test_subcontractor_sourced_item(self): item_code = "_Test Subcontracted FG Item 1" set_backflush_based_on("Material Transferred for Subcontract") if not frappe.db.exists("Item", item_code): make_item( item_code, { "is_stock_item": 1, "is_sub_contracted_item": 1, "stock_uom": "Nos" }) if not frappe.db.exists("Item", "Test Extra Item 1"): make_item("Test Extra Item 1", { "is_stock_item": 1, "stock_uom": "Nos" }) if not frappe.db.exists("Item", "Test Extra Item 2"): make_item("Test Extra Item 2", { "is_stock_item": 1, "stock_uom": "Nos" }) if not frappe.db.exists("Item", "Test Extra Item 3"): make_item("Test Extra Item 3", { "is_stock_item": 1, "stock_uom": "Nos" }) bom = frappe.get_doc({ "doctype": "BOM", "is_default": 1, "item": item_code, "currency": "USD", "quantity": 1, "company": "_Test Company", }) for item in ["Test Extra Item 1", "Test Extra Item 2"]: item_doc = frappe.get_doc("Item", item) bom.append( "items", { "item_code": item, "qty": 1, "uom": item_doc.stock_uom, "stock_uom": item_doc.stock_uom, "rate": item_doc.valuation_rate, }, ) bom.append( "items", { "item_code": "Test Extra Item 3", "qty": 1, "uom": item_doc.stock_uom, "stock_uom": item_doc.stock_uom, "rate": 0, "sourced_by_supplier": 1, }, ) bom.insert(ignore_permissions=True) bom.update_cost() bom.submit() # test that sourced_by_supplier rate is zero even after updating cost self.assertEqual(bom.items[2].rate, 0) # test in Purchase Order sourced_by_supplier is not added to Supplied Item po = create_purchase_order( item_code=item_code, qty=1, is_subcontracted=1, supplier_warehouse="_Test Warehouse 1 - _TC") bom_items = sorted( [d.item_code for d in bom.items if d.sourced_by_supplier != 1]) supplied_items = sorted([d.rm_item_code for d in po.supplied_items]) self.assertEqual(bom_items, supplied_items)
def setUpClass(cls): setup_company() setup_customers() setup_gst_settings() make_item("Golf Car", properties={"gst_hsn_code": "999900"})
def test_dependent_gl_entry_reposting(self): def _get_stock_credit(doc): return frappe.db.get_value( "GL Entry", { "voucher_no": doc.name, "voucher_type": doc.doctype, "is_cancelled": 0, "account": "Stock In Hand - TCP1", }, "sum(credit)", ) def _day(days): return add_to_date(date=today(), days=days) item = make_item().name A = "Stores - TCP1" B = "Work In Progress - TCP1" C = "Finished Goods - TCP1" make_stock_entry(item_code=item, to_warehouse=A, qty=5, rate=10, posting_date=_day(0)) make_stock_entry(item_code=item, from_warehouse=A, to_warehouse=B, qty=5, posting_date=_day(1)) depdendent_consumption = make_stock_entry(item_code=item, from_warehouse=B, qty=5, posting_date=_day(2)) self.assertEqual(50, _get_stock_credit(depdendent_consumption)) # backdated receipt - should trigger GL repost of all previous stock entries bd_receipt = make_stock_entry(item_code=item, to_warehouse=A, qty=5, rate=20, posting_date=_day(-1)) self.assertEqual(100, _get_stock_credit(depdendent_consumption)) # cancelling receipt should reset it back bd_receipt.cancel() self.assertEqual(50, _get_stock_credit(depdendent_consumption)) bd_receipt2 = make_stock_entry(item_code=item, to_warehouse=A, qty=2, rate=20, posting_date=_day(-2)) # total as per FIFO -> 2 * 20 + 3 * 10 = 70 self.assertEqual(70, _get_stock_credit(depdendent_consumption)) # transfer WIP material to final destination and consume it all depdendent_consumption.cancel() make_stock_entry(item_code=item, from_warehouse=B, to_warehouse=C, qty=5, posting_date=_day(3)) final_consumption = make_stock_entry(item_code=item, from_warehouse=C, qty=5, posting_date=_day(4)) # exact amount gets consumed self.assertEqual(70, _get_stock_credit(final_consumption)) # cancel original backdated receipt - should repost A -> B -> C bd_receipt2.cancel() # original amount self.assertEqual(50, _get_stock_credit(final_consumption))
def make_batch_item(cls, item_name): from erpnext.stock.doctype.item.test_item import make_item if not frappe.db.exists(item_name): return make_item( item_name, dict(has_batch_no=1, create_new_batch=1, is_stock_item=1))
def create_test_records(): from erpnext.stock.doctype.item.test_item import make_item subA = make_item("_Test PPT Item Sub A",{ "item_code": "_Test PPT Item Sub A", "item_name": "_Test PPT Item Sub A", "description": "A manufactured _Test PPT Item Sub Assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) subB = make_item("_Test PPT Item Sub B",{ "item_code": "_Test PPT Item Sub B", "item_name": "_Test PPT Item Sub B", "description": "A manufactured _Test PPT Item Sub Assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) subC = make_item("_Test PPT Item Sub C",{ "item_code": "_Test PPT Item Sub C", "item_name": "_Test PPT Item Sub C", "description": "A manufactured _Test PPT Item Sub Assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) sCA = make_item("_Test PPT Item SC A",{ "item_code": "_Test PPT Item SC A", "item_name": "_Test PPT Item SC A", "description": "A subcontracted part with raw materials", "default_material_request_type": "Purchase", "is_sub_contracted_item": 1, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) subA = make_item("_Test PPT Item Sub A",{ "item_code": "_Test PPT Item Sub A", "item_name": "_Test PPT Item Sub A", "description": "A manufactured _Test PPT Item Sub Assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) sCB = make_item("_Test PPT Item SC B",{ "item_code": "_Test PPT Item SC B", "item_name": "_Test PPT Item SC B", "description": "A subcontracted part with raw materials", "default_material_request_type": "Purchase", "is_sub_contracted_item": 1, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) rawA = make_item("_Test PPT Item Raw A",{ "item_code": "_Test PPT Item Raw A", "item_name": "_Test PPT Item Raw A", "description": "A raw material", "default_material_request_type": "Purchase", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) rawB = make_item("_Test PPT Item Raw B",{ "item_code": "_Test PPT Item Raw B", "item_name": "_Test PPT Item Raw B", "description": "A raw material", "default_material_request_type": "Purchase", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) rawC = make_item("_Test PPT Item Raw C",{ "item_code": "_Test PPT Item Raw C", "item_name": "_Test PPT Item Raw C", "description": "A raw material", "default_material_request_type": "Purchase", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) rawD = make_item("_Test PPT Item Raw D",{ "item_code": "_Test PPT Item Raw D", "item_name": "_Test PPT Item Raw D", "description": "A raw material", "default_material_request_type": "Purchase", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) master = make_item("_Test PPT Item Master",{ "item_code": "_Test PPT Item Master", "item_name": "_Test PPT Item Master", "description": "The final assembly", "default_material_request_type": "Manufacture", "is_sub_contracted_item": 0, "is_stock_item": 1, "stock_uom": "_Test UOM", "item_group": "_Test Item Group", "default_warehouse": "_Test Warehouse - _TC"}) bom_subB = make_bom("BOM-_Test PPT Item Sub B-001",{"quantity":1.0, "item": "_Test PPT Item Sub B", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0}, [{"item_code": "_Test PPT Item Raw B", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100, "stock_uom": "_Test UOM"}, {"item_code": "_Test PPT Item Raw C", "doctype":"BOM Item", "stock_qty":4, "rate":100, "amount": 400,"stock_uom": "_Test UOM"}]) bom_subC = make_bom("BOM-_Test PPT Item Sub C-001",{"quantity":1, "item": "_Test PPT Item Sub C", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A", "doctype":"BOM Item", "stock_qty":6, "rate":100, "amount": 600}, {"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B", "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}]) bom_sCA = make_bom("BOM-_Test PPT Item SC A-001",{"quantity":1, "item": "_Test PPT Item SC A", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw D","item_name": "_Test PPT Item Raw D", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}]) bom_sCB = make_bom("BOM-_Test PPT Item SC B-001",{"quantity":1, "item": "_Test PPT Item SC B", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Raw B","item_name": "_Test PPT Item Raw B", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item Raw C","item_name": "_Test PPT Item Raw C", "doctype":"BOM Item", "stock_qty":4, "rate":100, "amount": 400}]) bom_subA = make_bom("BOM-_Test PPT Item Sub A-001",{"quantity":1, "item": "_Test PPT Item Sub A", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Sub C","item_name": "_Test PPT Item Sub C", "bom_no":"BOM-_Test PPT Item Sub C-001", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item SC B","item_name": "_Test PPT Item SC B", "bom_no":"BOM-_Test PPT Item SC B-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}]) bom_master = make_bom("BOM-_Test PPT Item Master-001",{"quantity":1, "item": "_Test PPT Item Master", "is_active": 1, "is_default": 1, "docstatus": 1, "with_operations": 0}, [ {"item_code": "_Test PPT Item Sub A","item_name": "_Test PPT Item Sub A", "bom_no":"BOM-_Test PPT Item Sub A-001", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}, {"item_code": "_Test PPT Item Sub B","item_name": "_Test PPT Item Sub B", "bom_no":"BOM-_Test PPT Item Sub B-001", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100}, {"item_code": "_Test PPT Item Raw A","item_name": "_Test PPT Item Raw A", "doctype":"BOM Item", "stock_qty":2, "rate":100, "amount": 200}, {"item_code": "_Test PPT Item SC A","item_name": "_Test PPT Item SC A", "bom_no":"BOM-_Test PPT Item SC A-001", "doctype":"BOM Item", "stock_qty":1, "rate":100, "amount": 100} ])
def test_request_for_raw_materials(self): from erpnext.stock.doctype.item.test_item import make_item item = make_item( "_Test Finished Item", { "is_stock_item": 1, "maintain_stock": 1, "valuation_rate": 500, "item_defaults": [{ "default_warehouse": "_Test Warehouse - _TC", "company": "_Test Company" }] }) make_item( "_Test Raw Item A", { "maintain_stock": 1, "valuation_rate": 100, "item_defaults": [{ "default_warehouse": "_Test Warehouse - _TC", "company": "_Test Company" }] }) make_item( "_Test Raw 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 Raw Item A', '_Test Raw Item B']) so = make_sales_order(**{ "item_list": [{ "item_code": item.item_code, "qty": 1, "rate": 1000 }] }) so.submit() mr_dict = frappe._dict() items = so.get_work_order_items(1) mr_dict['items'] = items mr_dict['include_exploded_items'] = 0 mr_dict['ignore_existing_ordered_qty'] = 1 make_raw_material_request(mr_dict, so.company, so.name) mr = frappe.db.sql( """select name from `tabMaterial Request` ORDER BY creation DESC LIMIT 1""", as_dict=1)[0] mr_doc = frappe.get_doc('Material Request', mr.get('name')) self.assertEqual(mr_doc.items[0].sales_order, so.name)
def setUpClass(cls) -> None: super().setUpClass() make_item(cls.ITEM_CODE, {"valuation_method": "LIFO"})
def make_batch_item(cls, item_name): from erpnext.stock.doctype.item.test_item import make_item if not frappe.db.exists(item_name): make_item(item_name, dict(has_batch_no = 1, create_new_batch = 1))
def make_purchase_receipt(**args): if not frappe.db.exists('Location', 'Test Location'): frappe.get_doc({ 'doctype': 'Location', 'location_name': 'Test Location' }).insert() frappe.db.set_value("Buying Settings", None, "allow_multiple_items", 1) pr = frappe.new_doc("Purchase Receipt") args = frappe._dict(args) pr.posting_date = args.posting_date or today() if args.posting_time: pr.posting_time = args.posting_time pr.company = args.company or "_Test Company" pr.supplier = args.supplier or "_Test Supplier" pr.is_subcontracted = args.is_subcontracted or "No" pr.supplier_warehouse = args.supplier_warehouse or "_Test Warehouse 1 - _TC" pr.currency = args.currency or "INR" pr.is_return = args.is_return pr.return_against = args.return_against qty = args.qty or 5 received_qty = args.received_qty or qty rejected_qty = args.rejected_qty or flt(received_qty) - flt(qty) item_code = args.item or args.item_code or "_Test Item" if not frappe.db.exists('Item', item_code): make_item( item_code, { 'is_stock_item': 0, 'stock_uom': 'Box', 'is_fixed_asset': 1, 'auto_create_assets': 1, 'asset_naming_series': 'ABC.###', 'is_sales_item': 1 }) uom = args.uom or frappe.db.get_value("Item", item_code, "stock_uom") or "_Test UOM" pr.append( "items", { "item_code": item_code, "warehouse": args.warehouse or "_Test Warehouse - _TC", "qty": qty, "received_qty": received_qty, "rejected_qty": rejected_qty, "rejected_warehouse": args.rejected_warehouse or "_Test Rejected Warehouse - _TC" if rejected_qty != 0 else "", "rate": args.rate or 50, "conversion_factor": args.conversion_factor or 1.0, "serial_no": args.serial_no, "stock_uom": args.stock_uom or "_Test UOM", "uom": uom, "cost_center": args.cost_center or frappe.get_cached_value('Company', pr.company, 'cost_center'), "asset_location": args.location or "Test Location" }) if args.get_multiple_items: pr.items = [] for item in get_items(warehouse=args.warehouse, cost_center=args.cost_center or frappe.get_cached_value( 'Company', pr.company, 'cost_center')): pr.append("items", item) if args.get_taxes_and_charges: for tax in get_taxes(): pr.append("taxes", tax) if not args.do_not_save: pr.insert() if not args.do_not_submit: pr.submit() return pr
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)
def test_pick_list_for_items_from_multiple_sales_orders(self): item_code = make_item().name try: frappe.get_doc({ "doctype": "Stock Reconciliation", "company": "_Test Company", "purpose": "Opening Stock", "expense_account": "Temporary Opening - _TC", "items": [{ "item_code": item_code, "warehouse": "_Test Warehouse - _TC", "valuation_rate": 100, "qty": 10, }], }).submit() except EmptyStockReconciliationItemsError: pass sales_order = frappe.get_doc({ "doctype": "Sales Order", "customer": "_Test Customer", "company": "_Test Company", "items": [{ "item_code": item_code, "qty": 10, "delivery_date": frappe.utils.today(), "warehouse": "_Test Warehouse - _TC", }], }) sales_order.submit() pick_list = frappe.get_doc({ "doctype": "Pick List", "company": "_Test Company", "customer": "_Test Customer", "items_based_on": "Sales Order", "purpose": "Delivery", "locations": [ { "item_code": item_code, "qty": 5, "stock_qty": 5, "conversion_factor": 1, "sales_order": "_T-Sales Order-1", "sales_order_item": "_T-Sales Order-1_item", }, { "item_code": item_code, "qty": 5, "stock_qty": 5, "conversion_factor": 1, "sales_order": sales_order.name, "sales_order_item": sales_order.items[0].name, }, ], }) pick_list.set_item_locations() self.assertEqual(pick_list.locations[0].item_code, item_code) self.assertEqual(pick_list.locations[0].warehouse, "_Test Warehouse - _TC") self.assertEqual(pick_list.locations[0].qty, 5) self.assertEqual(pick_list.locations[0].sales_order_item, "_T-Sales Order-1_item") self.assertEqual(pick_list.locations[1].item_code, item_code) self.assertEqual(pick_list.locations[1].warehouse, "_Test Warehouse - _TC") self.assertEqual(pick_list.locations[1].qty, 5) self.assertEqual(pick_list.locations[1].sales_order_item, sales_order.items[0].name)
def test_supplied_qty_against_subcontracted_po(self): item_code = "_Test Subcontracted FG Item 5" make_item('Sub Contracted Raw Material 4', { 'is_stock_item': 1, 'is_sub_contracted_item': 1 }) make_subcontracted_item( item_code=item_code, raw_materials=["Sub Contracted Raw Material 4"]) update_backflush_based_on("Material Transferred for Subcontract") order_qty = 250 po = create_purchase_order( item_code=item_code, qty=order_qty, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC", do_not_save=True) # Add same subcontracted items multiple times po.append( "items", { "item_code": item_code, "qty": order_qty, "schedule_date": add_days(nowdate(), 1), "warehouse": "_Test Warehouse - _TC" }) po.set_missing_values() po.submit() # Material receipt entry for the raw materials which will be send to supplier make_stock_entry(target="_Test Warehouse - _TC", item_code="Sub Contracted Raw Material 4", qty=500, basic_rate=100) rm_items = [ { "item_code": item_code, "rm_item_code": "Sub Contracted Raw Material 4", "item_name": "_Test Item", "qty": 250, "warehouse": "_Test Warehouse - _TC", "stock_uom": "Nos", "name": po.supplied_items[0].name }, { "item_code": item_code, "rm_item_code": "Sub Contracted Raw Material 4", "item_name": "_Test Item", "qty": 250, "warehouse": "_Test Warehouse - _TC", "stock_uom": "Nos" }, ] # Raw Materials transfer entry from stores to supplier's warehouse rm_item_string = json.dumps(rm_items) se = frappe.get_doc( make_subcontract_transfer_entry(po.name, rm_item_string)) se.submit() # Test po_detail field has value or not for item_row in se.items: self.assertEqual(item_row.po_detail, po.supplied_items[item_row.idx - 1].name) po_doc = frappe.get_doc("Purchase Order", po.name) for row in po_doc.supplied_items: # Valid that whether transferred quantity is matching with supplied qty or not in the purchase order self.assertEqual(row.supplied_qty, 250.0) update_backflush_based_on("BOM")
def test_pick_list_for_items_with_multiple_UOM(self): item_code = make_item().name purchase_receipt = make_purchase_receipt(item_code=item_code, qty=10) purchase_receipt.submit() sales_order = frappe.get_doc({ "doctype": "Sales Order", "customer": "_Test Customer", "company": "_Test Company", "items": [ { "item_code": item_code, "qty": 1, "conversion_factor": 5, "stock_qty": 5, "delivery_date": frappe.utils.today(), "warehouse": "_Test Warehouse - _TC", }, { "item_code": item_code, "qty": 1, "conversion_factor": 1, "delivery_date": frappe.utils.today(), "warehouse": "_Test Warehouse - _TC", }, ], }).insert() sales_order.submit() pick_list = frappe.get_doc({ "doctype": "Pick List", "company": "_Test Company", "customer": "_Test Customer", "items_based_on": "Sales Order", "purpose": "Delivery", "locations": [ { "item_code": item_code, "qty": 2, "stock_qty": 1, "conversion_factor": 0.5, "sales_order": sales_order.name, "sales_order_item": sales_order.items[0].name, }, { "item_code": item_code, "qty": 1, "stock_qty": 1, "conversion_factor": 1, "sales_order": sales_order.name, "sales_order_item": sales_order.items[1].name, }, ], }) pick_list.set_item_locations() pick_list.submit() delivery_note = create_delivery_note(pick_list.name) self.assertEqual(pick_list.locations[0].qty, delivery_note.items[0].qty) self.assertEqual(pick_list.locations[1].qty, delivery_note.items[1].qty) self.assertEqual(sales_order.items[0].conversion_factor, delivery_note.items[0].conversion_factor) pick_list.cancel() sales_order.cancel() purchase_receipt.cancel()
def test_backflush_based_on_stock_entry(self): item_code = "_Test Subcontracted FG Item 1" make_subcontracted_item(item_code=item_code) make_item('Sub Contracted Raw Material 1', { 'is_stock_item': 1, 'is_sub_contracted_item': 1 }) update_backflush_based_on("Material Transferred for Subcontract") order_qty = 5 po = create_purchase_order( item_code=item_code, qty=order_qty, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC") make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100", qty=10, basic_rate=100) make_stock_entry(target="_Test Warehouse - _TC", item_code="Test Extra Item 1", qty=100, basic_rate=100) make_stock_entry(target="_Test Warehouse - _TC", item_code="Test Extra Item 2", qty=10, basic_rate=100) make_stock_entry(target="_Test Warehouse - _TC", item_code="Sub Contracted Raw Material 1", qty=10, basic_rate=100) rm_items = [{ "item_code": item_code, "rm_item_code": "Sub Contracted Raw Material 1", "item_name": "_Test Item", "qty": 10, "warehouse": "_Test Warehouse - _TC", "stock_uom": "Nos" }, { "item_code": item_code, "rm_item_code": "_Test Item Home Desktop 100", "item_name": "_Test Item Home Desktop 100", "qty": 20, "warehouse": "_Test Warehouse - _TC", "stock_uom": "Nos" }, { "item_code": item_code, "rm_item_code": "Test Extra Item 1", "item_name": "Test Extra Item 1", "qty": 10, "warehouse": "_Test Warehouse - _TC", "stock_uom": "Nos" }, { 'item_code': item_code, 'rm_item_code': 'Test Extra Item 2', 'stock_uom': 'Nos', 'qty': 10, 'warehouse': '_Test Warehouse - _TC', 'item_name': 'Test Extra Item 2' }] rm_item_string = json.dumps(rm_items) se = frappe.get_doc( make_subcontract_transfer_entry(po.name, rm_item_string)) se.submit() pr = make_purchase_receipt(po.name) received_qty = 2 # partial receipt pr.get('items')[0].qty = received_qty pr.save() pr.submit() transferred_items = sorted([ d.item_code for d in se.get('items') if se.purchase_order == po.name ]) issued_items = sorted( [d.rm_item_code for d in pr.get('supplied_items')]) self.assertEquals(transferred_items, issued_items) self.assertEquals(pr.get('items')[0].rm_supp_cost, 2000) transferred_rm_map = frappe._dict() for item in rm_items: transferred_rm_map[item.get('rm_item_code')] = item for item in pr.get('supplied_items'): self.assertEqual( item.get('required_qty'), (transferred_rm_map[item.get('rm_item_code')].get('qty') / order_qty) * received_qty) update_backflush_based_on("BOM")
def make_batch_item(self): from erpnext.stock.doctype.item.test_item import make_item if not frappe.db.exists('ITEM-BATCH-1'): make_item('ITEM-BATCH-1', dict(has_batch_no = 1, create_new_batch = 1))