From 03a6c38f06034383b57593145f8c9e77c42d6370 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Mon, 26 Jul 2021 22:24:25 +0530 Subject: [PATCH 1/6] test: fix test due to rename change --- erpnext/selling/doctype/sales_order/test_sales_order.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 974648d6d44..1de1e000975 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -673,6 +673,8 @@ class TestSalesOrder(unittest.TestCase): so.cancel() + dn.load_from_db() + self.assertRaises(frappe.CancelledLinkError, dn.submit) def test_service_type_product_bundle(self): From e5b02216933a71c06457920e5f3a58a06ffa5bbc Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 11 Aug 2021 13:02:49 +0530 Subject: [PATCH 2/6] test: fix attendance request tests - Use `frappe.db.get_value` instead of `get_doc` for asserting values - Get values after cancellation as reloading attendance doc breaks due to stale doc (primary key changed after cancel of attendance request) - rollback everything on tearDown --- .../test_attendance_request.py | 68 ++++++++++++++----- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/erpnext/hr/doctype/attendance_request/test_attendance_request.py b/erpnext/hr/doctype/attendance_request/test_attendance_request.py index 3c42bd9fc35..0898476edf4 100644 --- a/erpnext/hr/doctype/attendance_request/test_attendance_request.py +++ b/erpnext/hr/doctype/attendance_request/test_attendance_request.py @@ -15,6 +15,9 @@ class TestAttendanceRequest(unittest.TestCase): for doctype in ["Attendance Request", "Attendance"]: frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype)) + def tearDown(self): + frappe.db.rollback() + def test_on_duty_attendance_request(self): today = nowdate() employee = get_employee() @@ -26,15 +29,33 @@ class TestAttendanceRequest(unittest.TestCase): attendance_request.company = "_Test Company" attendance_request.insert() attendance_request.submit() - attendance = frappe.get_doc('Attendance', { - 'employee': employee.name, - 'attendance_date': date(date.today().year, 1, 1), - 'docstatus': 1 - }) - self.assertEqual(attendance.status, 'Present') + + attendance = frappe.db.get_value( + "Attendance", + filters={ + "attendance_request": attendance_request.name, + "attendance_date": date(date.today().year, 1, 1) + }, + fieldname=["status", "docstatus"], + as_dict=True + ) + self.assertEqual(attendance.status, "Present") + self.assertEqual(attendance.docstatus, 1) + + # cancelling attendance request cancels linked attendances attendance_request.cancel() - attendance.reload() - self.assertEqual(attendance.docstatus, 2) + + # cancellation alters docname + # fetch attendance value again to avoid stale docname + attendance_docstatus = frappe.db.get_value( + "Attendance", + filters={ + "attendance_request": attendance_request.name, + "attendance_date": date(date.today().year, 1, 1) + }, + fieldname="docstatus" + ) + self.assertEqual(attendance_docstatus, 2) def test_work_from_home_attendance_request(self): today = nowdate() @@ -47,15 +68,30 @@ class TestAttendanceRequest(unittest.TestCase): attendance_request.company = "_Test Company" attendance_request.insert() attendance_request.submit() - attendance = frappe.get_doc('Attendance', { - 'employee': employee.name, - 'attendance_date': date(date.today().year, 1, 1), - 'docstatus': 1 - }) - self.assertEqual(attendance.status, 'Work From Home') + + attendance_status = frappe.db.get_value( + "Attendance", + filters={ + "attendance_request": attendance_request.name, + "attendance_date": date(date.today().year, 1, 1) + }, + fieldname="status" + ) + self.assertEqual(attendance_status, 'Work From Home') + attendance_request.cancel() - attendance.reload() - self.assertEqual(attendance.docstatus, 2) + + # cancellation alters docname + # fetch attendance value again to avoid stale docname + attendance_docstatus = frappe.db.get_value( + "Attendance", + filters={ + "attendance_request": attendance_request.name, + "attendance_date": date(date.today().year, 1, 1) + }, + fieldname="docstatus" + ) + self.assertEqual(attendance_docstatus, 2) def get_employee(): return frappe.get_doc("Employee", "_T-Employee-00001") From bca30d6101f539b4f68c536e83a82c1cd29b1bb7 Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 11 Aug 2021 13:29:44 +0530 Subject: [PATCH 3/6] test: fix Shift Request test - Use `get_value` instead of `get_doc` - Remove unnecessary loop, only one shift assignment is made against a shift request - Get value after cancel again. Get doc is not reliable since primary key changed after cancel --- .../test_attendance_request.py | 2 ++ .../shift_request/test_shift_request.py | 33 ++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/erpnext/hr/doctype/attendance_request/test_attendance_request.py b/erpnext/hr/doctype/attendance_request/test_attendance_request.py index 0898476edf4..9e668aa72fb 100644 --- a/erpnext/hr/doctype/attendance_request/test_attendance_request.py +++ b/erpnext/hr/doctype/attendance_request/test_attendance_request.py @@ -19,6 +19,7 @@ class TestAttendanceRequest(unittest.TestCase): frappe.db.rollback() def test_on_duty_attendance_request(self): + "Test creation/updation of Attendace from Attendance Request, on duty." today = nowdate() employee = get_employee() attendance_request = frappe.new_doc("Attendance Request") @@ -58,6 +59,7 @@ class TestAttendanceRequest(unittest.TestCase): self.assertEqual(attendance_docstatus, 2) def test_work_from_home_attendance_request(self): + "Test creation/updation of Attendace from Attendance Request, work from home." today = nowdate() employee = get_employee() attendance_request = frappe.new_doc("Attendance Request") diff --git a/erpnext/hr/doctype/shift_request/test_shift_request.py b/erpnext/hr/doctype/shift_request/test_shift_request.py index 9c0d8e31985..3525540cdfd 100644 --- a/erpnext/hr/doctype/shift_request/test_shift_request.py +++ b/erpnext/hr/doctype/shift_request/test_shift_request.py @@ -15,24 +15,35 @@ class TestShiftRequest(unittest.TestCase): for doctype in ["Shift Request", "Shift Assignment"]: frappe.db.sql("delete from `tab{doctype}`".format(doctype=doctype)) + def tearDown(self): + frappe.db.rollback() + def test_make_shift_request(self): + "Test creation/updation of Shift Assignment from Shift Request." department = frappe.get_value("Employee", "_T-Employee-00001", 'department') set_shift_approver(department) approver = frappe.db.sql("""select approver from `tabDepartment Approver` where parent= %s and parentfield = 'shift_request_approver'""", (department))[0][0] shift_request = make_shift_request(approver) - shift_assignments = frappe.db.sql(''' - SELECT shift_request, employee - FROM `tabShift Assignment` - WHERE shift_request = '{0}' - '''.format(shift_request.name), as_dict=1) - for d in shift_assignments: - employee = d.get('employee') - self.assertEqual(shift_request.employee, employee) - shift_request.cancel() - shift_assignment_doc = frappe.get_doc("Shift Assignment", {"shift_request": d.get('shift_request')}) - self.assertEqual(shift_assignment_doc.docstatus, 2) + # Only one shift assignment is created against a shift request + shift_assignment = frappe.db.get_value( + "Shift Assignment", + filters={"shift_request": shift_request.name}, + fieldname=["employee", "docstatus"], + as_dict=True + ) + self.assertEqual(shift_request.employee, shift_assignment.employee) + self.assertEqual(shift_assignment.docstatus, 1) + + shift_request.cancel() + + shift_assignment_docstatus = frappe.db.get_value( + "Shift Assignment", + filters={"shift_request": shift_request.name}, + fieldname="docstatus" + ) + self.assertEqual(shift_assignment_docstatus, 2) def test_shift_request_approver_perms(self): employee = frappe.get_doc("Employee", "_T-Employee-00001") From 8f1a3aef2e3f14e179f4ac91718e9f376b34198c Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 11 Aug 2021 15:17:06 +0530 Subject: [PATCH 4/6] test: fix POS Closing Entry Test - Separated into two tests, one checks if SI cancelling is blocked, the other checks PCE cancel impact - This is done because after cancel via assertRaises, damage done by cancel still exists or is partially comitted - Dont use this partially cancelled doc for any assertions further, end test at exception assertion - Use `get_value` to check SI docstatus, as its primary key changes after cancel --- .../test_pos_closing_entry.py | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index b596c0cf25a..0265f43476f 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -19,6 +19,7 @@ class TestPOSClosingEntry(unittest.TestCase): def tearDown(self): frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`") + frappe.db.rollback() def test_pos_closing_entry(self): test_user, pos_profile = init_user_and_profile() @@ -50,7 +51,8 @@ class TestPOSClosingEntry(unittest.TestCase): self.assertEqual(pcv_doc.total_quantity, 2) self.assertEqual(pcv_doc.net_total, 6700) - def test_cancelling_of_pos_closing_entry(self): + def test_cancelling_of_consolidated_sales_invoice(self): + "Check if cancelling consolidated Sales Invoice with submitted POS Closing Entry is blocked." test_user, pos_profile = init_user_and_profile() opening_entry = create_opening_entry(pos_profile, test_user.name) @@ -83,13 +85,46 @@ class TestPOSClosingEntry(unittest.TestCase): si_doc = frappe.get_doc("Sales Invoice", pos_inv1.consolidated_invoice) self.assertRaises(frappe.ValidationError, si_doc.cancel) + def test_cancelling_of_pos_closing_entry(self): + "Check impact of cancelling POS Closing Entry." + test_user, pos_profile = init_user_and_profile() + opening_entry = create_opening_entry(pos_profile, test_user.name) + + pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1) + pos_inv1.append('payments', { + 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3500 + }) + pos_inv1.submit() + + pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) + pos_inv2.append('payments', { + 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200 + }) + pos_inv2.submit() + + pcv_doc = make_closing_entry_from_opening(opening_entry) + payment = pcv_doc.payment_reconciliation[0] + + for d in pcv_doc.payment_reconciliation: + if d.mode_of_payment == 'Cash': + d.closing_amount = 6700 + + pcv_doc.submit() + + pos_inv1.load_from_db() + si_name = pos_inv1.consolidated_invoice + pcv_doc.load_from_db() pcv_doc.cancel() - si_doc.load_from_db() pos_inv1.load_from_db() - self.assertEqual(si_doc.docstatus, 2) - self.assertEqual(pos_inv1.status, 'Paid') + # After POS Closing Entry cancel, SI doc gets cancelled, unlinked and renamed + # There's no reference doc to fetch SI with new cancelled name + # which is why we are hardcoding suffix + si_docstatus = frappe.db.get_value("Sales Invoice", si_name+"-CANC-0", "docstatus") + self.assertEqual(si_docstatus, 2) + self.assertEqual(pos_inv1.status, 'Paid') + self.assertIsNone(pos_inv1.consolidated_invoice) def init_user_and_profile(**args): user = 'test@example.com' From 867939fcae12c689c145c0d8610a469508f1b900 Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 11 Aug 2021 16:40:07 +0530 Subject: [PATCH 5/6] test: fixed asset movement tests - set cwip account in company to avoid value missing - removed unused statement - removed trailing spaces --- .../test_pos_closing_entry.py | 1 - .../asset_movement/test_asset_movement.py | 19 ++++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index 0265f43476f..c585f310b16 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -103,7 +103,6 @@ class TestPOSClosingEntry(unittest.TestCase): pos_inv2.submit() pcv_doc = make_closing_entry_from_opening(opening_entry) - payment = pcv_doc.payment_reconciliation[0] for d in pcv_doc.payment_reconciliation: if d.mode_of_payment == 'Cash': diff --git a/erpnext/assets/doctype/asset_movement/test_asset_movement.py b/erpnext/assets/doctype/asset_movement/test_asset_movement.py index cddee5fa0f1..985bca9d0de 100644 --- a/erpnext/assets/doctype/asset_movement/test_asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/test_asset_movement.py @@ -15,6 +15,7 @@ from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_pu class TestAssetMovement(unittest.TestCase): def setUp(self): + frappe.db.set_value("Company", "_Test Company", "capital_work_in_progress_account", "CWIP Account - _TC") create_asset_data() make_location() @@ -45,12 +46,12 @@ class TestAssetMovement(unittest.TestCase): 'location_name': 'Test Location 2' }).insert() - movement1 = create_asset_movement(purpose = 'Transfer', company = asset.company, + movement1 = create_asset_movement(purpose = 'Transfer', company = asset.company, assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'target_location': 'Test Location 2'}], reference_doctype = 'Purchase Receipt', reference_name = pr.name) self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location 2") - movement2 = create_asset_movement(purpose = 'Transfer', company = asset.company, + movement2 = create_asset_movement(purpose = 'Transfer', company = asset.company, assets = [{ 'asset': asset.name , 'source_location': 'Test Location 2', 'target_location': 'Test Location'}], reference_doctype = 'Purchase Receipt', reference_name = pr.name) self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location") @@ -59,18 +60,18 @@ class TestAssetMovement(unittest.TestCase): self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location") employee = make_employee("testassetmovemp@example.com", company="_Test Company") - movement3 = create_asset_movement(purpose = 'Issue', company = asset.company, + movement3 = create_asset_movement(purpose = 'Issue', company = asset.company, assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'to_employee': employee}], reference_doctype = 'Purchase Receipt', reference_name = pr.name) - + # after issuing asset should belong to an employee not at a location self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), None) self.assertEqual(frappe.db.get_value("Asset", asset.name, "custodian"), employee) - + def test_last_movement_cancellation(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") - + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 @@ -85,17 +86,17 @@ class TestAssetMovement(unittest.TestCase): }) if asset.docstatus == 0: asset.submit() - + if not frappe.db.exists("Location", "Test Location 2"): frappe.get_doc({ 'doctype': 'Location', 'location_name': 'Test Location 2' }).insert() - + movement = frappe.get_doc({'doctype': 'Asset Movement', 'reference_name': pr.name }) self.assertRaises(frappe.ValidationError, movement.cancel) - movement1 = create_asset_movement(purpose = 'Transfer', company = asset.company, + movement1 = create_asset_movement(purpose = 'Transfer', company = asset.company, assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'target_location': 'Test Location 2'}], reference_doctype = 'Purchase Receipt', reference_name = pr.name) self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location 2") From 455d300fca044643eb37a78568e123a62a94ef38 Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 11 Aug 2021 17:00:46 +0530 Subject: [PATCH 6/6] Revert "test: fix POS Closing Entry Test" This reverts commit 8f1a3aef2e3f14e179f4ac91718e9f376b34198c. --- .../test_pos_closing_entry.py | 42 ++----------------- .../asset_movement/test_asset_movement.py | 4 +- 2 files changed, 6 insertions(+), 40 deletions(-) diff --git a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py index c585f310b16..b596c0cf25a 100644 --- a/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py +++ b/erpnext/accounts/doctype/pos_closing_entry/test_pos_closing_entry.py @@ -19,7 +19,6 @@ class TestPOSClosingEntry(unittest.TestCase): def tearDown(self): frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`") - frappe.db.rollback() def test_pos_closing_entry(self): test_user, pos_profile = init_user_and_profile() @@ -51,8 +50,7 @@ class TestPOSClosingEntry(unittest.TestCase): self.assertEqual(pcv_doc.total_quantity, 2) self.assertEqual(pcv_doc.net_total, 6700) - def test_cancelling_of_consolidated_sales_invoice(self): - "Check if cancelling consolidated Sales Invoice with submitted POS Closing Entry is blocked." + def test_cancelling_of_pos_closing_entry(self): test_user, pos_profile = init_user_and_profile() opening_entry = create_opening_entry(pos_profile, test_user.name) @@ -85,45 +83,13 @@ class TestPOSClosingEntry(unittest.TestCase): si_doc = frappe.get_doc("Sales Invoice", pos_inv1.consolidated_invoice) self.assertRaises(frappe.ValidationError, si_doc.cancel) - def test_cancelling_of_pos_closing_entry(self): - "Check impact of cancelling POS Closing Entry." - test_user, pos_profile = init_user_and_profile() - opening_entry = create_opening_entry(pos_profile, test_user.name) - - pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1) - pos_inv1.append('payments', { - 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3500 - }) - pos_inv1.submit() - - pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) - pos_inv2.append('payments', { - 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200 - }) - pos_inv2.submit() - - pcv_doc = make_closing_entry_from_opening(opening_entry) - - for d in pcv_doc.payment_reconciliation: - if d.mode_of_payment == 'Cash': - d.closing_amount = 6700 - - pcv_doc.submit() - - pos_inv1.load_from_db() - si_name = pos_inv1.consolidated_invoice - pcv_doc.load_from_db() pcv_doc.cancel() + si_doc.load_from_db() pos_inv1.load_from_db() - - # After POS Closing Entry cancel, SI doc gets cancelled, unlinked and renamed - # There's no reference doc to fetch SI with new cancelled name - # which is why we are hardcoding suffix - si_docstatus = frappe.db.get_value("Sales Invoice", si_name+"-CANC-0", "docstatus") - self.assertEqual(si_docstatus, 2) + self.assertEqual(si_doc.docstatus, 2) self.assertEqual(pos_inv1.status, 'Paid') - self.assertIsNone(pos_inv1.consolidated_invoice) + def init_user_and_profile(**args): user = 'test@example.com' diff --git a/erpnext/assets/doctype/asset_movement/test_asset_movement.py b/erpnext/assets/doctype/asset_movement/test_asset_movement.py index 985bca9d0de..2b2d2b44004 100644 --- a/erpnext/assets/doctype/asset_movement/test_asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/test_asset_movement.py @@ -51,7 +51,7 @@ class TestAssetMovement(unittest.TestCase): reference_doctype = 'Purchase Receipt', reference_name = pr.name) self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location 2") - movement2 = create_asset_movement(purpose = 'Transfer', company = asset.company, + create_asset_movement(purpose = 'Transfer', company = asset.company, assets = [{ 'asset': asset.name , 'source_location': 'Test Location 2', 'target_location': 'Test Location'}], reference_doctype = 'Purchase Receipt', reference_name = pr.name) self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location") @@ -60,7 +60,7 @@ class TestAssetMovement(unittest.TestCase): self.assertEqual(frappe.db.get_value("Asset", asset.name, "location"), "Test Location") employee = make_employee("testassetmovemp@example.com", company="_Test Company") - movement3 = create_asset_movement(purpose = 'Issue', company = asset.company, + create_asset_movement(purpose = 'Issue', company = asset.company, assets = [{ 'asset': asset.name , 'source_location': 'Test Location', 'to_employee': employee}], reference_doctype = 'Purchase Receipt', reference_name = pr.name)