From 956277b1210231d464b1eec98bfe9910580c3303 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 8 Jun 2018 14:05:05 +0530 Subject: [PATCH 01/21] Fix tests --- erpnext/assets/doctype/asset/asset.py | 2 + erpnext/assets/doctype/asset/test_asset.py | 62 ++++++++++++------- .../test_leave_application.py | 30 +++++++-- 3 files changed, 67 insertions(+), 27 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 6cdb550c9d..f2d8bb725b 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -24,6 +24,8 @@ class Asset(AccountsController): self.make_depreciation_schedule() self.set_accumulated_depreciation() get_depreciation_accounts(self) + else: + self.finance_books = [] if self.get("schedules"): self.validate_expected_value_after_useful_life() diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 9846ec9717..32bb8025aa 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -22,10 +22,10 @@ class TestAsset(unittest.TestCase): pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount, asset.company, asset.purchase_date) + pi.supplier = "_Test Supplier" pi.insert() pi.submit() - asset.load_from_db() self.assertEqual(asset.supplier, "_Test Supplier") self.assertEqual(asset.purchase_date, getdate("2015-01-01")) @@ -39,7 +39,6 @@ class TestAsset(unittest.TestCase): gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` where voucher_type='Purchase Invoice' and voucher_no = %s order by account""", pi.name) - self.assertEqual(gle, expected_gle) pi.cancel() @@ -54,20 +53,21 @@ class TestAsset(unittest.TestCase): def test_schedule_for_straight_line_method(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 asset.append("finance_books", { "expected_value_after_useful_life": 10000, "next_depreciation_date": "2020-12-31", "depreciation_method": "Straight Line", "total_number_of_depreciations": 3, "frequency_of_depreciation": 10, - "depreciation_start_date": add_days(nowdate(), 5) + "depreciation_start_date": "2020-06-06" }) asset.insert() self.assertEqual(asset.status, "Draft") expected_schedules = [ - ["2018-06-11", 490.20, 490.20], - ["2019-04-11", 49673.20, 50163.40], - ["2020-02-11", 39836.60, 90000.00] + ["2020-06-06", 163.93, 163.93], + ["2021-04-06", 49836.07, 50000.0], + ["2022-02-06", 40000.0, 90000.00] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -78,6 +78,7 @@ class TestAsset(unittest.TestCase): def test_schedule_for_straight_line_method_for_existing_asset(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) asset.is_existing_asset = 1 + asset.calculate_depreciation = 1 asset.number_of_depreciations_booked = 1 asset.opening_accumulated_depreciation = 40000 asset.append("finance_books", { @@ -86,14 +87,14 @@ class TestAsset(unittest.TestCase): "depreciation_method": "Straight Line", "total_number_of_depreciations": 3, "frequency_of_depreciation": 10, - "depreciation_start_date": add_days(nowdate(), 5) + "depreciation_start_date": "2020-06-06" }) asset.insert() self.assertEqual(asset.status, "Draft") asset.save() expected_schedules = [ - ["2018-06-11", 588.24, 40588.24], - ["2019-04-11", 49411.76, 90000.00] + ["2020-06-06", 197.37, 40197.37], + ["2021-04-06", 49802.63, 90000.00] ] schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] for d in asset.get("schedules")] @@ -102,22 +103,23 @@ class TestAsset(unittest.TestCase): def test_schedule_for_double_declining_method(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 asset.append("finance_books", { "expected_value_after_useful_life": 10000, "next_depreciation_date": "2020-12-31", "depreciation_method": "Double Declining Balance", "total_number_of_depreciations": 3, "frequency_of_depreciation": 10, - "depreciation_start_date": add_days(nowdate(), 5) + "depreciation_start_date": "2020-06-06" }) asset.insert() self.assertEqual(asset.status, "Draft") asset.save() expected_schedules = [ - ["2018-06-11", 66667.0, 66667.0], - ["2019-04-11", 22222.0, 88889.0], - ["2020-02-11", 1111.0, 90000.0] + ["2020-06-06", 66667.0, 66667.0], + ["2021-04-06", 22222.0, 88889.0], + ["2022-02-06", 1111.0, 90000.0] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -127,6 +129,7 @@ class TestAsset(unittest.TestCase): def test_schedule_for_double_declining_method_for_existing_asset(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 asset.is_existing_asset = 1 asset.number_of_depreciations_booked = 1 asset.opening_accumulated_depreciation = 50000 @@ -136,7 +139,7 @@ class TestAsset(unittest.TestCase): "depreciation_method": "Double Declining Balance", "total_number_of_depreciations": 3, "frequency_of_depreciation": 10, - "depreciation_start_date": add_days(nowdate(), 5) + "depreciation_start_date": "2020-06-06" }) asset.insert() self.assertEqual(asset.status, "Draft") @@ -145,8 +148,8 @@ class TestAsset(unittest.TestCase): asset.save() expected_schedules = [ - ["2018-06-11", 33333.0, 83333.0], - ["2019-04-11", 6667.0, 90000.0] + ["2020-06-06", 33333.0, 83333.0], + ["2021-04-06", 6667.0, 90000.0] ] schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] @@ -157,6 +160,7 @@ class TestAsset(unittest.TestCase): def test_schedule_for_prorated_straight_line_method(self): set_prorated_depreciation_schedule() asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 asset.is_existing_asset = 0 asset.available_for_use_date = "2020-01-30" asset.append("finance_books", { @@ -186,6 +190,7 @@ class TestAsset(unittest.TestCase): def test_depreciation(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 asset.available_for_use_date = "2020-01-30" asset.append("finance_books", { "expected_value_after_useful_life": 10000, @@ -220,6 +225,7 @@ class TestAsset(unittest.TestCase): def test_depreciation_entry_cancellation(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 asset.append("finance_books", { "expected_value_after_useful_life": 10000, "depreciation_method": "Straight Line", @@ -242,15 +248,15 @@ class TestAsset(unittest.TestCase): depr_entry = asset.get("schedules")[0].journal_entry self.assertFalse(depr_entry) - def test_scrap_asset(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 asset.append("finance_books", { "expected_value_after_useful_life": 10000, "depreciation_method": "Straight Line", "total_number_of_depreciations": 3, "frequency_of_depreciation": 10, - "depreciation_start_date": "2020-12-31" + "depreciation_start_date": "2020-06-06" }) asset.insert() asset.submit() @@ -280,6 +286,7 @@ class TestAsset(unittest.TestCase): def test_asset_sale(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 asset.append("finance_books", { "expected_value_after_useful_life": 10000, "depreciation_method": "Straight Line", @@ -320,13 +327,13 @@ class TestAsset(unittest.TestCase): def test_asset_expected_value_after_useful_life(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) - asset.depreciation_method = "Straight Line" + asset.calculate_depreciation = 1 asset.append("finance_books", { "expected_value_after_useful_life": 10000, "depreciation_method": "Straight Line", "total_number_of_depreciations": 3, "frequency_of_depreciation": 10, - "depreciation_start_date": "2020-12-31" + "depreciation_start_date": "2020-06-06" }) asset.insert() accumulated_depreciation_after_full_schedule = \ @@ -339,6 +346,17 @@ class TestAsset(unittest.TestCase): def tearDown(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + pi = [d[0] for d in frappe.db.sql(''' + select p.name from `tabPurchase Invoice` p, `tabPurchase Invoice Item` pi + where p.name = pi.parent + and pi.asset = %s + ''', (asset.name))] + if pi: + pi_doc = frappe.get_doc("Purchase Invoice", pi[0]) + print(pi[0]) + pi_doc.cancel + # if pi: + # frappe.db.set_value("Purchase Invoice", {"name": pi[0]}, "docstatus", 2) if asset.docstatus == 1 and asset.status not in ("Scrapped", "Sold", "Draft", "Cancelled"): asset.cancel() @@ -367,11 +385,11 @@ def create_asset(): "item_code": "Macbook Pro", "company": "_Test Company", "purchase_date": "2015-01-01", - "calculate_depreciation": 1, + "calculate_depreciation": 0, "gross_purchase_amount": 100000, "expected_value_after_useful_life": 10000, "warehouse": "_Test Warehouse - _TC", - "available_for_use_date": add_days(nowdate(),3), + "available_for_use_date": "2020-06-06", "location": "Test Location", "asset_owner": "Company" }) diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index 4e85074b69..a9a1a9d1c6 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -54,9 +54,12 @@ class TestLeaveApplication(unittest.TestCase): def tearDown(self): frappe.set_user("Administrator") + def _clear_roles(self): + frappe.db.sql("""delete from `tabHas Role` where parent in + ("test@example.com", "test1@example.com", "test2@example.com")""") + def _clear_applications(self): frappe.db.sql("""delete from `tabLeave Application`""") - frappe.db.sql("""delete from `tabDepartment Approver` where parentfield = 'Leave Approver'""") def get_application(self, doc): application = frappe.copy_doc(doc) @@ -65,6 +68,10 @@ class TestLeaveApplication(unittest.TestCase): return application def test_block_list(self): + self._clear_roles() + + from frappe.utils.user import add_role + add_role("test@example.com", "HR User") clear_user_permissions_for_doctype("Employee") frappe.db.set_value("Department", "_Test Department - _TC", @@ -86,8 +93,11 @@ class TestLeaveApplication(unittest.TestCase): self.assertTrue(application.insert()) def test_overlap(self): + self._clear_roles() self._clear_applications() + from frappe.utils.user import add_role + add_role("test@example.com", "Employee") frappe.set_user("test@example.com") make_allocation_record() @@ -99,8 +109,11 @@ class TestLeaveApplication(unittest.TestCase): self.assertRaises(OverlapError, application.insert) def test_overlap_with_half_day_1(self): + self._clear_roles() self._clear_applications() + from frappe.utils.user import add_role + add_role("test@example.com", "Employee") frappe.set_user("test@example.com") make_allocation_record() @@ -129,8 +142,12 @@ class TestLeaveApplication(unittest.TestCase): self.assertRaises(OverlapError, application.insert) def test_overlap_with_half_day_2(self): + self._clear_roles() self._clear_applications() + from frappe.utils.user import add_role + add_role("test@example.com", "Employee") + frappe.set_user("test@example.com") make_allocation_record() @@ -147,8 +164,12 @@ class TestLeaveApplication(unittest.TestCase): self.assertRaises(OverlapError, application.insert) def test_overlap_with_half_day_3(self): + self._clear_roles() self._clear_applications() + from frappe.utils.user import add_role + add_role("test@example.com", "Employee") + frappe.set_user("test@example.com") make_allocation_record() @@ -176,7 +197,6 @@ class TestLeaveApplication(unittest.TestCase): application.half_day_date = "2013-01-05" application.insert() - def test_optional_leave(self): leave_period = get_leave_period() today = nowdate() @@ -228,6 +248,7 @@ class TestLeaveApplication(unittest.TestCase): # check leave balance is reduced self.assertEqual(get_leave_balance_on(employee.name, leave_type, today), 9) + def test_leaves_allowed(self): employee = get_employee() leave_period = get_leave_period() @@ -412,7 +433,7 @@ def get_leave_period(): to_date = "{0}-12-31".format(now_datetime().year), company = "_Test Company", is_active = 1 - )).insert() + )).insert() def allocate_leaves(employee, leave_period, leave_type, new_leaves_allocated, eligible_leaves=0): allocate_leave = frappe.get_doc({ @@ -427,5 +448,4 @@ def allocate_leaves(employee, leave_period, leave_type, new_leaves_allocated, el "docstatus": 1 }).insert() - allocate_leave.submit() - + allocate_leave.submit() \ No newline at end of file From 3b201cc2fd2420bd9f7393a0659cb24ab3b9663a Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 8 Jun 2018 17:15:15 +0530 Subject: [PATCH 02/21] Remove python 3 stage from travis --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b8ffffbdd8..6c5afc3fac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,6 +52,4 @@ jobs: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - bench migrate - env: Patch Testing - allow_failures: - - python: "3.6" \ No newline at end of file + env: Patch Testing \ No newline at end of file From 294238abfd399fd82c2852766765d4f8ec436e2e Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 8 Jun 2018 17:15:30 +0530 Subject: [PATCH 03/21] Fix shopify test case --- erpnext/assets/doctype/asset/test_asset.py | 3 +-- .../doctype/shopify_settings/sync_product.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 32bb8025aa..e3610e1d11 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -22,7 +22,7 @@ class TestAsset(unittest.TestCase): pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount, asset.company, asset.purchase_date) - + print(pi.name) pi.supplier = "_Test Supplier" pi.insert() pi.submit() @@ -353,7 +353,6 @@ class TestAsset(unittest.TestCase): ''', (asset.name))] if pi: pi_doc = frappe.get_doc("Purchase Invoice", pi[0]) - print(pi[0]) pi_doc.cancel # if pi: # frappe.db.set_value("Purchase Invoice", {"name": pi[0]}, "docstatus", 2) diff --git a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py index 55f47a600e..ff1edea713 100644 --- a/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py +++ b/erpnext/erpnext_integrations/doctype/shopify_settings/sync_product.py @@ -216,7 +216,7 @@ def get_supplier(shopify_item): "doctype": "Supplier", "supplier_name": shopify_item.get("vendor"), "shopify_supplier_id": shopify_item.get("vendor").lower(), - "supplier_type": get_supplier_type() + "supplier_group": get_supplier_group() }).insert() return supplier.name else: @@ -224,15 +224,15 @@ def get_supplier(shopify_item): else: return "" -def get_supplier_type(): - supplier_type = frappe.db.get_value("Supplier Type", _("Shopify Supplier")) - if not supplier_type: - supplier_type = frappe.get_doc({ - "doctype": "Supplier Type", - "supplier_type": _("Shopify Supplier") +def get_supplier_group(): + supplier_group = frappe.db.get_value("Supplier Group", _("Shopify Supplier")) + if not supplier_group: + supplier_group = frappe.get_doc({ + "doctype": "Supplier Group", + "supplier_group_name": _("Shopify Supplier") }).insert() - return supplier_type.name - return supplier_type + return supplier_group.name + return supplier_group def get_item_details(shopify_item): item_details = {} From 77662eb5f4f20a986357c2ae159145098f5406e7 Mon Sep 17 00:00:00 2001 From: Shreya Date: Fri, 8 Jun 2018 17:35:49 +0530 Subject: [PATCH 04/21] Fix shopify test case --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6c5afc3fac..b8ffffbdd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,4 +52,6 @@ jobs: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - bench migrate - env: Patch Testing \ No newline at end of file + env: Patch Testing + allow_failures: + - python: "3.6" \ No newline at end of file From 664f30a018a7098e021627bdd03c9d1995cfa5c1 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sat, 9 Jun 2018 23:46:50 +0530 Subject: [PATCH 05/21] Fix asset maintenance json --- .travis.yml | 5 +- erpnext/assets/doctype/asset/test_asset.py | 3 +- .../asset_maintenance_log.json | 87 ++++++++++++------- 3 files changed, 57 insertions(+), 38 deletions(-) diff --git a/.travis.yml b/.travis.yml index b8ffffbdd8..4cfde8a679 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ dist: trusty python: - "2.7" - - "3.6" services: - mysql @@ -52,6 +51,4 @@ jobs: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - bench migrate - env: Patch Testing - allow_failures: - - python: "3.6" \ No newline at end of file + env: Patch Testing \ No newline at end of file diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index e3610e1d11..45e9c3e6f8 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe import unittest -from frappe.utils import cstr, nowdate, getdate, flt, add_days +from frappe.utils import cstr, nowdate, getdate, flt from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries, scrap_asset, restore_asset from erpnext.assets.doctype.asset.asset import make_sales_invoice, make_purchase_invoice @@ -22,7 +22,6 @@ class TestAsset(unittest.TestCase): pi = make_purchase_invoice(asset.name, asset.item_code, asset.gross_purchase_amount, asset.company, asset.purchase_date) - print(pi.name) pi.supplier = "_Test Supplier" pi.insert() pi.submit() diff --git a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json index 767097dd34..95968cffe4 100644 --- a/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json +++ b/erpnext/assets/doctype/asset_maintenance_log/asset_maintenance_log.json @@ -15,6 +15,7 @@ "fields": [ { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -42,11 +43,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -74,16 +76,17 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "asset_maintenance.asset_name", + "fetch_from": "asset_maintenance.asset_name", "fieldname": "asset_name", "fieldtype": "Read Only", "hidden": 0, @@ -107,11 +110,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -137,16 +141,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "asset_maintenance.item_code", + "fetch_from": "asset_maintenance.item_code", "fieldname": "item_code", "fieldtype": "Read Only", "hidden": 0, @@ -170,16 +175,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "asset_maintenance.item_name", + "fetch_from": "asset_maintenance.item_name", "fieldname": "item_name", "fieldtype": "Read Only", "hidden": 0, @@ -203,11 +209,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -233,11 +240,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -265,16 +273,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "task.maintenance_type", + "fetch_from": "task.maintenance_type", "fieldname": "maintenance_type", "fieldtype": "Read Only", "hidden": 0, @@ -298,16 +307,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "task.periodicity", + "fetch_from": "task.periodicity", "fieldname": "periodicity", "fieldtype": "Data", "hidden": 0, @@ -331,16 +341,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "task.assign_to_name", + "fetch_from": "task.assign_to_name", "fieldname": "assign_to_name", "fieldtype": "Read Only", "hidden": 0, @@ -364,11 +375,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -394,11 +406,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -427,11 +440,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -458,11 +472,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -490,11 +505,12 @@ "reqd": 1, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -520,16 +536,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "task.has_certificate", + "fetch_from": "task.certificate_required", "fieldname": "has_certificate", "fieldtype": "Check", "hidden": 0, @@ -553,11 +570,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -585,11 +603,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -615,16 +634,17 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "task.description", + "fetch_from": "task.description", "fieldname": "description", "fieldtype": "Read Only", "hidden": 0, @@ -648,11 +668,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -678,11 +699,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 1, "bold": 0, "collapsible": 0, @@ -709,11 +731,12 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 }, { "allow_bulk_edit": 0, + "allow_in_quick_entry": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -741,7 +764,7 @@ "reqd": 0, "search_index": 0, "set_only_once": 0, - "translatable": 0, + "translatable": 0, "unique": 0 } ], @@ -755,7 +778,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-05-25 22:43:39.866477", + "modified": "2018-06-09 23:45:55.492528", "modified_by": "Administrator", "module": "Assets", "name": "Asset Maintenance Log", From 83d5dc119b053040bdc3e867ce138e1acf7076d8 Mon Sep 17 00:00:00 2001 From: Shreya Date: Sun, 10 Jun 2018 00:38:30 +0530 Subject: [PATCH 06/21] Fix Employee tax declaration test case --- ...test_employee_tax_exemption_declaration.py | 31 +++++++++++-------- .../test_leave_application.py | 2 +- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py b/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py index dff02eac14..8974c36b5b 100644 --- a/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py +++ b/erpnext/hr/doctype/employee_tax_exemption_declaration/test_employee_tax_exemption_declaration.py @@ -8,7 +8,7 @@ import unittest from erpnext.hr.doctype.salary_structure.test_salary_structure import make_employee class TestEmployeeTaxExemptionDeclaration(unittest.TestCase): - def setup(self): + def setUp(self): make_employee("employee@taxexepmtion.com") make_employee("employee1@taxexepmtion.com") create_payroll_period() @@ -19,7 +19,7 @@ class TestEmployeeTaxExemptionDeclaration(unittest.TestCase): declaration = frappe.get_doc({ "doctype": "Employee Tax Exemption Declaration", "employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"), - "payroll_period": "Test Payroll Period", + "payroll_period": "_Test Payroll Period", "declarations": [dict(exemption_sub_category = "_Test Sub Category", exemption_category = "_Test Category", amount = 150000)] @@ -27,7 +27,7 @@ class TestEmployeeTaxExemptionDeclaration(unittest.TestCase): self.assertRaises(frappe.ValidationError, declaration.save) declaration = frappe.get_doc({ "doctype": "Employee Tax Exemption Declaration", - "payroll_period": "Test Payroll Period", + "payroll_period": "_Test Payroll Period", "employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"), "declarations": [dict(exemption_sub_category = "_Test Sub Category", exemption_category = "_Test Category", @@ -39,7 +39,8 @@ class TestEmployeeTaxExemptionDeclaration(unittest.TestCase): declaration = frappe.get_doc({ "doctype": "Employee Tax Exemption Declaration", "employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"), - "payroll_period": "Test Payroll Period", + "company": "_Test Company", + "payroll_period": "_Test Payroll Period", "declarations": [dict(exemption_sub_category = "_Test Sub Category", exemption_category = "_Test Category", amount = 100000), @@ -54,7 +55,8 @@ class TestEmployeeTaxExemptionDeclaration(unittest.TestCase): declaration = frappe.get_doc({ "doctype": "Employee Tax Exemption Declaration", "employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"), - "payroll_period": "Test Payroll Period", + "company": "_Test Company", + "payroll_period": "_Test Payroll Period", "declarations": [dict(exemption_sub_category = "_Test Sub Category", exemption_category = "_Test Category", amount = 100000), @@ -62,17 +64,18 @@ class TestEmployeeTaxExemptionDeclaration(unittest.TestCase): exemption_category = "_Test Category", amount = 50000), ] - }) + }).insert() self.assertTrue(declaration.submit) duplicate_declaration = frappe.get_doc({ "doctype": "Employee Tax Exemption Declaration", "employee": frappe.get_value("Employee", {"user_id":"employee@taxexepmtion.com"}, "name"), - "payroll_period": "Test Payroll Period", + "company": "_Test Company", + "payroll_period": "_Test Payroll Period", "declarations": [dict(exemption_sub_category = "_Test Sub Category", exemption_category = "_Test Category", amount = 100000) ] - }) + }).insert() self.assertRaises(frappe.DocstatusTransitionError, duplicate_declaration.submit) duplicate_declaration.employee = frappe.get_value("Employee", {"user_id":"employee1@taxexepmtion.com"}, "name") self.assertTrue(duplicate_declaration.submit) @@ -93,20 +96,22 @@ def create_exemption_category(): category = frappe.get_doc({ "doctype": "Employee Tax Exemption Category", "name": "_Test Category", - "deduction_component": "_Test Tax", + "deduction_component": "Income Tax", "max_amount": 100000 }).insert() - if not frappe.db.exists("Employee Tax Exemption Sub Category", "_Test Category"): + if not frappe.db.exists("Employee Tax Exemption Sub Category", "_Test Sub Category"): frappe.get_doc({ "doctype": "Employee Tax Exemption Sub Category", "name": "_Test Sub Category", "exemption_category": "_Test Category", - "max_amount": 100000 + "max_amount": 100000, + "is_active": 1 }).insert() - if not frappe.db.exists("Employee Tax Exemption Sub Category", "_Test Category"): + if not frappe.db.exists("Employee Tax Exemption Sub Category", "_Test1 Sub Category"): frappe.get_doc({ "doctype": "Employee Tax Exemption Sub Category", "name": "_Test1 Sub Category", "exemption_category": "_Test Category", - "max_amount": 50000 + "max_amount": 50000, + "is_active": 1 }).insert() diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index a9a1a9d1c6..1532e8534b 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -433,7 +433,7 @@ def get_leave_period(): to_date = "{0}-12-31".format(now_datetime().year), company = "_Test Company", is_active = 1 - )).insert() + )).insert() def allocate_leaves(employee, leave_period, leave_type, new_leaves_allocated, eligible_leaves=0): allocate_leave = frappe.get_doc({ From 86026d31cfa499f6e7ac82428449754e71795818 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 11 Jun 2018 14:10:52 +0530 Subject: [PATCH 07/21] [Fix] Alternative item, transferred qty issue for backflush method --- erpnext/manufacturing/doctype/work_order/work_order.py | 7 +++++-- erpnext/stock/doctype/stock_entry/stock_entry.py | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index d10fd21a6c..1624bb989c 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -554,12 +554,15 @@ class WorkOrder(Document): consumed_qty = frappe.db.sql('''select sum(qty) from `tabStock Entry` entry, `tabStock Entry Detail` detail where - entry.work_order = %s + entry.work_order = %(name)s and (entry.purpose = "Material Consumption for Manufacture" or entry.purpose = "Manufacture") and entry.docstatus = 1 and detail.parent = entry.name - and detail.item_code = %s''', (self.name, d.item_code))[0][0] + and (detail.item_code = %(item)s or detail.original_item = %(item)s)''', { + 'name': self.name, + 'item': d.item_code + })[0][0] d.db_set('consumed_qty', flt(consumed_qty), update_modified = False) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 586e21de40..eed401626e 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -832,7 +832,7 @@ class StockEntry(StockController): def get_transfered_raw_materials(self): transferred_materials = frappe.db.sql(""" select - item_name, item_code, sum(qty) as qty, sed.t_warehouse as warehouse, + item_name, original_item, item_code, sum(qty) as qty, sed.t_warehouse as warehouse, description, stock_uom, expense_account, cost_center from `tabStock Entry` se,`tabStock Entry Detail` sed where @@ -866,8 +866,9 @@ class StockEntry(StockController): for item in transferred_materials: qty= item.qty + item_code = item.original_item or item.item_code req_items = frappe.get_all('Work Order Item', - filters={'parent': self.work_order, 'item_code': item.item_code}, + filters={'parent': self.work_order, 'item_code': item_code}, fields=["required_qty", "consumed_qty"] ) req_qty = flt(req_items[0].required_qty) @@ -912,6 +913,7 @@ class StockEntry(StockController): "stock_uom": item.stock_uom, "expense_account": item.expense_account, "cost_center": item.buying_cost_center, + "original_item": item.original_item } }) @@ -986,6 +988,7 @@ class StockEntry(StockController): se_child.cost_center = item_dict[d].get("cost_center") or cost_center se_child.allow_alternative_item = item_dict[d].get("allow_alternative_item", 0) se_child.subcontracted_item = item_dict[d].get("main_item_code") + se_child.original_item = item_dict[d].get("original_item") if item_dict[d].get("idx"): se_child.idx = item_dict[d].get("idx") From 061492a9af76edafcc94584c6476fec7c957216f Mon Sep 17 00:00:00 2001 From: Kenneth Sequeira <33246109+kennethsequeira@users.noreply.github.com> Date: Mon, 11 Jun 2018 14:24:19 +0530 Subject: [PATCH 08/21] Fix minor div issue in Accounts --- erpnext/docs/user/manual/en/accounts/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/docs/user/manual/en/accounts/index.md b/erpnext/docs/user/manual/en/accounts/index.md index 531775e0e7..7fec54ebb1 100644 --- a/erpnext/docs/user/manual/en/accounts/index.md +++ b/erpnext/docs/user/manual/en/accounts/index.md @@ -10,7 +10,7 @@ In ERPNext, your accounting operations consists of 3 main transactions: * Purchase Invoice: Bills that your Suppliers give you for their products or services. * Journal Entries: For accounting entries, like payments, credit and other types. -
+
From 9680dc476f55980ada1d767e56aa3180d86d8f9e Mon Sep 17 00:00:00 2001 From: Shreya Date: Mon, 11 Jun 2018 15:40:09 +0530 Subject: [PATCH 09/21] Remove commented code --- erpnext/assets/doctype/asset/test_asset.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 45e9c3e6f8..3f706f8b64 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -345,17 +345,6 @@ class TestAsset(unittest.TestCase): def tearDown(self): asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) - pi = [d[0] for d in frappe.db.sql(''' - select p.name from `tabPurchase Invoice` p, `tabPurchase Invoice Item` pi - where p.name = pi.parent - and pi.asset = %s - ''', (asset.name))] - if pi: - pi_doc = frappe.get_doc("Purchase Invoice", pi[0]) - pi_doc.cancel - # if pi: - # frappe.db.set_value("Purchase Invoice", {"name": pi[0]}, "docstatus", 2) - if asset.docstatus == 1 and asset.status not in ("Scrapped", "Sold", "Draft", "Cancelled"): asset.cancel() From 0ca76323af5efea64cc0e3033b43437b6d2eb770 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Mon, 11 Jun 2018 17:25:49 +0530 Subject: [PATCH 10/21] Clinical Procedure Template - get_item_details - fix (#14449) --- .../clinical_procedure_template.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py index 565fe9021d..90bf95770f 100644 --- a/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py +++ b/erpnext/healthcare/doctype/clinical_procedure_template/clinical_procedure_template.py @@ -33,8 +33,8 @@ class ClinicalProcedureTemplate(Document): frappe.throw("""Not permitted. Please disable the Procedure Template""") def get_item_details(self, args=None): - item = frappe.db.sql("""select stock_uom, description, image, item_name, - expense_account, buying_cost_center, item_group from `tabItem` + item = frappe.db.sql("""select stock_uom, item_name + from `tabItem` where name = %s and disabled=0 and (end_of_life is null or end_of_life='0000-00-00' or end_of_life > %s)""", From 157815ff0c1028dad4cd907e609ab789f3c9b4f3 Mon Sep 17 00:00:00 2001 From: Shreya Shah Date: Mon, 11 Jun 2018 17:32:17 +0530 Subject: [PATCH 11/21] Patch for total quantity (#14458) * Add path to patches.txt * Modify patch --- erpnext/patches.txt | 3 ++- .../patches/v11_0/update_total_qty_field.py | 27 ++++++++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 658b7e7795..eb29528ac7 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -546,4 +546,5 @@ erpnext.patches.v11_0.update_backflush_subcontract_rm_based_on_bom erpnext.patches.v10_0.update_status_in_purchase_receipt erpnext.patches.v11_0.inter_state_field_for_gst erpnext.patches.v11_0.rename_members_with_naming_series #04-06-2018 -erpnext.patches.v11_0.set_update_field_and_value_in_workflow_state \ No newline at end of file +erpnext.patches.v11_0.set_update_field_and_value_in_workflow_state +erpnext.patches.v11_0.update_total_qty_field diff --git a/erpnext/patches/v11_0/update_total_qty_field.py b/erpnext/patches/v11_0/update_total_qty_field.py index e618593a54..6f78d8a77f 100644 --- a/erpnext/patches/v11_0/update_total_qty_field.py +++ b/erpnext/patches/v11_0/update_total_qty_field.py @@ -9,19 +9,26 @@ def execute(): frappe.reload_doc('stock', 'doctype', 'purchase_receipt') frappe.reload_doc('accounts', 'doctype', 'sales_invoice') frappe.reload_doc('accounts', 'doctype', 'purchase_invoice') - + doctypes = ["Sales Order", "Sales Invoice", "Delivery Note",\ "Purchase Order", "Purchase Invoice", "Purchase Receipt", "Quotation", "Supplier Quotation"] for doctype in doctypes: + total_qty = frappe.db.sql(''' + SELECT + parent, SUM(qty) as qty + FROM + `tab%s Item` + GROUP BY parent + ''' % (doctype), as_dict = True) + + when_then = [] + for d in total_qty: + when_then.append(""" + when dt.name = '{0}' then {1} + """.format(frappe.db.escape(d.get("parent")), d.get("qty"))) + frappe.db.sql(''' UPDATE - `tab%s` dt SET dt.total_qty = - ( - SELECT SUM(dt_item.qty) - FROM - `tab%s Item` dt_item - WHERE - dt_item.parent=dt.name - ) - ''' % (doctype, doctype)) + `tab%s` dt SET dt.total_qty = CASE %s END + ''' % (doctype, " ".join(when_then))) \ No newline at end of file From fde28a284ea7339ed031d92fb44c19e4e3e9ad3d Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Mon, 11 Jun 2018 18:07:49 +0530 Subject: [PATCH 12/21] Update .travis.yml --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4cfde8a679..9bca4270ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -44,11 +44,11 @@ jobs: - stage: test script: - set -e - - bench run-tests + - bench run-tests --app erpnext env: Server Side Test - # stage script: - wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz - bench --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz --mariadb-root-password travis - bench migrate - env: Patch Testing \ No newline at end of file + env: Patch Testing From 647d595158ff8a4076261b2e30ecc4a55bc557c8 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 11 Jun 2018 18:53:55 +0530 Subject: [PATCH 13/21] Code cleanup and fixes for the asset --- .../purchase_invoice/purchase_invoice.py | 23 +++++++------ erpnext/assets/doctype/asset/asset.py | 32 ++++++++++++------- .../doctype/asset_movement/asset_movement.js | 2 +- .../asset_movement/asset_movement.json | 4 +-- .../doctype/asset_movement/asset_movement.py | 2 +- erpnext/controllers/buying_controller.py | 3 +- erpnext/stock/doctype/item/item.json | 4 +-- .../purchase_receipt/purchase_receipt.py | 17 +++++----- erpnext/stock/doctype/serial_no/serial_no.py | 2 ++ 9 files changed, 49 insertions(+), 40 deletions(-) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 0242d60a5f..697611d961 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -16,11 +16,11 @@ from erpnext.accounts.general_ledger import make_gl_entries, merge_similar_entri from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt from erpnext.buying.utils import check_for_closed_status from erpnext.accounts.general_ledger import get_round_off_account_and_cost_center +from erpnext.assets.doctype.asset.asset import get_asset_account from frappe.model.mapper import get_mapped_doc from six import iteritems from erpnext.accounts.doctype.sales_invoice.sales_invoice import validate_inter_company_party, update_linked_invoice,\ unlink_inter_company_invoice -from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -474,17 +474,16 @@ class PurchaseInvoice(BuyingController): def get_asset_gl_entry(self, gl_entries): for item in self.get("items"): if item.is_fixed_asset: - asset_accounts = self.get_company_default(["asset_received_but_not_billed", - "expenses_included_in_asset_valuation", "capital_work_in_progress_account"]) + eiiav_account = self.get_company_default("expenses_included_in_asset_valuation") asset_amount = flt(item.net_amount) + flt(item.item_tax_amount/self.conversion_rate) base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) - item.expense_account = item.expense_account or asset_accounts[0] + item.expense_account = item.expense_account if (not item.expense_account or frappe.db.get_value('Account', item.expense_account, 'account_type') != 'Asset Received But Not Billed'): - frappe.throw(_("Row {0}: Expense account must be of type Asset Received But Not Billed"). - format(item.idx)) + arbnb_account = self.get_company_default("asset_received_but_not_billed") + item.expense_account = arbnb_account if not self.update_stock: asset_rbnb_currency = get_account_currency(item.expense_account) @@ -498,9 +497,9 @@ class PurchaseInvoice(BuyingController): })) if item.item_tax_amount: - asset_eiiav_currency = get_account_currency(asset_accounts[0]) + asset_eiiav_currency = get_account_currency(eiiav_account) gl_entries.append(self.get_gl_dict({ - "account": asset_accounts[1], + "account": eiiav_account, "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "cost_center": item.cost_center, @@ -510,8 +509,8 @@ class PurchaseInvoice(BuyingController): item.item_tax_amount / self.conversion_rate) })) else: - cwip_account = get_asset_category_account(item.asset, - 'capital_work_in_progress_account') or asset_accounts[2] + cwip_account = get_asset_account("capital_work_in_progress_account", + item.asset, company = self.company) cwip_account_currency = get_account_currency(cwip_account) gl_entries.append(self.get_gl_dict({ @@ -524,9 +523,9 @@ class PurchaseInvoice(BuyingController): })) if item.item_tax_amount and not cint(erpnext.is_perpetual_inventory_enabled(self.company)): - asset_eiiav_currency = get_account_currency(asset_accounts[1]) + asset_eiiav_currency = get_account_currency(eiiav_account) gl_entries.append(self.get_gl_dict({ - "account": asset_accounts[1], + "account": eiiav_account, "against": self.supplier, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "cost_center": item.cost_center, diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index f2d8bb725b..247dc10972 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -10,7 +10,7 @@ from frappe.model.document import Document from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account from erpnext.assets.doctype.asset.depreciation \ import get_disposal_account_and_cost_center, get_depreciation_accounts -from erpnext.accounts.general_ledger import make_gl_entries +from erpnext.accounts.general_ledger import make_gl_entries, delete_gl_entries from erpnext.accounts.utils import get_account_currency from erpnext.controllers.accounts_controller import AccountsController @@ -33,11 +33,15 @@ class Asset(AccountsController): self.validate_in_use_date() self.set_status() self.update_stock_movement() + if not self.booked_fixed_asset: + self.make_gl_entries() def on_cancel(self): self.validate_cancellation() self.delete_depreciation_entries() self.set_status() + delete_gl_entries() + self.db_set('booked_fixed_asset', 0) def validate_item(self): item = frappe.db.get_value("Item", self.item_code, @@ -325,12 +329,14 @@ class Asset(AccountsController): doc.submit() def make_gl_entries(self): - if self.purchase_receipt and self.purchase_receipt_amount: + if self.purchase_receipt and self.purchase_receipt_amount and self.available_for_use_date <= nowdate(): from erpnext.accounts.general_ledger import make_gl_entries gl_entries = [] - cwip_account = get_cwip_account(self.name, self.asset_category, self.company) + cwip_account = get_asset_account("capital_work_in_progress_account", + self.name, self.asset_category, self.company) + fixed_aseet_account = get_asset_category_account(self.name, 'fixed_asset_account', asset_category = self.asset_category, company = self.company) @@ -471,15 +477,17 @@ def get_item_details(item_code, asset_category=None): return books -def get_cwip_account(asset, asset_category=None, company=None): - cwip_account = get_asset_category_account(asset, 'capital_work_in_progress_account', - asset_category = asset_category, company = company) +def get_asset_account(account_name, asset=None, asset_category=None, company=None): + account = None + if asset: + account = get_asset_category_account(asset, account_name, + asset_category = asset_category, company = company) - if not cwip_account: - cwip_account = frappe.db.get_value('Company', company, 'capital_work_in_progress_account') + if not account: + account = frappe.db.get_value('Company', company, account_name) - if not cwip_account: - frappe.throw(_("Set Capital Work In Progress Account in asset category {0} or company {1}") - .format(asset_category, company)) + if not account: + frappe.throw(_("Set {0} in asset category {1} or company {2}") + .format(account_name.replace('_', ' ').title(), asset_category, company)) - return cwip_account + return account diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.js b/erpnext/assets/doctype/asset_movement/asset_movement.js index 358b64d850..739a3c849d 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.js +++ b/erpnext/assets/doctype/asset_movement/asset_movement.js @@ -3,6 +3,6 @@ frappe.ui.form.on('Asset Movement', { onload: function(frm) { - + // } }); diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.json b/erpnext/assets/doctype/asset_movement/asset_movement.json index e82a5f0510..64c7f4abb7 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.json +++ b/erpnext/assets/doctype/asset_movement/asset_movement.json @@ -277,7 +277,7 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fetch_from": "asset.location", + "fetch_from": "", "fieldname": "source_location", "fieldtype": "Link", "hidden": 0, @@ -575,7 +575,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2018-06-06 06:21:36.607432", + "modified": "2018-06-11 18:42:55.381972", "modified_by": "Administrator", "module": "Assets", "name": "Asset Movement", diff --git a/erpnext/assets/doctype/asset_movement/asset_movement.py b/erpnext/assets/doctype/asset_movement/asset_movement.py index 638987ee96..a89b312732 100644 --- a/erpnext/assets/doctype/asset_movement/asset_movement.py +++ b/erpnext/assets/doctype/asset_movement/asset_movement.py @@ -31,7 +31,7 @@ class AssetMovement(Document): if self.purpose in ['Transfer', 'Issue']: self.source_location = frappe.db.get_value("Asset", self.asset, "location") - if self.source_location == self.target_location: + if self.source_location == self.target_location and self.purpose == 'Transfer': frappe.throw(_("Source and Target Location cannot be same")) def on_submit(self): diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index c1df2b5b79..6507513e64 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -558,7 +558,8 @@ class BuyingController(StockController): 'actual_qty': d.qty, 'purchase_document_type': self.doctype, 'purchase_document_no': self.name, - 'asset': d.asset + 'asset': d.asset, + 'location': d.asset_location }) d.db_set('serial_no', serial_nos) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index b7c90d0fdd..050a032e55 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -1223,7 +1223,7 @@ "collapsible": 1, "collapsible_depends_on": "eval:doc.has_batch_no || doc.has_serial_no || doc.is_fixed_asset", "columns": 0, - "depends_on": "is_stock_item", + "depends_on": "eval:doc.is_stock_item || doc.is_fixed_asset", "fieldname": "serial_nos_and_batches", "fieldtype": "Section Break", "hidden": 0, @@ -3918,7 +3918,7 @@ "issingle": 0, "istable": 0, "max_attachments": 1, - "modified": "2018-05-28 14:18:03.234070", + "modified": "2018-06-11 17:11:55.458770", "modified_by": "Administrator", "module": "Stock", "name": "Item", diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index fa441b5103..5c370d3bec 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -13,8 +13,8 @@ from erpnext.controllers.buying_controller import BuyingController from erpnext.accounts.utils import get_account_currency from frappe.desk.notifications import clear_doctype_notifications from erpnext.buying.utils import check_for_closed_status +from erpnext.assets.doctype.asset.asset import get_asset_account from six import iteritems -from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account form_grid_templates = { "items": "templates/form_grid/item_grid.html" @@ -314,12 +314,11 @@ class PurchaseReceipt(BuyingController): def get_asset_gl_entry(self, gl_entries): for d in self.get("items"): if d.is_fixed_asset: - asset_accounts = self.get_company_default(["capital_work_in_progress_account", - "asset_received_but_not_billed"]) + arbnb_account = self.get_company_default("asset_received_but_not_billed") # CWIP entry - cwip_account = get_asset_category_account(d.asset, - 'capital_work_in_progress_account') or asset_accounts[0] + cwip_account = get_asset_account("capital_work_in_progress_account", d.asset, + company = self.company) asset_amount = flt(d.net_amount) + flt(d.item_tax_amount/self.conversion_rate) base_asset_amount = flt(d.base_net_amount + d.item_tax_amount) @@ -327,7 +326,7 @@ class PurchaseReceipt(BuyingController): cwip_account_currency = get_account_currency(cwip_account) gl_entries.append(self.get_gl_dict({ "account": cwip_account, - "against": asset_accounts[1], + "against": arbnb_account, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "debit": base_asset_amount, @@ -336,10 +335,10 @@ class PurchaseReceipt(BuyingController): })) # Asset received but not billed - asset_rbnb_currency = get_account_currency(asset_accounts[1]) + asset_rbnb_currency = get_account_currency(arbnb_account) gl_entries.append(self.get_gl_dict({ - "account": asset_accounts[1], - "against": asset_accounts[0], + "account": arbnb_account, + "against": cwip_account, "cost_center": d.cost_center, "remarks": self.get("remarks") or _("Accounting Entry for Asset"), "credit": base_asset_amount, diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 67871c3ba9..fb33adc892 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -306,6 +306,7 @@ def auto_make_serial_nos(args): sr.via_stock_ledger = True sr.item_code = args.get('item_code') sr.warehouse = args.get('warehouse') if args.get('actual_qty', 0) > 0 else None + sr.location = args.get('location') sr.save(ignore_permissions=True) elif args.get('actual_qty', 0) > 0: make_serial_no(serial_no, args) @@ -330,6 +331,7 @@ def make_serial_no(serial_no, args): sr.company = args.get('company') sr.via_stock_ledger = args.get('via_stock_ledger') or True sr.asset = args.get('asset') + sr.location = args.get('location') if args.get('purchase_document_type'): sr.purchase_document_type = args.get('purchase_document_type') From f226b50d6db49aaa90639837e7e33432736a9388 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Mon, 11 Jun 2018 19:27:46 +0530 Subject: [PATCH 14/21] fix the salary slip test cases --- erpnext/hr/doctype/salary_slip/salary_slip.py | 7 +++++-- erpnext/hr/doctype/salary_slip/test_salary_slip.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 24ecf26a66..dc2446ba35 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -447,7 +447,7 @@ class SalarySlip(TransactionBase): else: self.set_status() self.update_status(self.name) - if(frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry: + if (frappe.db.get_single_value("HR Settings", "email_salary_slip_to_employee")) and not frappe.flags.via_payroll_entry: self.email_salary_slip() def on_cancel(self): @@ -466,7 +466,10 @@ class SalarySlip(TransactionBase): "reference_doctype": self.doctype, "reference_name": self.name } - enqueue(method=frappe.sendmail, queue='short', timeout=300, async=True, **email_args) + if not frappe.flags.in_test: + enqueue(method=frappe.sendmail, queue='short', timeout=300, async=True, **email_args) + else: + frappe.sendmail(**email_args) else: msgprint(_("{0}: Employee email not found, hence email not sent").format(self.employee_name)) diff --git a/erpnext/hr/doctype/salary_slip/test_salary_slip.py b/erpnext/hr/doctype/salary_slip/test_salary_slip.py index b10df8bf9c..95be748b7e 100644 --- a/erpnext/hr/doctype/salary_slip/test_salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/test_salary_slip.py @@ -279,7 +279,7 @@ def make_salary_structure(sal_struct, payroll_frequency, employee): "payroll_frequency": payroll_frequency, "payment_account": get_random("Account") }).insert() - create_salary_structure_assignment(employee, salary_structure) + create_salary_structure_assignment(employee, salary_structure.name) elif not frappe.db.get_value("Salary Structure Assignment",{'salary_structure':sal_struct, 'employee':employee},'name'): create_salary_structure_assignment(employee, sal_struct) From ec2a2ac47e655261a42cb80c73188e42f53c164c Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 12 Jun 2018 01:16:28 +0530 Subject: [PATCH 15/21] [Fix] patch --- erpnext/patches/v11_0/update_total_qty_field.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/patches/v11_0/update_total_qty_field.py b/erpnext/patches/v11_0/update_total_qty_field.py index 6f78d8a77f..c5d27d25d0 100644 --- a/erpnext/patches/v11_0/update_total_qty_field.py +++ b/erpnext/patches/v11_0/update_total_qty_field.py @@ -28,7 +28,8 @@ def execute(): when dt.name = '{0}' then {1} """.format(frappe.db.escape(d.get("parent")), d.get("qty"))) - frappe.db.sql(''' - UPDATE - `tab%s` dt SET dt.total_qty = CASE %s END - ''' % (doctype, " ".join(when_then))) \ No newline at end of file + if when_then: + frappe.db.sql(''' + UPDATE + `tab%s` dt SET dt.total_qty = CASE %s END + ''' % (doctype, " ".join(when_then))) \ No newline at end of file From 65b55a53a6da9ce74c70974de1a83513b277dc73 Mon Sep 17 00:00:00 2001 From: Manas Solanki Date: Tue, 12 Jun 2018 11:18:01 +0530 Subject: [PATCH 16/21] Update test_leave_application.py --- .../hr/doctype/leave_application/test_leave_application.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.py b/erpnext/hr/doctype/leave_application/test_leave_application.py index 1532e8534b..db46856fed 100644 --- a/erpnext/hr/doctype/leave_application/test_leave_application.py +++ b/erpnext/hr/doctype/leave_application/test_leave_application.py @@ -369,7 +369,7 @@ class TestLeaveApplication(unittest.TestCase): employee = get_employee() leave_type = 'Test Earned Leave Type' if not frappe.db.exists('Leave Type', leave_type): - leave_type = frappe.get_doc(dict( + leave_type_doc = frappe.get_doc(dict( leave_type_name = leave_type, doctype = 'Leave Type', is_earned_leave = 1, @@ -448,4 +448,4 @@ def allocate_leaves(employee, leave_period, leave_type, new_leaves_allocated, el "docstatus": 1 }).insert() - allocate_leave.submit() \ No newline at end of file + allocate_leave.submit() From 8d66f1e45da049e86757fe4d54c0f7bfadae5275 Mon Sep 17 00:00:00 2001 From: Jamsheer Date: Tue, 12 Jun 2018 11:30:59 +0530 Subject: [PATCH 17/21] Employee benefit - Late employee benefit application (#14465) * HR Utils - get salary slip total benefit given for a payroll period * Late employee benefit application * Additional Salary - code refactor - get_amount * new line in salary detail json * Employee benefit late application - validation refactor * Codacy fix --- .../additional_salary/additional_salary.py | 10 +--- .../employee_benefit_application.js | 58 ++++++++++++++----- .../employee_benefit_application.py | 25 +++++--- .../employee_benefit_claim.py | 2 + .../doctype/salary_detail/salary_detail.json | 2 +- erpnext/hr/doctype/salary_slip/salary_slip.py | 3 +- erpnext/hr/utils.py | 28 +++++++++ 7 files changed, 95 insertions(+), 33 deletions(-) diff --git a/erpnext/hr/doctype/additional_salary/additional_salary.py b/erpnext/hr/doctype/additional_salary/additional_salary.py index 7482c8b0f8..dfa22d7d2f 100644 --- a/erpnext/hr/doctype/additional_salary/additional_salary.py +++ b/erpnext/hr/doctype/additional_salary/additional_salary.py @@ -25,11 +25,6 @@ class AdditionalSalary(Document): frappe.throw(_("To date can not greater than employee's relieving date")) def get_amount(self, sal_start_date, sal_end_date): - # If additional salary dates in between the salary slip dates - # then return complete additional salary amount - if getdate(sal_start_date) <= getdate(self.from_date) <= getdate(sal_end_date)\ - and getdate(sal_end_date) >= getdate(self.to_date) >= getdate(sal_start_date): - return self.amount start_date = getdate(sal_start_date) end_date = getdate(sal_end_date) total_days = date_diff(getdate(self.to_date), getdate(self.from_date)) + 1 @@ -38,12 +33,9 @@ class AdditionalSalary(Document): start_date = getdate(self.from_date) if getdate(sal_end_date) > getdate(self.to_date): end_date = getdate(self.to_date) - no_of_days = date_diff(getdate(end_date), getdate(start_date)) + no_of_days = date_diff(getdate(end_date), getdate(start_date)) + 1 return amount_per_day * no_of_days - - - @frappe.whitelist() def get_additional_salary_component(employee, start_date, end_date): additional_components = frappe.db.sql(""" diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js index f96f2629c3..b63c76f4b3 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.js @@ -11,25 +11,53 @@ frappe.ui.form.on('Employee Benefit Application', { }); }, employee: function(frm) { - if(frm.doc.employee && frm.doc.date){ - frappe.call({ - method: "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits", - args:{ - employee: frm.doc.employee, - on_date: frm.doc.date - }, - callback: function (data) { - if(!data.exc){ - if(data.message){ - frm.set_value("max_benefits", data.message); - } - } - } - }); + var method, args; + if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){ + method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining"; + args = { + employee: frm.doc.employee, + on_date: frm.doc.date, + payroll_period: frm.doc.payroll_period + }; + get_max_benefits(frm, method, args); + } + else if(frm.doc.employee && frm.doc.date){ + method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits"; + args = { + employee: frm.doc.employee, + on_date: frm.doc.date + }; + get_max_benefits(frm, method, args); + } + }, + payroll_period: function(frm) { + var method, args; + if(frm.doc.employee && frm.doc.date && frm.doc.payroll_period){ + method = "erpnext.hr.doctype.employee_benefit_application.employee_benefit_application.get_max_benefits_remaining"; + args = { + employee: frm.doc.employee, + on_date: frm.doc.date, + payroll_period: frm.doc.payroll_period + }; + get_max_benefits(frm, method, args); } } }); +var get_max_benefits=function(frm, method, args) { + frappe.call({ + method: method, + args: args, + callback: function (data) { + if(!data.exc){ + if(data.message){ + frm.set_value("max_benefits", data.message); + } + } + } + }); +}; + frappe.ui.form.on("Employee Benefit Application Detail",{ amount: function(frm) { calculate_all(frm.doc); diff --git a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py index 2d33ce843a..ed54fb828f 100644 --- a/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py +++ b/erpnext/hr/doctype/employee_benefit_application/employee_benefit_application.py @@ -5,10 +5,11 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import date_diff, getdate +from frappe.utils import date_diff, getdate, rounded from frappe.model.document import Document from erpnext.hr.doctype.payroll_period.payroll_period import get_payroll_period_days from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment import get_assigned_salary_structure +from erpnext.hr.utils import get_sal_slip_total_benefit_given class EmployeeBenefitApplication(Document): def validate(self): @@ -41,9 +42,10 @@ class EmployeeBenefitApplication(Document): pro_rata_amount += max_benefit_amount else: non_pro_rata_amount += max_benefit_amount + if pro_rata_amount == 0 and non_pro_rata_amount == 0: frappe.throw(_("Please add the remainig benefits {0} to any of the existing component").format(self.remainig_benefits)) - elif non_pro_rata_amount > 0 and non_pro_rata_amount < self.remainig_benefits: + elif non_pro_rata_amount > 0 and non_pro_rata_amount < rounded(self.remainig_benefits): frappe.throw(_("You can claim only an amount of {0}, the rest amount {1} should be in the application \ as pro-rata component").format(non_pro_rata_amount, self.remainig_benefits - non_pro_rata_amount)) elif non_pro_rata_amount == 0: @@ -65,7 +67,9 @@ class EmployeeBenefitApplication(Document): for employee_benefit in self.employee_benefits: if employee_benefit.earning_component == earning_component_name: benefit_amount += employee_benefit.amount - if benefit_amount > max_benefit_amount: + prev_sal_slip_flexi_amount = get_sal_slip_total_benefit_given(self.employee, frappe.get_doc("Payroll Period", self.payroll_period), earning_component_name) + benefit_amount += prev_sal_slip_flexi_amount + if rounded(benefit_amount, 2) > max_benefit_amount: frappe.throw(_("Maximum benefit amount of component {0} exceeds {1}").format(earning_component_name, max_benefit_amount)) def validate_duplicate_on_payroll_period(self): @@ -87,10 +91,17 @@ def get_max_benefits(employee, on_date): max_benefits = frappe.db.get_value("Salary Structure", sal_struct, "max_benefits") if max_benefits > 0: return max_benefits - else: - frappe.throw(_("Employee {0} has no max benefits in salary structure {1}").format(employee, sal_struct[0][0])) - else: - frappe.throw(_("Employee {0} has no salary structure assigned").format(employee)) + return False + +@frappe.whitelist() +def get_max_benefits_remaining(employee, on_date, payroll_period): + max_benefits = get_max_benefits(employee, on_date) + if max_benefits and max_benefits > 0: + payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period) + # Get all salary slip flexi amount in the payroll period + prev_sal_slip_flexi_total = get_sal_slip_total_benefit_given(employee, payroll_period_obj) + return max_benefits - prev_sal_slip_flexi_total + return max_benefits def get_benefit_component_amount(employee, start_date, end_date, struct_row, sal_struct): # Considering there is only one application for an year diff --git a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py index 1aed7ce1f8..50295996c6 100644 --- a/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py +++ b/erpnext/hr/doctype/employee_benefit_claim/employee_benefit_claim.py @@ -13,6 +13,8 @@ from erpnext.hr.doctype.salary_structure_assignment.salary_structure_assignment class EmployeeBenefitClaim(Document): def validate(self): max_benefits = get_max_benefits(self.employee, self.claim_date) + if not max_benefits or max_benefits <= 0: + frappe.throw(_("Employee {0} has no maximum benefit amount").format(self.employee)) payroll_period = get_payroll_period(self.claim_date, self.claim_date, frappe.db.get_value("Employee", self.employee, "company")) self.validate_max_benefit_for_component(payroll_period) self.validate_max_benefit_for_sal_struct(max_benefits) diff --git a/erpnext/hr/doctype/salary_detail/salary_detail.json b/erpnext/hr/doctype/salary_detail/salary_detail.json index a8f389b87d..4212f4a125 100644 --- a/erpnext/hr/doctype/salary_detail/salary_detail.json +++ b/erpnext/hr/doctype/salary_detail/salary_detail.json @@ -606,4 +606,4 @@ "sort_order": "DESC", "track_changes": 0, "track_seen": 0 -} \ No newline at end of file +} diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index dc2446ba35..dbd73b5602 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -107,7 +107,8 @@ class SalarySlip(TransactionBase): 'depends_on_lwp' : struct_row.depends_on_lwp, 'salary_component' : struct_row.salary_component, 'abbr' : struct_row.abbr, - 'do_not_include_in_total' : struct_row.do_not_include_in_total + 'do_not_include_in_total' : struct_row.do_not_include_in_total, + 'is_flexible_benefit': struct_row.is_flexible_benefit }) else: component_row.amount = amount diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index 11dbdf25d9..f4733176ac 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -350,3 +350,31 @@ def get_annual_component_pay(frequency, amount): return amount * 12 elif frequency == "Bimonthly": return amount * 6 + +def get_sal_slip_total_benefit_given(employee, payroll_period, component=False): + total_given_benefit_amount = 0 + query = """ + select sum(sd.amount) as 'total_amount' + from `tabSalary Slip` ss, `tabSalary Detail` sd + where ss.employee=%(employee)s + and ss.docstatus = 1 and ss.name = sd.parent + and sd.is_flexible_benefit = 1 and sd.parentfield = "earnings" + and sd.parenttype = "Salary Slip" + and (ss.start_date between %(start_date)s and %(end_date)s + or ss.end_date between %(start_date)s and %(end_date)s + or (ss.start_date < %(start_date)s and ss.end_date > %(end_date)s)) + """ + + if component: + query += "and sd.salary_component = %(component)s" + + sum_of_given_benefit = frappe.db.sql(query, { + 'employee': employee, + 'start_date': payroll_period.start_date, + 'end_date': payroll_period.end_date, + 'component': component + }, as_dict=True) + + if sum_of_given_benefit and sum_of_given_benefit[0].total_amount > 0: + total_given_benefit_amount = sum_of_given_benefit[0].total_amount + return total_given_benefit_amount From e06ecd2494fcdf76aae10d308a58d2b5756b76c0 Mon Sep 17 00:00:00 2001 From: Suraj Shetty Date: Tue, 12 Jun 2018 12:06:41 +0530 Subject: [PATCH 18/21] Check if user permission for employee exists (#14474) - Also check if user has permission to add user permission to avoid insufficient permission error while updating user profile --- erpnext/hr/doctype/employee/employee.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/erpnext/hr/doctype/employee/employee.py b/erpnext/hr/doctype/employee/employee.py index d79452cc36..58fb8eea9e 100755 --- a/erpnext/hr/doctype/employee/employee.py +++ b/erpnext/hr/doctype/employee/employee.py @@ -7,7 +7,8 @@ import frappe from frappe.utils import getdate, validate_email_add, today, add_years from frappe.model.naming import set_name_by_naming_series from frappe import throw, _, scrub -import frappe.permissions +from frappe.permissions import add_user_permission, remove_user_permission, \ + set_user_permission_if_allowed, has_permission from frappe.model.document import Document from erpnext.utilities.transaction_base import delete_events from frappe.utils.nestedset import NestedSet @@ -51,7 +52,7 @@ class Employee(NestedSet): else: existing_user_id = frappe.db.get_value("Employee", self.name, "user_id") if existing_user_id: - frappe.permissions.remove_user_permission( + remove_user_permission( "Employee", self.name, existing_user_id) def update_nsm_model(self): @@ -65,8 +66,8 @@ class Employee(NestedSet): def update_user_permissions(self): if not self.create_user_permission: return - frappe.permissions.add_user_permission("Employee", self.name, self.user_id) - frappe.permissions.set_user_permission_if_allowed("Company", self.company, self.user_id) + add_user_permission("Employee", self.name, self.user_id) + set_user_permission_if_allowed("Company", self.company, self.user_id) def update_user(self): # add employee role if missing @@ -206,6 +207,9 @@ def validate_employee_role(doc, method): def update_user_permissions(doc, method): # called via User hook if "Employee" in [d.role for d in doc.get("roles")]: + employee_name = frappe.get_value('Employee', {'user_id': doc.name}, 'name') + if has_user_permission_for_employee(doc.name, employee_name): return + if not has_permission('User Permission', ptype='write'): return employee = frappe.get_doc("Employee", {"user_id": doc.name}) employee.update_user_permissions() @@ -342,3 +346,11 @@ def get_children(doctype, parent=None, company=None, is_root=False, is_tree=Fals def on_doctype_update(): frappe.db.add_index("Employee", ["lft", "rgt"]) + +def has_user_permission_for_employee(user_name, employee_name): + return frappe.db.exists({ + 'doctype': 'User Permission', + 'user': user_name, + 'allow': 'Employee', + 'for_value': employee_name + }) From 138e6abaff14a0f23669e880c6c40cc572eac577 Mon Sep 17 00:00:00 2001 From: Ranjith Kurungadam Date: Tue, 12 Jun 2018 12:19:36 +0530 Subject: [PATCH 19/21] Salary Slip - update tax calculation, deduct tax for unsubmitted exemption proof (#14428) --- erpnext/hr/doctype/salary_slip/salary_slip.py | 178 +++++++++++++----- 1 file changed, 131 insertions(+), 47 deletions(-) diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index dbd73b5602..b8fadfd0f1 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -108,7 +108,9 @@ class SalarySlip(TransactionBase): 'salary_component' : struct_row.salary_component, 'abbr' : struct_row.abbr, 'do_not_include_in_total' : struct_row.do_not_include_in_total, - 'is_flexible_benefit': struct_row.is_flexible_benefit + 'is_tax_applicable': struct_row.is_tax_applicable, + 'is_flexible_benefit': struct_row.is_flexible_benefit, + 'variable_based_on_taxable_salary': struct_row.variable_based_on_taxable_salary }) else: component_row.amount = amount @@ -499,25 +501,35 @@ class SalarySlip(TransactionBase): return status def calculate_variable_based_on_taxable_salary(self, tax_component): - # TODO case both checked - restrict to and make this mandatory on final period of payroll? - # case only deduct_tax_for_unsubmitted_tax_exemption_proof checked not handled, calculate_variable_tax called payroll_period = get_payroll_period(self.start_date, self.end_date, self.company) if not payroll_period: frappe.msgprint(_("Start and end dates not in a valid Payroll Period, \ cannot calculate {0}.").format(tax_component)) return False, False - if self.deduct_tax_for_unclaimed_employee_benefits and not self.deduct_tax_for_unsubmitted_tax_exemption_proof: - total_taxable_benefit = self.calculate_unclaimed_benefit_amount(payroll_period) - total_taxable_benefit += self.get_taxable_earnings(only_flexi=True) - return self.calculate_variable_tax(tax_component, payroll_period, benefit_amount=total_taxable_benefit) - elif self.deduct_tax_for_unclaimed_employee_benefits and self.deduct_tax_for_unsubmitted_tax_exemption_proof: - return self.calculate_tax_for_payroll_period(tax_component, payroll_period) - else: - return self.calculate_variable_tax(tax_component, payroll_period) + if payroll_period.end_date <= getdate(self.end_date): + if not self.deduct_tax_for_unsubmitted_tax_exemption_proof \ + or not self.deduct_tax_for_unclaimed_employee_benefits: + frappe.throw(_("You have to Deduct Tax for Unsubmitted Tax Exemption Proof \ + and Unclaimed Employee Benefits in the last Salary Slip of Payroll Period")) + else: + return self.calculate_tax_for_payroll_period(tax_component, payroll_period) - def calculate_variable_tax(self, tax_component, payroll_period, benefit_amount=0): + benefit_amount_to_tax = 0 + if self.deduct_tax_for_unclaimed_employee_benefits: + # get all untaxed benefits till date, pass amount to be taxed by later methods + benefit_amount_to_tax = self.calculate_unclaimed_taxable_benefit(payroll_period) + # flexi's excluded from monthly tax, add flexis in this slip to total_taxable_benefit + benefit_amount_to_tax += self.get_taxable_earnings(only_flexi=True) + if self.deduct_tax_for_unsubmitted_tax_exemption_proof: + # calc tax to be paid for the period till date considering prorata taxes paid and proofs submitted + return self.calculate_unclaimed_taxable_earning(payroll_period, tax_component, benefit_amount_to_tax) + + # calc prorata tax to be applied + return self.calculate_variable_tax(tax_component, payroll_period, benefit_amount_to_tax=benefit_amount_to_tax) + + def calculate_variable_tax(self, tax_component, payroll_period, benefit_amount_to_tax=0): total_taxable_earning = self.get_taxable_earnings() - period_factor = self.get_period_factor(payroll_period.start_date, payroll_period.end_date) + period_factor = self.get_period_factor(payroll_period.start_date, payroll_period.end_date, self.start_date, self.end_date) annual_earning = total_taxable_earning * period_factor # Calculate total exemption declaration @@ -529,18 +541,7 @@ class SalarySlip(TransactionBase): "total_exemption_amount") annual_taxable_earning = annual_earning - exemption_amount - # Get tax calc by period - annual_tax = self.calculate_tax(payroll_period.name, annual_taxable_earning) - - # Calc prorata tax - pro_rata_tax = annual_tax / period_factor - struct_row = self.get_salary_slip_row(tax_component) - - # find the annual tax diff caused by benefit, add to pro_rata_tax - if benefit_amount > 0: - annual_tax_with_benefit = self.calculate_tax(payroll_period.name, annual_taxable_earning + benefit_amount) - pro_rata_tax += annual_tax_with_benefit - annual_tax - return struct_row, pro_rata_tax + return self.calculate_tax(payroll_period, tax_component, annual_taxable_earning, period_factor, 0, benefit_amount_to_tax) def calculate_tax_for_payroll_period(self, tax_component, payroll_period): # get total taxable income, total tax paid in payroll period @@ -560,18 +561,15 @@ class SalarySlip(TransactionBase): if sum_benefit_claim and sum_benefit_claim[0][0]: total_benefit_claim = sum_benefit_claim[0][0] total_taxable_earning = taxable_income - total_tax_exemption_proof - total_benefit_claim + # add taxable earnings of current salary_slip, include flexi total_taxable_earning += self.get_taxable_earnings(include_flexi=1) - # calc annual tax by tax slab - annual_tax = self.calculate_tax(payroll_period.name, total_taxable_earning) - # get balance amount to tax, even if -ve add to deduction - pay_slip_tax = annual_tax - tax_paid - struct_row = self.get_salary_slip_row(tax_component) - return struct_row, pay_slip_tax + return self.calculate_tax(payroll_period, tax_component, total_taxable_earning, 1, tax_paid, 0) - def calculate_unclaimed_benefit_amount(self, payroll_period): + def calculate_unclaimed_taxable_benefit(self, payroll_period): total_benefit = 0 start_date = payroll_period.start_date + # if tax for unclaimed benefit deducted earlier set the start date last_deducted = frappe.db.sql("""select end_date from `tabSalary Slip` where deduct_tax_for_unclaimed_employee_benefits=1 and docstatus=1 and @@ -580,6 +578,8 @@ class SalarySlip(TransactionBase): self.employee, payroll_period.start_date, payroll_period.end_date)) if last_deducted and last_deducted[0][0]: start_date = getdate(last_deducted[0][0]) + + # get total sum of benefits paid sum_benefit = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join `tabSalary Slip` ss on sd.parent=ss.name where sd.parentfield='earnings' and sd.is_tax_applicable=1 and is_flexible_benefit=1 and ss.docstatus=1 @@ -588,6 +588,8 @@ class SalarySlip(TransactionBase): start_date, payroll_period.end_date)) if sum_benefit and sum_benefit[0][0]: total_benefit = sum_benefit[0][0] + + # get total benefits claimed total_benefit_claim = 0 sum_benefit_claim = frappe.db.sql("""select sum(claimed_amount) from `tabEmployee Benefit Claim` where docstatus=1 and employee='{0}' and claim_date @@ -596,28 +598,103 @@ class SalarySlip(TransactionBase): total_benefit_claim = sum_benefit_claim[0][0] return total_benefit - total_benefit_claim + def calculate_unclaimed_taxable_earning(self, payroll_period, tax_component, benefit_amount_to_tax): + total_taxable_earning, total_tax_paid = 0, 0 + start_date = payroll_period.start_date + + # if tax deducted earlier set the start date + last_deducted = frappe.db.sql("""select end_date from `tabSalary Slip` where + deduct_tax_for_unsubmitted_tax_exemption_proof=1 and docstatus=1 and + employee='{0}' and start_date between '{1}' and '{2}' and end_date + between '{1}' and '{2}' order by end_date desc limit 1""".format( + self.employee, payroll_period.start_date, self.start_date)) + if last_deducted and last_deducted[0][0]: + start_date = getdate(last_deducted[0][0]) + + # calc total taxable amount in period + sum_taxable_earning = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join + `tabSalary Slip` ss on sd.parent=ss.name where sd.parentfield='earnings' + and sd.is_tax_applicable=1 and is_flexible_benefit=0 and ss.docstatus=1 + and ss.employee='{0}' and ss.start_date between '{1}' and '{2}' and + ss.end_date between '{1}' and '{2}'""".format(self.employee, + start_date, self.start_date)) + if sum_taxable_earning and sum_taxable_earning[0][0]: + total_taxable_earning = sum_taxable_earning[0][0] + + # add taxable earning in this salary slip + total_taxable_earning += self.get_taxable_earnings() + + # find total_tax_paid from salary slip where benefit is not taxed + sum_tax_paid = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join + `tabSalary Slip` ss on sd.parent=ss.name where sd.parentfield='deductions' + and sd.salary_component='{3}' and sd.variable_based_on_taxable_salary=1 and ss.docstatus=1 + and ss.employee='{0}' and ss.deduct_tax_for_unclaimed_employee_benefits=0 + and ss.start_date between '{1}' and '{2}' and ss.end_date between '{1}' and + '{2}'""".format(self.employee, start_date, self.start_date, tax_component)) + if sum_tax_paid and sum_tax_paid[0][0]: + total_tax_paid = sum_tax_paid[0][0] + + # get benefit taxed salary slips + benefit_taxed_ss = frappe.db.sql("""select name from `tabSalary Slip` where + deduct_tax_for_unsubmitted_tax_exemption_proof=0 and + deduct_tax_for_unclaimed_employee_benefits=1 and docstatus=1 and employee='{0}' + and start_date between '{1}' and '{2}' and end_date between '{1}' + and '{2}'""".format(self.employee, start_date, self.start_date)) + # add pro_rata_tax of all salary slips where benefit tax added up + if benefit_taxed_ss and benefit_taxed_ss[0]: + for salary_slip in benefit_taxed_ss[0]: + ss_obj = frappe.get_doc("Salary Slip", salary_slip) + struct_row, pro_rata_tax = ss_obj.calculate_variable_tax(tax_component, payroll_period) + if pro_rata_tax: + total_tax_paid += pro_rata_tax + total_exemption_amount = 0 + + # add up total Proof Submission + sum_exemption = frappe.db.sql("""select sum(total_amount) from + `tabEmployee Tax Exemption Proof Submission` where docstatus=1 and employee='{0}' and + payroll_period='{1}' and processed_in_payroll=0""".format(self.employee, payroll_period.name)) + if sum_exemption and sum_exemption[0][0]: + total_exemption_amount = sum_exemption[0][0] + total_taxable_earning -= total_exemption_amount + + # recalc annual tax slab by start date and end date + period_factor = self.get_period_factor(payroll_period.start_date, payroll_period.end_date, start_date, self.end_date) + annual_taxable_earning = total_taxable_earning * period_factor + return self.calculate_tax(payroll_period, tax_component, annual_taxable_earning, period_factor, total_tax_paid, benefit_amount_to_tax) + def get_taxable_earnings(self, include_flexi=0, only_flexi=0): - # TODO remove this, iterate in self.earnings. map_doc fails to copy field values from Salary Structure to Slary Slip - tax_applicable_components = [] - for earning in self._salary_structure_doc.earnings: + taxable_earning = 0 + for earning in self.earnings: if only_flexi: if earning.is_tax_applicable and earning.is_flexible_benefit: - tax_applicable_components.append(earning.salary_component) + taxable_earning += earning.amount continue if include_flexi: if earning.is_tax_applicable or (earning.is_tax_applicable and earning.is_flexible_benefit): - tax_applicable_components.append(earning.salary_component) + taxable_earning += earning.amount else: if earning.is_tax_applicable and not earning.is_flexible_benefit: - tax_applicable_components.append(earning.salary_component) - - taxable_earning = 0 - for earning in self.earnings: - if earning.salary_component in tax_applicable_components: - taxable_earning += earning.amount + taxable_earning += earning.amount return taxable_earning - def calculate_tax(self, payroll_period, annual_earning): + def calculate_tax(self, payroll_period, tax_component, annual_taxable_earning, period_factor, tax_paid=0, benefit_amount_to_tax=0): + # Get tax calc by period + annual_tax = self.calculate_tax_by_tax_slab(payroll_period.name, annual_taxable_earning) + + # Calc prorata tax + tax_amount = annual_tax / period_factor + if tax_paid: + tax_amount -= tax_paid + + # find the annual tax diff caused by benefit_amount_to_tax, add to tax_amount + if benefit_amount_to_tax > 0: + annual_tax_with_benefit_amt = self.calculate_tax_by_tax_slab(payroll_period.name, annual_taxable_earning + benefit_amount_to_tax) + tax_amount += annual_tax_with_benefit_amt - annual_tax + struct_row = self.get_salary_slip_row(tax_component) + return struct_row, tax_amount + + def calculate_tax_by_tax_slab(self, payroll_period, annual_earning): + # TODO consider condition in tax slab payroll_period_obj = frappe.get_doc("Payroll Period", payroll_period) taxable_amount = 0 for slab in payroll_period_obj.taxable_salary_slabs: @@ -627,13 +704,17 @@ class SalarySlip(TransactionBase): taxable_amount += (slab.to_amount - slab.from_amount) * slab.percent_deduction * .01 return taxable_amount - def get_period_factor(self, start_date, end_date): - # period length is hard coded to keep tax calc consistent + def get_period_factor(self, period_start, period_end, start_date=None, end_date=None): + # TODO make this configurable? - use hard coded period length to keep tax calc consistent frequency_days = {"Daily": 1, "Weekly": 7, "Fortnightly": 15, "Monthly": 30, "Bimonthly": 60} - payroll_days = date_diff(end_date, start_date) + 1 + payroll_days = date_diff(period_end, period_start) + 1 + if start_date and end_date: + salary_days = date_diff(end_date, start_date) +1 + return flt(payroll_days)/flt(salary_days) return flt(payroll_days)/frequency_days[self.payroll_frequency] def get_tax_detail_till_date(self, payroll_period, tax_component): + # find total taxable income, total tax paid by employee in payroll period total_taxable_income = 0 total_tax_paid = 0 sum_income = frappe.db.sql("""select sum(sd.amount) from `tabSalary Detail` sd join @@ -662,6 +743,9 @@ class SalarySlip(TransactionBase): struct_row['salary_component'] = component.name struct_row['abbr'] = component.salary_component_abbr struct_row['do_not_include_in_total'] = component.do_not_include_in_total + struct_row['is_tax_applicable'] = component.is_tax_applicable + struct_row['is_flexible_benefit'] = component.is_flexible_benefit + struct_row['variable_based_on_taxable_salary'] = component.variable_based_on_taxable_salary return struct_row def unlink_ref_doc_from_salary_slip(ref_no): From f270567c456c7a6b9cb656abca571e11a3f12671 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 12 Jun 2018 12:20:52 +0530 Subject: [PATCH 20/21] [Fix] Test cases for asset --- erpnext/assets/doctype/asset/asset.py | 2 +- erpnext/assets/doctype/asset/test_asset.py | 2 +- erpnext/public/js/controllers/transaction.js | 3 +-- erpnext/stock/doctype/stock_entry/stock_entry.js | 3 ++- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 247dc10972..cef5b0abb9 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -40,7 +40,7 @@ class Asset(AccountsController): self.validate_cancellation() self.delete_depreciation_entries() self.set_status() - delete_gl_entries() + delete_gl_entries(voucher_type='Asset', voucher_no=self.name) self.db_set('booked_fixed_asset', 0) def validate_item(self): diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 3f706f8b64..4ee4894f04 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -31,7 +31,7 @@ class TestAsset(unittest.TestCase): self.assertEqual(asset.purchase_invoice, pi.name) expected_gle = ( - ("_Test Fixed Asset - _TC", 100000.0, 0.0), + ("Asset Received But Not Billed - _TC", 100000.0, 0.0), ("Creditors - _TC", 0.0, 100000.0) ) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 7adb38ea67..ff0d134d81 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -152,8 +152,6 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ onload: function() { var me = this; - this.setup_quality_inspection(); - if(this.frm.doc.__islocal) { var currency = frappe.defaults.get_user_default("currency"); @@ -230,6 +228,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ erpnext.hide_company(); this.set_dynamic_labels(); this.setup_sms(); + this.setup_quality_inspection(); }, apply_default_taxes: function() { diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 359d8347d2..e468533b8a 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -59,7 +59,6 @@ frappe.ui.form.on('Stock Entry', { }); frm.add_fetch("bom_no", "inspection_required", "inspection_required"); - frm.trigger("setup_quality_inspection"); }, setup_quality_inspection: function(frm) { @@ -189,6 +188,8 @@ frappe.ui.form.on('Stock Entry', { frm.trigger("make_retention_stock_entry"); }); } + + frm.trigger("setup_quality_inspection"); }, purpose: function(frm) { From b6381c66d86dc2743a318c9d65fdf0b62d7560b4 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Tue, 12 Jun 2018 13:54:40 +0530 Subject: [PATCH 21/21] [Fix] Purchase receipt test cases --- erpnext/buying/doctype/buying_settings/buying_settings.json | 3 ++- erpnext/controllers/stock_controller.py | 2 +- .../stock/doctype/purchase_receipt/test_purchase_receipt.py | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/erpnext/buying/doctype/buying_settings/buying_settings.json b/erpnext/buying/doctype/buying_settings/buying_settings.json index 21e9485915..add0fd514c 100644 --- a/erpnext/buying/doctype/buying_settings/buying_settings.json +++ b/erpnext/buying/doctype/buying_settings/buying_settings.json @@ -339,6 +339,7 @@ "bold": 0, "collapsible": 0, "columns": 0, + "default": "Material Transferred for Subcontract", "fieldname": "backflush_raw_materials_of_subcontract_based_on", "fieldtype": "Select", "hidden": 0, @@ -377,7 +378,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2018-05-30 16:28:46.899823", + "modified": "2018-06-12 03:41:41.739193", "modified_by": "Administrator", "module": "Buying", "name": "Buying Settings", diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 31c034da34..a76a3b3bfb 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -33,7 +33,7 @@ class StockController(AccountsController): items, warehouses = self.get_items_and_warehouses() update_gl_entries_after(self.posting_date, self.posting_time, warehouses, items, warehouse_account) - elif self.doctype in ['Purchase Receipt', 'Purchase Invoice']: + elif self.doctype in ['Purchase Receipt', 'Purchase Invoice'] and self.docstatus == 1: gl_entries = [] gl_entries = self.get_asset_gl_entry(gl_entries) make_gl_entries(gl_entries, from_repost=from_repost) diff --git a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py index 1abc0f4e81..c199271227 100644 --- a/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/test_purchase_receipt.py @@ -92,6 +92,7 @@ class TestPurchaseReceipt(unittest.TestCase): def test_subcontracting(self): from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry + frappe.db.set_value("Buying Settings", None, "backflush_raw_materials_of_subcontract_based_on", "BOM") make_stock_entry(item_code="_Test Item", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100) make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse 1 - _TC", qty=100, basic_rate=100) @@ -314,9 +315,10 @@ class TestPurchaseReceipt(unittest.TestCase): asset_category = doc.name - asset_item = make_item(asset_item, {'is_stock_item':0, + 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 if not frappe.db.exists('Location', 'Test Location'): frappe.get_doc({ @@ -334,7 +336,6 @@ class TestPurchaseReceipt(unittest.TestCase): 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 Category`") frappe.db.sql("delete from `tabAsset`") def get_gl_entries(voucher_type, voucher_no):