def test_backflush_based_on_stock_entry(self): item_code = "_Test Subcontracted FG Item 1" make_subcontracted_item(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 test_subcontracting_over_receipt(self): """ Behaviour: Raise multiple PRs against one PO that in total receive more than the required qty in the PO. Expected Result: Error Raised for Over Receipt against PO. """ from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry from erpnext.buying.doctype.purchase_order.test_purchase_order import (update_backflush_based_on, make_subcontracted_item, create_purchase_order) from erpnext.buying.doctype.purchase_order.purchase_order import (make_purchase_receipt, make_rm_stock_entry as make_subcontract_transfer_entry) update_backflush_based_on("Material Transferred for Subcontract") item_code = "_Test Subcontracted FG Item 1" make_subcontracted_item(item_code=item_code) po = create_purchase_order(item_code=item_code, qty=1, include_exploded_items=0, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC") #stock raw materials in a warehouse before transfer se1 = make_stock_entry(target="_Test Warehouse - _TC", item_code = "Test Extra Item 1", qty=10, basic_rate=100) se2 = make_stock_entry(target="_Test Warehouse - _TC", item_code = "_Test FG Item", qty=1, basic_rate=100) rm_items = [ { "item_code": item_code, "rm_item_code": po.supplied_items[0].rm_item_code, "item_name": "_Test FG Item", "qty": po.supplied_items[0].required_qty, "warehouse": "_Test Warehouse - _TC", "stock_uom": "Nos" }, { "item_code": item_code, "rm_item_code": po.supplied_items[1].rm_item_code, "item_name": "Test Extra Item 1", "qty": po.supplied_items[1].required_qty, "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.to_warehouse = "_Test Warehouse 1 - _TC" se.save() se.submit() pr1 = make_purchase_receipt(po.name) pr2 = make_purchase_receipt(po.name) pr1.submit() self.assertRaises(frappe.ValidationError, pr2.submit) pr1.cancel() se.cancel() se1.cancel() se2.cancel() po.reload() po.cancel()
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_backflush_based_on_stock_entry(self): item_code = "_Test Subcontracted FG Item 1" make_subcontracted_item(item_code) update_backflush_based_on("Material Transferred for Subcontract") po = create_purchase_order(item_code=item_code, qty=1, is_subcontracted="Yes", supplier_warehouse="_Test Warehouse 1 - _TC") make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100) 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) rm_item = [ {"item_code":item_code,"rm_item_code":"_Test Item","item_name":"_Test Item", "qty":1,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":100,"stock_uom":"Nos"}, {"item_code":item_code,"rm_item_code":"_Test Item Home Desktop 100","item_name":"_Test Item Home Desktop 100", "qty":2,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":200,"stock_uom":"Nos"}, {"item_code":item_code,"rm_item_code":"Test Extra Item 1","item_name":"Test Extra Item 1", "qty":1,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":200,"stock_uom":"Nos"}] rm_item_string = json.dumps(rm_item) se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string)) se.append('items', { 'item_code': "Test Extra Item 2", "qty": 1, "rate": 100, "s_warehouse": "_Test Warehouse - _TC", "t_warehouse": "_Test Warehouse 1 - _TC" }) se.set_missing_values() se.submit() pr = make_purchase_receipt(po.name) pr.save() pr.submit() se_items = sorted([d.item_code for d in se.get('items')]) supplied_items = sorted([d.rm_item_code for d in pr.get('supplied_items')]) self.assertEquals(se_items, supplied_items) update_backflush_based_on("BOM")
def test_reserved_qty_subcontract_po(self): # Make stock available for raw materials make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100) make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100", qty=20, basic_rate=100) bin1 = frappe.db.get_value( "Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname=["reserved_qty_for_sub_contract", "projected_qty"], as_dict=1) # Submit PO po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes") bin2 = frappe.db.get_value( "Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname=["reserved_qty_for_sub_contract", "projected_qty"], as_dict=1) self.assertEquals(bin2.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10) self.assertEquals(bin2.projected_qty, bin1.projected_qty - 10) # Create stock transfer rm_item = [{ "item_code": "_Test FG Item", "rm_item_code": "_Test Item", "item_name": "_Test Item", "qty": 6, "warehouse": "_Test Warehouse - _TC", "rate": 100, "amount": 600, "stock_uom": "Nos" }] rm_item_string = json.dumps(rm_item) se = frappe.get_doc( make_subcontract_transfer_entry(po.name, rm_item_string)) se.to_warehouse = "_Test Warehouse 1 - _TC" se.save() se.submit() bin3 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin3.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6) # close PO po.update_status("Closed") bin4 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin4.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract) # Re-open PO po.update_status("Submitted") bin5 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6) # make Purchase Receipt against PO pr = make_purchase_receipt(po.name) pr.supplier_warehouse = "_Test Warehouse 1 - _TC" pr.save() pr.submit() bin6 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin6.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract) # Cancel PR pr.cancel() bin7 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin7.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6) # Make Purchase Invoice pi = make_purchase_invoice(po.name) pi.update_stock = 1 pi.supplier_warehouse = "_Test Warehouse 1 - _TC" pi.insert() pi.submit() bin8 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin8.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract) # Cancel PR pi.cancel() bin9 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin9.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6) # Cancel Stock Entry se.cancel() bin10 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin10.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10) # Cancel PO po.reload() po.cancel() bin11 = frappe.db.get_value("Bin", filters={ "warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item" }, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin11.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)
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 test_reserved_qty_subcontract_po(self): # Make stock available for raw materials make_stock_entry(target="_Test Warehouse - _TC", qty=10, basic_rate=100) make_stock_entry(target="_Test Warehouse - _TC", item_code="_Test Item Home Desktop 100", qty=20, basic_rate=100) make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item", qty=30, basic_rate=100) make_stock_entry(target="_Test Warehouse 1 - _TC", item_code="_Test Item Home Desktop 100", qty=30, basic_rate=100) bin1 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname=["reserved_qty_for_sub_contract", "projected_qty"], as_dict=1) # Submit PO po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes") bin2 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname=["reserved_qty_for_sub_contract", "projected_qty"], as_dict=1) self.assertEquals(bin2.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10) self.assertEquals(bin2.projected_qty, bin1.projected_qty - 10) # Create stock transfer rm_item = [{"item_code":"_Test FG Item","rm_item_code":"_Test Item","item_name":"_Test Item", "qty":6,"warehouse":"_Test Warehouse - _TC","rate":100,"amount":600,"stock_uom":"Nos"}] rm_item_string = json.dumps(rm_item) se = frappe.get_doc(make_subcontract_transfer_entry(po.name, rm_item_string)) se.to_warehouse = "_Test Warehouse 1 - _TC" se.save() se.submit() bin3 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin3.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6) # close PO po.update_status("Closed") bin4 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin4.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract) # Re-open PO po.update_status("Submitted") bin5 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin5.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6) # make Purchase Receipt against PO pr = make_purchase_receipt(po.name) pr.supplier_warehouse = "_Test Warehouse 1 - _TC" pr.save() pr.submit() bin6 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin6.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract) # Cancel PR pr.cancel() bin7 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin7.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6) # Make Purchase Invoice pi = make_purchase_invoice(po.name) pi.update_stock = 1 pi.supplier_warehouse = "_Test Warehouse 1 - _TC" pi.insert() pi.submit() bin8 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin8.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract) # Cancel PR pi.cancel() bin9 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin9.reserved_qty_for_sub_contract, bin2.reserved_qty_for_sub_contract - 6) # Cancel Stock Entry se.cancel() bin10 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin10.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract + 10) # Cancel PO po.reload() po.cancel() bin11 = frappe.db.get_value("Bin", filters={"warehouse": "_Test Warehouse - _TC", "item_code": "_Test Item"}, fieldname="reserved_qty_for_sub_contract", as_dict=1) self.assertEquals(bin11.reserved_qty_for_sub_contract, bin1.reserved_qty_for_sub_contract)