def test_update_child_adding_new_item(self): po = create_purchase_order(do_not_save=1) po.items[0].qty = 4 po.save() po.submit() pr = make_pr_against_po(po.name, 2) po.load_from_db() existing_ordered_qty = get_ordered_qty() first_item_of_po = po.get("items")[0] trans_item = json.dumps([ { "item_code": first_item_of_po.item_code, "rate": first_item_of_po.rate, "qty": first_item_of_po.qty, "docname": first_item_of_po.name, }, { "item_code": "_Test Item", "rate": 200, "qty": 7 }, ]) update_child_qty_rate("Purchase Order", trans_item, po.name) po.reload() self.assertEqual(len(po.get("items")), 2) self.assertEqual(po.status, "To Receive and Bill") # ordered qty should increase on row addition self.assertEqual(get_ordered_qty(), existing_ordered_qty + 7)
def test_update_child_adding_new_item(self): so = make_sales_order(item_code= "_Test Item", qty=4) create_dn_against_so(so.name, 4) make_sales_invoice(so.name) prev_total = so.get("base_total") prev_total_in_words = so.get("base_in_words") first_item_of_so = so.get("items")[0] trans_item = json.dumps([ {'item_code' : first_item_of_so.item_code, 'rate' : first_item_of_so.rate, \ 'qty' : first_item_of_so.qty, 'docname': first_item_of_so.name}, {'item_code' : '_Test Item 2', 'rate' : 200, 'qty' : 7} ]) update_child_qty_rate('Sales Order', trans_item, so.name) so.reload() self.assertEqual(so.get("items")[-1].item_code, '_Test Item 2') self.assertEqual(so.get("items")[-1].rate, 200) self.assertEqual(so.get("items")[-1].qty, 7) self.assertEqual(so.get("items")[-1].amount, 1400) self.assertEqual(so.status, 'To Deliver and Bill') updated_total = so.get("base_total") updated_total_in_words = so.get("base_in_words") self.assertEqual(updated_total, prev_total+1400) self.assertNotEqual(updated_total_in_words, prev_total_in_words)
def test_update_child_qty_rate(self): mr = make_material_request(qty=10) po = make_purchase_order(mr.name) po.supplier = "_Test Supplier" po.items[0].qty = 4 po.save() po.submit() create_pr_against_po(po.name) make_purchase_invoice(po.name) existing_ordered_qty = get_ordered_qty() existing_requested_qty = get_requested_qty() trans_item = json.dumps([{ 'item_code': '_Test Item', 'rate': 200, 'qty': 7, 'docname': po.items[0].name }]) update_child_qty_rate('Purchase Order', trans_item, po.name) mr.reload() self.assertEqual(mr.items[0].ordered_qty, 7) self.assertEqual(mr.per_ordered, 70) self.assertEqual(get_requested_qty(), existing_requested_qty - 3) po.reload() self.assertEqual(po.get("items")[0].rate, 200) self.assertEqual(po.get("items")[0].qty, 7) self.assertEqual(po.get("items")[0].amount, 1400) self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
def test_update_child(self): mr = make_material_request(qty=10) po = make_purchase_order(mr.name) po.supplier = "_Test Supplier" po.items[0].qty = 4 po.save() po.submit() create_pr_against_po(po.name) make_pi_from_po(po.name) existing_ordered_qty = get_ordered_qty() existing_requested_qty = get_requested_qty() trans_item = json.dumps([{ "item_code": "_Test Item", "rate": 200, "qty": 7, "docname": po.items[0].name }]) update_child_qty_rate("Purchase Order", trans_item, po.name) mr.reload() self.assertEqual(mr.items[0].ordered_qty, 7) self.assertEqual(mr.per_ordered, 70) self.assertEqual(get_requested_qty(), existing_requested_qty - 3) po.reload() self.assertEqual(po.get("items")[0].rate, 200) self.assertEqual(po.get("items")[0].qty, 7) self.assertEqual(po.get("items")[0].amount, 1400) self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
def test_update_child_qty_rate(self): so = make_sales_order(item_code="_Test Item", qty=4) create_dn_against_so(so.name, 4) make_sales_invoice(so.name) existing_reserved_qty = get_reserved_qty() trans_item = json.dumps([{ 'item_code': '_Test Item', 'rate': 200, 'qty': 7, 'docname': so.items[0].name }]) update_child_qty_rate('Sales Order', trans_item, so.name) so.reload() self.assertEqual(so.get("items")[0].rate, 200) self.assertEqual(so.get("items")[0].qty, 7) self.assertEqual(so.get("items")[0].amount, 1400) self.assertEqual(so.status, 'To Deliver and Bill') self.assertEqual(get_reserved_qty(), existing_reserved_qty + 3) trans_item = json.dumps([{ 'item_code': '_Test Item', 'rate': 200, 'qty': 2, 'docname': so.items[0].name }]) self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Sales Order', trans_item, so.name)
def test_update_child_qty_rate(self): mr = make_material_request(qty=10) po = make_purchase_order(mr.name) po.supplier = "_Test Supplier" po.items[0].qty = 4 po.save() po.submit() create_pr_against_po(po.name) make_purchase_invoice(po.name) existing_ordered_qty = get_ordered_qty() existing_requested_qty = get_requested_qty() trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': po.items[0].name}]) update_child_qty_rate('Purchase Order', trans_item, po.name) mr.reload() self.assertEqual(mr.items[0].ordered_qty, 7) self.assertEqual(mr.per_ordered, 70) self.assertEqual(get_requested_qty(), existing_requested_qty - 3) po.reload() self.assertEqual(po.get("items")[0].rate, 200) self.assertEqual(po.get("items")[0].qty, 7) self.assertEqual(po.get("items")[0].amount, 1400) self.assertEqual(get_ordered_qty(), existing_ordered_qty + 3)
def test_update_child_qty_rate_product_bundle(self): # test Update Items with product bundle if not frappe.db.exists("Item", "_Product Bundle Item"): bundle_item = make_item("_Product Bundle Item", {"is_stock_item": 0}) bundle_item.append( "item_defaults", { "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC" }) bundle_item.save(ignore_permissions=True) make_item("_Packed Item", {"is_stock_item": 1}) make_product_bundle("_Product Bundle Item", ["_Packed Item"], 2) so = make_sales_order(item_code="_Test Item", warehouse=None) added_item = json.dumps([{ "item_code": "_Product Bundle Item", "rate": 200, 'qty': 2 }]) update_child_qty_rate('Sales Order', added_item, so.name) so.reload() self.assertEqual(so.packed_items[0].qty, 4)
def test_update_child_qty_rate_with_workflow(self): from frappe.model.workflow import apply_workflow workflow = make_sales_order_workflow() so = make_sales_order(item_code= "_Test Item", qty=1, rate=150, do_not_submit=1) apply_workflow(so, 'Approve') frappe.set_user("Administrator") user = '******' test_user = frappe.get_doc('User', user) test_user.add_roles("Sales User", "Test Junior Approver") frappe.set_user(user) # user shouldn't be able to edit since grand_total will become > 200 if qty is doubled trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 150, 'qty' : 2, 'docname': so.items[0].name}]) self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Sales Order', trans_item, so.name) frappe.set_user("Administrator") user2 = '*****@*****.**' test_user2 = frappe.get_doc('User', user2) test_user2.add_roles("Sales User", "Test Approver") frappe.set_user(user2) # Test Approver is allowed to edit with grand_total > 200 update_child_qty_rate("Sales Order", trans_item, so.name) so.reload() self.assertEqual(so.items[0].qty, 2) frappe.set_user("Administrator") test_user.remove_roles("Sales User", "Test Junior Approver", "Test Approver") test_user2.remove_roles("Sales User", "Test Junior Approver", "Test Approver") workflow.is_active = 0 workflow.save()
def test_update_child_product_bundle(self): # test Update Items with product bundle if not frappe.db.exists("Item", "_Product Bundle Item"): bundle_item = make_item("_Product Bundle Item", {"is_stock_item": 0}) bundle_item.append("item_defaults", { "company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}) bundle_item.save(ignore_permissions=True) make_item("_Packed Item", {"is_stock_item": 1}) make_product_bundle("_Product Bundle Item", ["_Packed Item"], 2) so = make_sales_order(item_code = "_Test Item", warehouse=None) added_item = json.dumps([{"item_code" : "_Product Bundle Item", "rate" : 200, 'qty' : 2}]) update_child_qty_rate('Sales Order', added_item, so.name) so.reload() self.assertEqual(so.packed_items[0].qty, 4) # test uom and conversion factor change update_uom_conv_factor = json.dumps([{ 'item_code': so.get("items")[0].item_code, 'rate': so.get("items")[0].rate, 'qty': so.get("items")[0].qty, 'uom': "_Test UOM 1", 'conversion_factor': 2, 'docname': so.get("items")[0].name }]) update_child_qty_rate('Sales Order', update_uom_conv_factor, so.name) so.reload() self.assertEqual(so.packed_items[0].qty, 8)
def test_update_child_adding_new_item(self): po = create_purchase_order(do_not_save=1) po.items[0].qty = 4 po.save() po.submit() pr = make_pr_against_po(po.name, 2) po.load_from_db() first_item_of_po = po.get("items")[0] trans_item = json.dumps([{ 'item_code': first_item_of_po.item_code, 'rate': first_item_of_po.rate, 'qty': first_item_of_po.qty, 'docname': first_item_of_po.name }, { 'item_code': '_Test Item', 'rate': 200, 'qty': 7 }]) update_child_qty_rate('Purchase Order', trans_item, po.name) po.reload() self.assertEquals(len(po.get('items')), 2) self.assertEqual(po.status, 'To Receive and Bill')
def test_update_child_removing_item(self): po = create_purchase_order(do_not_save=1) po.items[0].qty = 4 po.save() po.submit() pr = make_pr_against_po(po.name, 2) po.reload() first_item_of_po = po.get("items")[0] existing_ordered_qty = get_ordered_qty() # add an item trans_item = json.dumps([ { "item_code": first_item_of_po.item_code, "rate": first_item_of_po.rate, "qty": first_item_of_po.qty, "docname": first_item_of_po.name, }, { "item_code": "_Test Item", "rate": 200, "qty": 7 }, ]) update_child_qty_rate("Purchase Order", trans_item, po.name) po.reload() # ordered qty should increase on row addition self.assertEqual(get_ordered_qty(), existing_ordered_qty + 7) # check if can remove received item trans_item = json.dumps([{ "item_code": "_Test Item", "rate": 200, "qty": 7, "docname": po.get("items")[1].name }]) self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Purchase Order", trans_item, po.name) first_item_of_po = po.get("items")[0] trans_item = json.dumps([{ "item_code": first_item_of_po.item_code, "rate": first_item_of_po.rate, "qty": first_item_of_po.qty, "docname": first_item_of_po.name, }]) update_child_qty_rate("Purchase Order", trans_item, po.name) po.reload() self.assertEqual(len(po.get("items")), 1) self.assertEqual(po.status, "To Receive and Bill") # ordered qty should decrease (back to initial) on row deletion self.assertEqual(get_ordered_qty(), existing_ordered_qty)
def test_update_remove_child_linked_to_mr(self): """Test impact on linked PO and MR on deleting/updating row.""" mr = make_material_request(qty=10) po = make_purchase_order(mr.name) po.supplier = "_Test Supplier" po.save() po.submit() first_item_of_po = po.get("items")[0] existing_ordered_qty = get_ordered_qty() # 10 existing_requested_qty = get_requested_qty() # 0 # decrease ordered qty by 3 (10 -> 7) and add item trans_item = json.dumps([ { "item_code": first_item_of_po.item_code, "rate": first_item_of_po.rate, "qty": 7, "docname": first_item_of_po.name, }, { "item_code": "_Test Item 2", "rate": 200, "qty": 2 }, ]) update_child_qty_rate("Purchase Order", trans_item, po.name) mr.reload() # requested qty increases as ordered qty decreases self.assertEqual(get_requested_qty(), existing_requested_qty + 3) # 3 self.assertEqual(mr.items[0].ordered_qty, 7) self.assertEqual(get_ordered_qty(), existing_ordered_qty - 3) # 7 # delete first item linked to Material Request trans_item = json.dumps([{ "item_code": "_Test Item 2", "rate": 200, "qty": 2 }]) update_child_qty_rate("Purchase Order", trans_item, po.name) mr.reload() # requested qty increases as ordered qty is 0 (deleted row) self.assertEqual(get_requested_qty(), existing_requested_qty + 10) # 10 self.assertEqual(mr.items[0].ordered_qty, 0) # ordered qty decreases as ordered qty is 0 (deleted row) self.assertEqual(get_ordered_qty(), existing_ordered_qty - 10) # 0
def test_add_new_item_in_update_child_qty_rate(self): so = make_sales_order(item_code= "_Test Item", qty=4) create_dn_against_so(so.name, 4) make_sales_invoice(so.name) trans_item = json.dumps([{'item_code' : '_Test Item 2', 'rate' : 200, 'qty' : 7}]) update_child_qty_rate('Sales Order', trans_item, so.name) so.reload() self.assertEqual(so.get("items")[-1].item_code, '_Test Item 2') self.assertEqual(so.get("items")[-1].rate, 200) self.assertEqual(so.get("items")[-1].qty, 7) self.assertEqual(so.get("items")[-1].amount, 1400) self.assertEqual(so.status, 'To Deliver and Bill')
def test_update_child_with_precision(self): from frappe.model.meta import get_field_precision from frappe.custom.doctype.property_setter.property_setter import make_property_setter precision = get_field_precision(frappe.get_meta("Sales Order Item").get_field("rate")) make_property_setter("Sales Order Item", "rate", "precision", 7, "Currency") so = make_sales_order(item_code= "_Test Item", qty=4, rate=200.34664) trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200.34669, 'qty' : 4, 'docname': so.items[0].name}]) update_child_qty_rate('Sales Order', trans_item, so.name) so.reload() self.assertEqual(so.items[0].rate, 200.34669) make_property_setter("Sales Order Item", "rate", "precision", precision, "Currency")
def test_remove_item_in_update_child_qty_rate(self): so = make_sales_order(**{ "item_list": [{ "item_code": '_Test Item', "qty": 5, "rate": 1000 }] }) create_dn_against_so(so.name, 2) make_sales_invoice(so.name) # add an item so as to try removing items trans_item = json.dumps([{ "item_code": '_Test Item', "qty": 5, "rate": 1000, "docname": so.get("items")[0].name }, { "item_code": '_Test Item 2', "qty": 2, "rate": 500 }]) update_child_qty_rate('Sales Order', trans_item, so.name) so.reload() self.assertEqual(len(so.get("items")), 2) # check if delivered items can be removed trans_item = json.dumps([{ "item_code": '_Test Item 2', "qty": 2, "rate": 500, "docname": so.get("items")[1].name }]) self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Sales Order', trans_item, so.name) #remove last added item trans_item = json.dumps([{ "item_code": '_Test Item', "qty": 5, "rate": 1000, "docname": so.get("items")[0].name }]) update_child_qty_rate('Sales Order', trans_item, so.name) so.reload() self.assertEqual(len(so.get("items")), 1) self.assertEqual(so.status, 'To Deliver and Bill')
def test_update_child_removing_item(self): po = create_purchase_order(do_not_save=1) po.items[0].qty = 4 po.save() po.submit() pr = make_pr_against_po(po.name, 2) po.reload() first_item_of_po = po.get("items")[0] # add an item trans_item = json.dumps([{ 'item_code': first_item_of_po.item_code, 'rate': first_item_of_po.rate, 'qty': first_item_of_po.qty, 'docname': first_item_of_po.name }, { 'item_code': '_Test Item', 'rate': 200, 'qty': 7 }]) update_child_qty_rate('Purchase Order', trans_item, po.name) po.reload() # check if can remove received item trans_item = json.dumps([{ 'item_code': '_Test Item', 'rate': 200, 'qty': 7, 'docname': po.get("items")[1].name }]) self.assertRaises(frappe.ValidationError, update_child_qty_rate, 'Purchase Order', trans_item, po.name) first_item_of_po = po.get("items")[0] trans_item = json.dumps([{ 'item_code': first_item_of_po.item_code, 'rate': first_item_of_po.rate, 'qty': first_item_of_po.qty, 'docname': first_item_of_po.name }]) update_child_qty_rate('Purchase Order', trans_item, po.name) po.reload() self.assertEquals(len(po.get('items')), 1) self.assertEqual(po.status, 'To Receive and Bill')
def test_update_child_uom_conv_factor_change(self): po = create_purchase_order(item_code="_Test FG Item", is_subcontracted="Yes") total_reqd_qty = sum([d.get("required_qty") for d in po.as_dict().get("supplied_items")]) trans_item = json.dumps([{ 'item_code': po.get("items")[0].item_code, 'rate': po.get("items")[0].rate, 'qty': po.get("items")[0].qty, 'uom': "_Test UOM 1", 'conversion_factor': 2, 'docname': po.get("items")[0].name }]) update_child_qty_rate('Purchase Order', trans_item, po.name) po.reload() total_reqd_qty_after_change = sum([d.get("required_qty") for d in po.as_dict().get("supplied_items")]) self.assertEqual(total_reqd_qty_after_change, 2 * total_reqd_qty)
def test_update_child_qty_rate(self): so = make_sales_order(item_code= "_Test Item", qty=4) create_dn_against_so(so.name, 4) make_sales_invoice(so.name) existing_reserved_qty = get_reserved_qty() trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 7, 'docname': so.items[0].name}]) update_child_qty_rate('Sales Order', trans_item, so.name) so.reload() self.assertEqual(so.get("items")[0].rate, 200) self.assertEqual(so.get("items")[0].qty, 7) self.assertEqual(so.get("items")[0].amount, 1400) self.assertEqual(so.status, 'To Deliver and Bill') self.assertEqual(get_reserved_qty(), existing_reserved_qty + 3) trans_item = json.dumps([{'item_code' : '_Test Item', 'rate' : 200, 'qty' : 2, 'docname': so.items[0].name}]) self.assertRaises(frappe.ValidationError, update_child_qty_rate,'Sales Order', trans_item, so.name)
def test_update_child_uom_conv_factor_change(self): po = create_purchase_order(item_code="_Test FG Item", is_subcontracted=1) total_reqd_qty = sum([ d.get("required_qty") for d in po.as_dict().get("supplied_items") ]) trans_item = json.dumps([{ "item_code": po.get("items")[0].item_code, "rate": po.get("items")[0].rate, "qty": po.get("items")[0].qty, "uom": "_Test UOM 1", "conversion_factor": 2, "docname": po.get("items")[0].name, }]) update_child_qty_rate("Purchase Order", trans_item, po.name) po.reload() total_reqd_qty_after_change = sum( d.get("required_qty") for d in po.as_dict().get("supplied_items")) self.assertEqual(total_reqd_qty_after_change, 2 * total_reqd_qty)
def test_update_child_with_tax_template(self): tax_template = "_Test Account Excise Duty @ 10" 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 ]) update_child_qty_rate('Purchase Order', items, po.name) po.reload() self.assertEqual(po.taxes[0].tax_amount, 60) self.assertEqual(po.taxes[0].total, 660) 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 })
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()