From 9a3a22a08ee267fd6c632e21267c4bd0b8f07dd1 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 20 Sep 2021 04:33:30 +0530 Subject: [PATCH 01/40] fix: Calculate depreciation_left accurately (cherry picked from commit 164a2ad28db541e1f68b0e9f4913991b067c721a) --- erpnext/assets/doctype/asset/asset.py | 20 +++++++++++++++++--- erpnext/regional/india/utils.py | 5 +++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 03824f7b64f..efb1713c8b0 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -214,7 +214,7 @@ class Asset(AccountsController): # If depreciation is already completed (for double declining balance) if skip_row: continue - depreciation_amount = get_depreciation_amount(self, value_after_depreciation, d) + depreciation_amount = get_depreciation_amount(self, value_after_depreciation, d, date_of_sale) if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1: schedule_date = add_months(d.depreciation_start_date, @@ -825,8 +825,8 @@ def get_total_days(date, frequency): return date_diff(date, period_start_date) @erpnext.allow_regional -def get_depreciation_amount(asset, depreciable_value, row): - depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked) +def get_depreciation_amount(asset, depreciable_value, row, date_of_sale=None): + depreciation_left = get_depreciation_left(asset, row, date_of_sale) if row.depreciation_method in ("Straight Line", "Manual"): # if the Depreciation Schedule is being prepared for the first time @@ -842,3 +842,17 @@ def get_depreciation_amount(asset, depreciable_value, row): depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100)) return depreciation_amount + +def get_depreciation_left(asset, row, date_of_sale): + if not date_of_sale: + return flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked) + else: + if len(asset.finance_books) == 1: + return (flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked)) - len(asset.schedules) + else: + depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked) + for schedule in asset.get('schedules'): + if schedule.finance_book == row.finance_book: + depreciation_left -= 1 + + return depreciation_left diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index d47242e2f98..fdfbd891241 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -13,6 +13,7 @@ from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_ from erpnext.hr.utils import get_salary_assignment from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip from erpnext.regional.india import number_state_mapping, state_numbers, states +from erpnext.assets.doctype.asset.asset import get_depreciation_left GST_INVOICE_NUMBER_FORMAT = re.compile(r"^[a-zA-Z0-9\-/]+$") #alphanumeric and - / GSTIN_FORMAT = re.compile("^[0-9]{2}[A-Z]{4}[0-9A-Z]{1}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[1-9A-Z]{1}[0-9A-Z]{1}$") @@ -837,8 +838,8 @@ def update_taxable_values(doc, method): diff = additional_taxes - total_charges doc.get('items')[item_count - 1].taxable_value += diff -def get_depreciation_amount(asset, depreciable_value, row): - depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked) +def get_depreciation_amount(asset, depreciable_value, row, date_of_sale=None): + depreciation_left = get_depreciation_left(asset, row, date_of_sale) if row.depreciation_method in ("Straight Line", "Manual"): # if the Depreciation Schedule is being prepared for the first time From 04acf5b08c28fc0d2d9ff704001f6ba2121ce969 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 21 Sep 2021 06:06:21 +0530 Subject: [PATCH 02/40] fix: Correct expected_values (cherry picked from commit 244d9dee044091ad3f27c6ddec32d2e45165363f) --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 058e5623b32..b066e141db3 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2207,7 +2207,7 @@ class TestSalesInvoice(unittest.TestCase): expected_values = [ ["2020-06-30", 1311.48, 1311.48], ["2021-06-30", 20000.0, 21311.48], - ["2021-09-30", 3966.76, 25278.24] + ["2021-09-30", 5041.1, 26352.58] ] for i, schedule in enumerate(asset.schedules): From 311f9c8389a03894f8213eb3c164c42c1ad3b22e Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 21 Sep 2021 06:07:06 +0530 Subject: [PATCH 03/40] fix: Calculate depreciation_amount accurately (cherry picked from commit 3c8879e777eccd5b4a0c61f9d932e421662848eb) --- erpnext/assets/doctype/asset/asset.py | 22 ++++------------------ erpnext/regional/india/utils.py | 7 +++---- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index efb1713c8b0..ef5bc43ffa9 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -214,7 +214,7 @@ class Asset(AccountsController): # If depreciation is already completed (for double declining balance) if skip_row: continue - depreciation_amount = get_depreciation_amount(self, value_after_depreciation, d, date_of_sale) + depreciation_amount = get_depreciation_amount(self, value_after_depreciation, d) if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1: schedule_date = add_months(d.depreciation_start_date, @@ -825,13 +825,13 @@ def get_total_days(date, frequency): return date_diff(date, period_start_date) @erpnext.allow_regional -def get_depreciation_amount(asset, depreciable_value, row, date_of_sale=None): - depreciation_left = get_depreciation_left(asset, row, date_of_sale) +def get_depreciation_amount(asset, depreciable_value, row): + depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked) if row.depreciation_method in ("Straight Line", "Manual"): # if the Depreciation Schedule is being prepared for the first time if not asset.flags.increase_in_asset_life: - depreciation_amount = (flt(row.value_after_depreciation) - + depreciation_amount = ((flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation)) - flt(row.expected_value_after_useful_life)) / depreciation_left # if the Depreciation Schedule is being modified after Asset Repair @@ -842,17 +842,3 @@ def get_depreciation_amount(asset, depreciable_value, row, date_of_sale=None): depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100)) return depreciation_amount - -def get_depreciation_left(asset, row, date_of_sale): - if not date_of_sale: - return flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked) - else: - if len(asset.finance_books) == 1: - return (flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked)) - len(asset.schedules) - else: - depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked) - for schedule in asset.get('schedules'): - if schedule.finance_book == row.finance_book: - depreciation_left -= 1 - - return depreciation_left diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index fdfbd891241..0a46d6ef140 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -13,7 +13,6 @@ from erpnext.controllers.taxes_and_totals import get_itemised_tax, get_itemised_ from erpnext.hr.utils import get_salary_assignment from erpnext.payroll.doctype.salary_structure.salary_structure import make_salary_slip from erpnext.regional.india import number_state_mapping, state_numbers, states -from erpnext.assets.doctype.asset.asset import get_depreciation_left GST_INVOICE_NUMBER_FORMAT = re.compile(r"^[a-zA-Z0-9\-/]+$") #alphanumeric and - / GSTIN_FORMAT = re.compile("^[0-9]{2}[A-Z]{4}[0-9A-Z]{1}[0-9]{4}[A-Z]{1}[1-9A-Z]{1}[1-9A-Z]{1}[0-9A-Z]{1}$") @@ -838,13 +837,13 @@ def update_taxable_values(doc, method): diff = additional_taxes - total_charges doc.get('items')[item_count - 1].taxable_value += diff -def get_depreciation_amount(asset, depreciable_value, row, date_of_sale=None): - depreciation_left = get_depreciation_left(asset, row, date_of_sale) +def get_depreciation_amount(asset, depreciable_value, row): + depreciation_left = flt(row.total_number_of_depreciations) - flt(asset.number_of_depreciations_booked) if row.depreciation_method in ("Straight Line", "Manual"): # if the Depreciation Schedule is being prepared for the first time if not asset.flags.increase_in_asset_life: - depreciation_amount = (flt(row.value_after_depreciation) - + depreciation_amount = ((flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation)) - flt(row.expected_value_after_useful_life)) / depreciation_left # if the Depreciation Schedule is being modified after Asset Repair From 9eb37197e0db67cde2c39427c049694ad9cb6657 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 21 Sep 2021 07:03:12 +0530 Subject: [PATCH 04/40] fix: Remove extra brackets (cherry picked from commit 700e78d69b2e4e8f12dafc20e536b08c99cd2852) --- erpnext/assets/doctype/asset/asset.py | 2 +- erpnext/regional/india/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index ef5bc43ffa9..21033fdcb45 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -831,7 +831,7 @@ def get_depreciation_amount(asset, depreciable_value, row): if row.depreciation_method in ("Straight Line", "Manual"): # if the Depreciation Schedule is being prepared for the first time if not asset.flags.increase_in_asset_life: - depreciation_amount = ((flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation)) - + depreciation_amount = (flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation) - flt(row.expected_value_after_useful_life)) / depreciation_left # if the Depreciation Schedule is being modified after Asset Repair diff --git a/erpnext/regional/india/utils.py b/erpnext/regional/india/utils.py index 0a46d6ef140..36bc42d899e 100644 --- a/erpnext/regional/india/utils.py +++ b/erpnext/regional/india/utils.py @@ -843,7 +843,7 @@ def get_depreciation_amount(asset, depreciable_value, row): if row.depreciation_method in ("Straight Line", "Manual"): # if the Depreciation Schedule is being prepared for the first time if not asset.flags.increase_in_asset_life: - depreciation_amount = ((flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation)) - + depreciation_amount = (flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation) - flt(row.expected_value_after_useful_life)) / depreciation_left # if the Depreciation Schedule is being modified after Asset Repair From efe9926bb43a75d284984e2b2ebeb00b0b21ece8 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 21 Sep 2021 07:04:39 +0530 Subject: [PATCH 05/40] fix: Add depreciation_schedule details in create_asset() (cherry picked from commit 249672c35db9278e1c4027b2331e1b6b5ef8f7d2) --- erpnext/assets/doctype/asset/test_asset.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 0b5e41ee7ef..9424d626031 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -729,9 +729,8 @@ def create_asset(**args): "calculate_depreciation": args.calculate_depreciation or 0, "gross_purchase_amount": 100000, "purchase_receipt_amount": 100000, - "expected_value_after_useful_life": 10000, "warehouse": args.warehouse or "_Test Warehouse - _TC", - "available_for_use_date": "2020-06-06", + "available_for_use_date": args.available_for_use_date or "2020-06-06", "location": "Test Location", "asset_owner": "Company", "is_existing_asset": 1 @@ -740,8 +739,10 @@ def create_asset(**args): if asset.calculate_depreciation: asset.append("finance_books", { "depreciation_method": "Straight Line", - "frequency_of_depreciation": 12, - "total_number_of_depreciations": 5 + "frequency_of_depreciation": args.frequency_of_depreciation or 12, + "total_number_of_depreciations": args.total_number_of_depreciations or 5, + "expected_value_after_useful_life": args.expected_value_after_useful_life or 0, + "depreciation_start_date": args.depreciation_start_date }) try: From 7921e7ebfdba97e2e5c976244cb5872e53be609d Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 21 Sep 2021 07:07:00 +0530 Subject: [PATCH 06/40] fix: Add test for depreciation on sale of a depreciated Asset (cherry picked from commit 7ab3b9dd5a8877b1c1dff6eb1d5ab453b0a4c8f5) --- .../sales_invoice/test_sales_invoice.py | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index b066e141db3..46349b1abaf 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2194,7 +2194,7 @@ class TestSalesInvoice(unittest.TestCase): def test_asset_depreciation_on_sale(self): """ - Tests if an Asset set to depreciate yearly on June 30, that gets sold on Sept 30, creates an additional depreciation entry on Sept 30. + Tests if an Asset set to depreciate yearly on June 30, that gets sold on Sept 30, creates an additional depreciation entry on its date of sale. """ create_asset_data() @@ -2216,6 +2216,32 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) self.assertTrue(schedule.journal_entry) + def test_depreciation_on_sale_for_depreciated_asset(self): + """ + Tests if an Asset set to depreciate yearly on Dec 31, that gets sold on Dec 31 after two years, created an additional depreciation entry on its date of sale. + """ + + create_asset_data() + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-12-31"), submit=1) + + post_depreciation_entries(getdate("2021-09-30")) + + create_sales_invoice(item_code="Macbook Pro", asset=asset.name, qty=1, rate=90000, posting_date=getdate("2021-12-31")) + asset.load_from_db() + + expected_values = [ + ["2020-12-31", 30000, 30000], + ["2021-12-31", 30000, 60000] + ] + + for i, schedule in enumerate(asset.schedules): + self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) + self.assertEqual(expected_values[i][1], schedule.depreciation_amount) + self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) + self.assertTrue(schedule.journal_entry) + def test_sales_invoice_against_supplier(self): from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import ( make_customer, From 91fbe54b8dc2662fd799db47a28c8996baed3ac8 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Sat, 25 Sep 2021 19:04:16 +0530 Subject: [PATCH 07/40] fix: Reset depreciation schedule on returning asset (cherry picked from commit b9fb59da58aa4ac5f0e287fcdce7d2993d9af9c7) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 4 ++-- erpnext/assets/doctype/asset/asset.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 5b369b9895b..de01a6aa4c2 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1006,7 +1006,7 @@ class SalesInvoice(SellingController): def depreciate_asset(self, asset): asset.flags.ignore_validate_update_after_submit = True - asset.prepare_depreciation_data(self.posting_date) + asset.prepare_depreciation_data(date_of_sale=self.posting_date) asset.save() post_depreciation_entries(self.posting_date) @@ -1015,7 +1015,7 @@ class SalesInvoice(SellingController): asset.flags.ignore_validate_update_after_submit = True # recreate original depreciation schedule of the asset - asset.prepare_depreciation_data() + asset.prepare_depreciation_data(date_of_return=self.posting_date) self.modify_depreciation_schedule_for_asset_repairs(asset) asset.save() diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 21033fdcb45..34104623964 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -73,12 +73,12 @@ class Asset(AccountsController): if self.is_existing_asset and self.purchase_invoice: frappe.throw(_("Purchase Invoice cannot be made against an existing asset {0}").format(self.name)) - def prepare_depreciation_data(self, date_of_sale=None): + def prepare_depreciation_data(self, date_of_sale=None, date_of_return=None): if self.calculate_depreciation: self.value_after_depreciation = 0 self.set_depreciation_rate() self.make_depreciation_schedule(date_of_sale) - self.set_accumulated_depreciation(date_of_sale) + self.set_accumulated_depreciation(date_of_sale, date_of_return) else: self.finance_books = [] self.value_after_depreciation = (flt(self.gross_purchase_amount) - @@ -395,7 +395,7 @@ class Asset(AccountsController): frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Available-for-use Date") .format(row.idx)) - def set_accumulated_depreciation(self, date_of_sale=None, ignore_booked_entry = False): + def set_accumulated_depreciation(self, date_of_sale=None, date_of_return=None, ignore_booked_entry = False): straight_line_idx = [d.idx for d in self.get("schedules") if d.depreciation_method == 'Straight Line'] finance_books = [] @@ -412,7 +412,7 @@ class Asset(AccountsController): value_after_depreciation -= flt(depreciation_amount) # for the last row, if depreciation method = Straight Line - if straight_line_idx and i == max(straight_line_idx) - 1 and not date_of_sale: + if straight_line_idx and i == max(straight_line_idx) - 1 and not date_of_sale and not date_of_return: book = self.get('finance_books')[cint(d.finance_book_id) - 1] depreciation_amount += flt(value_after_depreciation - flt(book.expected_value_after_useful_life), d.precision("depreciation_amount")) From 46c0e349f6fc7ddc384238f0679c6e55d9f22fdf Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Sat, 25 Sep 2021 19:11:29 +0530 Subject: [PATCH 08/40] fix: Reverse depreciation entry made on sale if asset that was set to be sold in the future gets returned (cherry picked from commit 796ed947ce2217496706bf00e7c3ddf8c4fc2e3a) --- .../doctype/sales_invoice/sales_invoice.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index de01a6aa4c2..9cecac07783 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -943,6 +943,7 @@ class SalesInvoice(SellingController): asset.db_set("disposal_date", None) if asset.calculate_depreciation: + self.reverse_depreciation_entry_made_after_sale(asset) self.reset_depreciation_schedule(asset) else: @@ -1020,8 +1021,6 @@ class SalesInvoice(SellingController): self.modify_depreciation_schedule_for_asset_repairs(asset) asset.save() - self.delete_depreciation_entry_made_after_sale(asset) - def modify_depreciation_schedule_for_asset_repairs(self, asset): asset_repairs = frappe.get_all( 'Asset Repair', @@ -1035,7 +1034,7 @@ class SalesInvoice(SellingController): asset_repair.modify_depreciation_schedule() asset.prepare_depreciation_data() - def delete_depreciation_entry_made_after_sale(self, asset): + def reverse_depreciation_entry_made_after_sale(self, asset): from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry posting_date_of_original_invoice = self.get_posting_date_of_sales_invoice() @@ -1050,7 +1049,8 @@ class SalesInvoice(SellingController): row += 1 if schedule.schedule_date == posting_date_of_original_invoice: - if not self.sale_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_original_invoice): + if not self.sale_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_original_invoice) \ + or self.sale_happens_in_the_future(posting_date_of_original_invoice): reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) reverse_journal_entry.posting_date = nowdate() reverse_journal_entry.submit() @@ -1069,6 +1069,12 @@ class SalesInvoice(SellingController): return True return False + def sale_happens_in_the_future(self, posting_date_of_original_invoice): + if posting_date_of_original_invoice > getdate(): + return True + + return False + @property def enable_discount_accounting(self): if not hasattr(self, "_enable_discount_accounting"): From 7c114c0bc55f89007606df81259e0ccb0cd5094f Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 27 Sep 2021 22:14:16 +0530 Subject: [PATCH 09/40] fix: Replace asset.schedules with asset.get('schedules') (cherry picked from commit fdd9e6cc3c62a85573b7f02ff4940046d572e92b) --- erpnext/assets/doctype/asset/asset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 34104623964..ebeecba8833 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -180,7 +180,7 @@ class Asset(AccountsController): d.precision("rate_of_depreciation")) def make_depreciation_schedule(self, date_of_sale): - if 'Manual' not in [d.depreciation_method for d in self.finance_books] and not self.schedules: + if 'Manual' not in [d.depreciation_method for d in self.finance_books] and not self.get('schedules'): self.schedules = [] if not self.available_for_use_date: From 94c3e0503f5e68d21897461b37c67ea60928e5da Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 27 Sep 2021 22:14:42 +0530 Subject: [PATCH 10/40] fix: Add tests for depreciation (cherry picked from commit 40ec2d622baeb43f45086fcb7298457100a94f40) # Conflicts: # erpnext/assets/doctype/asset/test_asset.py --- erpnext/assets/doctype/asset/test_asset.py | 258 ++++++++++++++++++++- 1 file changed, 254 insertions(+), 4 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 9424d626031..b0bac887daa 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -274,6 +274,7 @@ class TestAsset(unittest.TestCase): self.assertEqual(gle, expected_gle) self.assertEqual(asset.get("value_after_depreciation"), 0) + # WDV: Written Down Value def test_depreciation_entry_for_wdv_without_pro_rata(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=8000.0, location="Test Location") @@ -477,6 +478,7 @@ class TestAsset(unittest.TestCase): self.assertTrue(asset.finance_books[0].expected_value_after_useful_life >= asset_value_after_full_schedule) + # CWIP: Capital Work In Progress def test_cwip_accounting(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=5000, do_not_submit=True, location="Test Location") @@ -680,6 +682,7 @@ class TestAsset(unittest.TestCase): # reset indian company frappe.flags.company = company_flag +<<<<<<< HEAD def test_expected_value_change(self): """ tests if changing `expected_value_after_useful_life` @@ -700,6 +703,250 @@ class TestAsset(unittest.TestCase): asset.save() asset.reload() self.assertEquals(asset.finance_books[0].value_after_depreciation, 98000.0) +======= + def test_depreciation_without_pro_rata(self): + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-12-31"), submit=1) + + expected_values = [ + ["2020-12-31", 30000, 30000], + ["2021-12-31", 30000, 60000], + ["2022-12-31", 30000, 90000] + ] + + for i, schedule in enumerate(asset.schedules): + self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) + self.assertEqual(expected_values[i][1], schedule.depreciation_amount) + self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) + + def test_depreciation_with_pro_rata(self): + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-07-01"), submit=1) + + expected_values = [ + ["2020-07-01", 15000, 15000], + ["2021-07-01", 30000, 45000], + ["2022-07-01", 30000, 75000], + ["2022-12-31", 15000, 90000] + ] + + for i, schedule in enumerate(asset.schedules): + self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) + self.assertEqual(expected_values[i][1], schedule.depreciation_amount) + self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) + + def test_get_depreciation_amount(self): + """Tests if get_depreciation_amount() returns the right value.""" + + from erpnext.assets.doctype.asset.asset import get_depreciation_amount + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31")) + + asset.finance_books = [] + asset.append("finance_books", { + "depreciation_method": "Straight Line", + "frequency_of_depreciation": 12, + "total_number_of_depreciations": 3, + "expected_value_after_useful_life": 10000, + "depreciation_start_date": getdate("2020-12-31") + }) + + depreciation_amount = get_depreciation_amount(asset, 100000, asset.finance_books[0]) + self.assertEqual(depreciation_amount, 30000) + + def test_make_depreciation_schedule(self): + """Tests if make_depreciation_schedule() returns the right values.""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), do_not_save=1) + + asset.finance_books = [] + asset.append("finance_books", { + "depreciation_method": "Straight Line", + "frequency_of_depreciation": 12, + "total_number_of_depreciations": 3, + "expected_value_after_useful_life": 10000, + "depreciation_start_date": getdate("2020-12-31") + }) + + asset.make_depreciation_schedule(date_of_sale=None) + + expected_values = [ + ['2020-12-31', 30000.0], + ['2021-12-31', 30000.0], + ['2022-12-31', 30000.0] + ] + + for i, schedule in enumerate(asset.schedules): + self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) + self.assertEqual(expected_values[i][1], schedule.depreciation_amount) + + def test_set_accumulated_depreciation(self): + """Tests if set_accumulated_depreciation() returns the right values.""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), do_not_save=1) + + asset.finance_books = [] + asset.append("finance_books", { + "depreciation_method": "Straight Line", + "frequency_of_depreciation": 12, + "total_number_of_depreciations": 3, + "expected_value_after_useful_life": 10000, + "depreciation_start_date": getdate("2020-12-31") + }) + + asset.make_depreciation_schedule(date_of_sale=None) + asset.set_accumulated_depreciation() + + expected_values = [30000.0, 60000.0, 90000.0] + + for i, schedule in enumerate(asset.schedules): + self.assertEqual(expected_values[i], schedule.accumulated_depreciation_amount) + + def test_check_is_pro_rata(self): + """Tests if check_is_pro_rata() returns the right value(i.e. checks if has_pro_rata is accurate).""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), do_not_save=1) + + asset.finance_books = [] + asset.append("finance_books", { + "depreciation_method": "Straight Line", + "frequency_of_depreciation": 12, + "total_number_of_depreciations": 3, + "expected_value_after_useful_life": 10000, + "depreciation_start_date": getdate("2020-12-31") + }) + + has_pro_rata = asset.check_is_pro_rata(asset.finance_books[0]) + self.assertFalse(has_pro_rata) + + asset.finance_books = [] + asset.append("finance_books", { + "depreciation_method": "Straight Line", + "frequency_of_depreciation": 12, + "total_number_of_depreciations": 3, + "expected_value_after_useful_life": 10000, + "depreciation_start_date": getdate("2020-07-01") + }) + + has_pro_rata = asset.check_is_pro_rata(asset.finance_books[0]) + self.assertTrue(has_pro_rata) + + def test_expected_value_after_useful_life(self): + """Tests if an error is raised when expected_value_after_useful_life(110,000) > gross_purchase_amount(100,000).""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=110000, depreciation_start_date=getdate("2020-07-01"), do_not_save=1) + + self.assertRaises(frappe.ValidationError, asset.save) + + def test_depreciation_start_date(self): + """Tests if an error is raised when neither depreciation_start_date nor available_for_use_date are specified.""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + total_number_of_depreciations=3, expected_value_after_useful_life=110000, do_not_save=1) + + self.assertRaises(frappe.ValidationError, asset.save) + + def test_opening_accumulated_depreciation(self): + """Tests if an error is raised when opening_accumulated_depreciation > (gross_purchase_amount - expected_value_after_useful_life).""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-07-01"), + opening_accumulated_depreciation=100000, do_not_save=1) + + self.assertRaises(frappe.ValidationError, asset.save) + + def test_number_of_depreciations_booked(self): + """Tests if an error is raised when number_of_depreciations_booked is not specified when opening_accumulated_depreciation is.""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-07-01"), + opening_accumulated_depreciation=10000, do_not_save=1) + + self.assertRaises(frappe.ValidationError, asset.save) + + def test_number_of_depreciations(self): + """Tests if an error is raised when number_of_depreciations_booked > total_number_of_depreciations.""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-07-01"), + opening_accumulated_depreciation=10000, number_of_depreciations_booked=5, + do_not_save=1) + + self.assertRaises(frappe.ValidationError, asset.save) + + def test_depreciation_start_date_is_before_purchase_date(self): + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=10000, depreciation_start_date=getdate("2014-07-01"), + do_not_save=1) + + self.assertRaises(frappe.ValidationError, asset.save) + + def test_depreciation_start_date_is_before_available_for_use_date(self): + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, + expected_value_after_useful_life=10000, depreciation_start_date=getdate("2018-07-01"), + do_not_save=1) + + self.assertRaises(frappe.ValidationError, asset.save) + + def test_post_depreciation_entries(self): + """Tests if post_depreciation_entries() works as expected.""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), do_not_save=1) + + asset.finance_books = [] + asset.append("finance_books", { + "depreciation_method": "Straight Line", + "frequency_of_depreciation": 12, + "total_number_of_depreciations": 3, + "expected_value_after_useful_life": 10000, + "depreciation_start_date": getdate("2020-12-31") + }) + asset.submit() + + post_depreciation_entries(date="2021-06-01") + asset.load_from_db() + + self.assertTrue(asset.schedules[0].journal_entry) + self.assertFalse(asset.schedules[1].journal_entry) + self.assertFalse(asset.schedules[2].journal_entry) + + def test_clear_depreciation_schedule(self): + """Tests if clear_depreciation_schedule() works as expected.""" + + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date=getdate("2019-12-31"), do_not_save=1) + + asset.finance_books = [] + asset.append("finance_books", { + "depreciation_method": "Straight Line", + "frequency_of_depreciation": 12, + "total_number_of_depreciations": 3, + "expected_value_after_useful_life": 10000, + "depreciation_start_date": getdate("2020-12-31") + }) + asset.submit() + + post_depreciation_entries(date="2021-06-01") + asset.load_from_db() + + asset.clear_depreciation_schedule() + + self.assertEqual(len(asset.schedules), 1) +>>>>>>> 40ec2d622b (fix: Add tests for depreciation) def create_asset_data(): if not frappe.db.exists("Asset Category", "Computers"): @@ -727,6 +974,8 @@ def create_asset(**args): "company": args.company or"_Test Company", "purchase_date": "2015-01-01", "calculate_depreciation": args.calculate_depreciation or 0, + "opening_accumulated_depreciation": args.opening_accumulated_depreciation or 0, + "number_of_depreciations_booked": args.number_of_depreciations_booked or 0, "gross_purchase_amount": 100000, "purchase_receipt_amount": 100000, "warehouse": args.warehouse or "_Test Warehouse - _TC", @@ -745,10 +994,11 @@ def create_asset(**args): "depreciation_start_date": args.depreciation_start_date }) - try: - asset.save() - except frappe.DuplicateEntryError: - pass + if not args.do_not_save: + try: + asset.save() + except frappe.DuplicateEntryError: + pass if args.submit: asset.submit() From ae6bac9fcbe15bc1d375349d2cd674ee24af2e44 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 28 Sep 2021 01:22:38 +0530 Subject: [PATCH 11/40] fix: Categorize into test suites (cherry picked from commit c84c983073943ae711100b265a981dfdc73c5fd6) # Conflicts: # erpnext/assets/doctype/asset/test_asset.py --- erpnext/assets/doctype/asset/test_asset.py | 624 +++++++++++---------- 1 file changed, 315 insertions(+), 309 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index b0bac887daa..672be336087 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -18,13 +18,13 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( ) from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt - -class TestAsset(unittest.TestCase): +class AssetSetup(unittest.TestCase): def setUp(self): set_depreciation_settings_in_company() create_asset_data() frappe.db.sql("delete from `tabTax Rule`") +class TestAsset(AssetSetup): def test_purchase_asset(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") @@ -87,287 +87,6 @@ class TestAsset(unittest.TestCase): doc.set_missing_values() self.assertEqual(doc.items[0].is_fixed_asset, 1) - def test_schedule_for_straight_line_method(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-01-01' - asset.purchase_date = '2030-01-01' - - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save() - - self.assertEqual(asset.status, "Draft") - expected_schedules = [ - ["2030-12-31", 30000.00, 30000.00], - ["2031-12-31", 30000.00, 60000.00], - ["2032-12-31", 30000.00, 90000.00] - ] - - schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in asset.get("schedules")] - - self.assertEqual(schedules, expected_schedules) - - def test_schedule_for_straight_line_method_for_existing_asset(self): - create_asset(is_existing_asset=1) - asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) - asset.calculate_depreciation = 1 - asset.number_of_depreciations_booked = 1 - asset.opening_accumulated_depreciation = 40000 - asset.available_for_use_date = "2030-06-06" - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - self.assertEqual(asset.status, "Draft") - asset.save() - expected_schedules = [ - ["2030-12-31", 14246.58, 54246.58], - ["2031-12-31", 25000.00, 79246.58], - ["2032-06-06", 10753.42, 90000.00] - ] - schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] - for d in asset.get("schedules")] - - self.assertEqual(schedules, expected_schedules) - - def test_schedule_for_double_declining_method(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-01-01' - asset.purchase_date = '2030-01-01' - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Double Declining Balance", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": '2030-12-31' - }) - asset.save() - self.assertEqual(asset.status, "Draft") - - expected_schedules = [ - ['2030-12-31', 66667.00, 66667.00], - ['2031-12-31', 22222.11, 88889.11], - ['2032-12-31', 1110.89, 90000.0] - ] - - schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in asset.get("schedules")] - - self.assertEqual(schedules, expected_schedules) - - def test_schedule_for_double_declining_method_for_existing_asset(self): - create_asset(is_existing_asset = 1) - 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 - asset.available_for_use_date = '2030-01-01' - asset.purchase_date = '2029-11-30' - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Double Declining Balance", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save() - self.assertEqual(asset.status, "Draft") - - expected_schedules = [ - ["2030-12-31", 33333.50, 83333.50], - ["2031-12-31", 6666.50, 90000.0] - ] - - schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] - for d in asset.get("schedules")] - - self.assertEqual(schedules, expected_schedules) - - def test_schedule_for_prorated_straight_line_method(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.purchase_date = '2030-01-30' - asset.is_existing_asset = 0 - asset.available_for_use_date = "2030-01-30" - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - - asset.save() - - expected_schedules = [ - ["2030-12-31", 27534.25, 27534.25], - ["2031-12-31", 30000.0, 57534.25], - ["2032-12-31", 30000.0, 87534.25], - ["2033-01-30", 2465.75, 90000.0] - ] - - schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] - for d in asset.get("schedules")] - - self.assertEqual(schedules, expected_schedules) - - def test_depreciation(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.purchase_date = '2020-01-30' - asset.available_for_use_date = "2020-01-30" - 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" - }) - asset.submit() - asset.load_from_db() - self.assertEqual(asset.status, "Submitted") - - frappe.db.set_value("Company", "_Test Company", "series_for_depreciation_entry", "DEPR-") - post_depreciation_entries(date="2021-01-01") - asset.load_from_db() - - # check depreciation entry series - self.assertEqual(asset.get("schedules")[0].journal_entry[:4], "DEPR") - - expected_gle = ( - ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0), - ("_Test Depreciations - _TC", 30000.0, 0.0) - ) - - gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` - where against_voucher_type='Asset' and against_voucher = %s - order by account""", asset.name) - - self.assertEqual(gle, expected_gle) - self.assertEqual(asset.get("value_after_depreciation"), 0) - - # WDV: Written Down Value - def test_depreciation_entry_for_wdv_without_pro_rata(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=8000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-01-01' - asset.purchase_date = '2030-01-01' - asset.append("finance_books", { - "expected_value_after_useful_life": 1000, - "depreciation_method": "Written Down Value", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save(ignore_permissions=True) - - self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) - - expected_schedules = [ - ["2030-12-31", 4000.00, 4000.00], - ["2031-12-31", 2000.00, 6000.00], - ["2032-12-31", 1000.00, 7000.0], - ] - - schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] - for d in asset.get("schedules")] - - self.assertEqual(schedules, expected_schedules) - - def test_pro_rata_depreciation_entry_for_wdv(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=8000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-06-06' - asset.purchase_date = '2030-01-01' - asset.append("finance_books", { - "expected_value_after_useful_life": 1000, - "depreciation_method": "Written Down Value", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save(ignore_permissions=True) - - self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) - - expected_schedules = [ - ["2030-12-31", 2279.45, 2279.45], - ["2031-12-31", 2860.28, 5139.73], - ["2032-12-31", 1430.14, 6569.87], - ["2033-06-06", 430.13, 7000.0], - ] - - schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] - for d in asset.get("schedules")] - - self.assertEqual(schedules, expected_schedules) - - def test_depreciation_entry_cancellation(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-06-06' - asset.purchase_date = '2020-06-06' - 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" - }) - asset.submit() - post_depreciation_entries(date="2021-01-01") - - asset.load_from_db() - - # cancel depreciation entry - depr_entry = asset.get("schedules")[0].journal_entry - self.assertTrue(depr_entry) - frappe.get_doc("Journal Entry", depr_entry).cancel() - - asset.load_from_db() - depr_entry = asset.get("schedules")[0].journal_entry - self.assertFalse(depr_entry) - def test_scrap_asset(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") @@ -410,7 +129,7 @@ class TestAsset(unittest.TestCase): self.assertFalse(asset.journal_entry_for_scrap) self.assertEqual(asset.status, "Partially Depreciated") - def test_asset_sale(self): + def test_gle_made_by_asset_sale(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") @@ -454,30 +173,6 @@ class TestAsset(unittest.TestCase): si.cancel() self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated") - def test_asset_expected_value_after_useful_life(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-06-06' - asset.purchase_date = '2020-06-06' - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 10 - }) - asset.save() - accumulated_depreciation_after_full_schedule = \ - max(d.accumulated_depreciation_amount for d in asset.get("schedules")) - - asset_value_after_full_schedule = (flt(asset.gross_purchase_amount) - - flt(accumulated_depreciation_after_full_schedule)) - - self.assertTrue(asset.finance_books[0].expected_value_after_useful_life >= asset_value_after_full_schedule) - # CWIP: Capital Work In Progress def test_cwip_accounting(self): pr = make_purchase_receipt(item_code="Macbook Pro", @@ -637,6 +332,220 @@ class TestAsset(unittest.TestCase): frappe.db.set_value("Asset Category Account", name, "capital_work_in_progress_account", cwip_acc) frappe.db.get_value("Company", "_Test Company", "capital_work_in_progress_account", cwip_acc) +class TestDepreciationMethods(AssetSetup): + def test_schedule_for_straight_line_method(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2030-01-01' + + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.save() + + self.assertEqual(asset.status, "Draft") + expected_schedules = [ + ["2030-12-31", 30000.00, 30000.00], + ["2031-12-31", 30000.00, 60000.00], + ["2032-12-31", 30000.00, 90000.00] + ] + + schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_schedule_for_straight_line_method_for_existing_asset(self): + create_asset(is_existing_asset=1) + asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) + asset.calculate_depreciation = 1 + asset.number_of_depreciations_booked = 1 + asset.opening_accumulated_depreciation = 40000 + asset.available_for_use_date = "2030-06-06" + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + self.assertEqual(asset.status, "Draft") + asset.save() + expected_schedules = [ + ["2030-12-31", 14246.58, 54246.58], + ["2031-12-31", 25000.00, 79246.58], + ["2032-06-06", 10753.42, 90000.00] + ] + schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_schedule_for_double_declining_method(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2030-01-01' + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Double Declining Balance", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": '2030-12-31' + }) + asset.save() + self.assertEqual(asset.status, "Draft") + + expected_schedules = [ + ['2030-12-31', 66667.00, 66667.00], + ['2031-12-31', 22222.11, 88889.11], + ['2032-12-31', 1110.89, 90000.0] + ] + + schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_schedule_for_double_declining_method_for_existing_asset(self): + create_asset(is_existing_asset = 1) + 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 + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2029-11-30' + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Double Declining Balance", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.save() + self.assertEqual(asset.status, "Draft") + + expected_schedules = [ + ["2030-12-31", 33333.50, 83333.50], + ["2031-12-31", 6666.50, 90000.0] + ] + + schedules = [[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + def test_schedule_for_prorated_straight_line_method(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.purchase_date = '2030-01-30' + asset.is_existing_asset = 0 + asset.available_for_use_date = "2030-01-30" + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + + asset.save() + + expected_schedules = [ + ["2030-12-31", 27534.25, 27534.25], + ["2031-12-31", 30000.0, 57534.25], + ["2032-12-31", 30000.0, 87534.25], + ["2033-01-30", 2465.75, 90000.0] + ] + + schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + # WDV: Written Down Value method + def test_depreciation_entry_for_wdv_without_pro_rata(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=8000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.available_for_use_date = '2030-01-01' + asset.purchase_date = '2030-01-01' + asset.append("finance_books", { + "expected_value_after_useful_life": 1000, + "depreciation_method": "Written Down Value", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.save(ignore_permissions=True) + + self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) + + expected_schedules = [ + ["2030-12-31", 4000.00, 4000.00], + ["2031-12-31", 2000.00, 6000.00], + ["2032-12-31", 1000.00, 7000.0], + ] + + schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + + # WDV: Written Down Value method + def test_pro_rata_depreciation_entry_for_wdv(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=8000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.available_for_use_date = '2030-06-06' + asset.purchase_date = '2030-01-01' + asset.append("finance_books", { + "expected_value_after_useful_life": 1000, + "depreciation_method": "Written Down Value", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 12, + "depreciation_start_date": "2030-12-31" + }) + asset.save(ignore_permissions=True) + + self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) + + expected_schedules = [ + ["2030-12-31", 2279.45, 2279.45], + ["2031-12-31", 2860.28, 5139.73], + ["2032-12-31", 1430.14, 6569.87], + ["2033-06-06", 430.13, 7000.0], + ] + + schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] + for d in asset.get("schedules")] + + self.assertEqual(schedules, expected_schedules) + def test_discounted_wdv_depreciation_rate_for_indian_region(self): # set indian company company_flag = frappe.flags.company @@ -682,6 +591,7 @@ class TestAsset(unittest.TestCase): # reset indian company frappe.flags.company = company_flag +<<<<<<< HEAD <<<<<<< HEAD def test_expected_value_change(self): """ @@ -704,6 +614,9 @@ class TestAsset(unittest.TestCase): asset.reload() self.assertEquals(asset.finance_books[0].value_after_depreciation, 98000.0) ======= +======= +class TestDepreciationBasics(AssetSetup): +>>>>>>> c84c983073 (fix: Categorize into test suites) def test_depreciation_without_pro_rata(self): asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, @@ -837,7 +750,7 @@ class TestAsset(unittest.TestCase): has_pro_rata = asset.check_is_pro_rata(asset.finance_books[0]) self.assertTrue(has_pro_rata) - def test_expected_value_after_useful_life(self): + def test_expected_value_after_useful_life_greater_than_purchase_amount(self): """Tests if an error is raised when expected_value_after_useful_life(110,000) > gross_purchase_amount(100,000).""" asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, @@ -948,6 +861,99 @@ class TestAsset(unittest.TestCase): self.assertEqual(len(asset.schedules), 1) >>>>>>> 40ec2d622b (fix: Add tests for depreciation) + def test_depreciation_entry_cancellation(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.available_for_use_date = '2020-06-06' + asset.purchase_date = '2020-06-06' + 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" + }) + asset.submit() + post_depreciation_entries(date="2021-01-01") + + asset.load_from_db() + + # cancel depreciation entry + depr_entry = asset.get("schedules")[0].journal_entry + self.assertTrue(depr_entry) + frappe.get_doc("Journal Entry", depr_entry).cancel() + + asset.load_from_db() + depr_entry = asset.get("schedules")[0].journal_entry + self.assertFalse(depr_entry) + + def test_asset_expected_value_after_useful_life(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.available_for_use_date = '2020-06-06' + asset.purchase_date = '2020-06-06' + asset.append("finance_books", { + "expected_value_after_useful_life": 10000, + "depreciation_method": "Straight Line", + "total_number_of_depreciations": 3, + "frequency_of_depreciation": 10 + }) + asset.save() + accumulated_depreciation_after_full_schedule = \ + max(d.accumulated_depreciation_amount for d in asset.get("schedules")) + + asset_value_after_full_schedule = (flt(asset.gross_purchase_amount) - + flt(accumulated_depreciation_after_full_schedule)) + + self.assertTrue(asset.finance_books[0].expected_value_after_useful_life >= asset_value_after_full_schedule) + + def test_gle_made_by_depreciation_entries(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=1, rate=100000.0, location="Test Location") + + asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') + asset = frappe.get_doc('Asset', asset_name) + asset.calculate_depreciation = 1 + asset.purchase_date = '2020-01-30' + asset.available_for_use_date = "2020-01-30" + 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" + }) + asset.submit() + asset.load_from_db() + self.assertEqual(asset.status, "Submitted") + + frappe.db.set_value("Company", "_Test Company", "series_for_depreciation_entry", "DEPR-") + post_depreciation_entries(date="2021-01-01") + asset.load_from_db() + + # check depreciation entry series + self.assertEqual(asset.get("schedules")[0].journal_entry[:4], "DEPR") + + expected_gle = ( + ("_Test Accumulated Depreciations - _TC", 0.0, 30000.0), + ("_Test Depreciations - _TC", 30000.0, 0.0) + ) + + gle = frappe.db.sql("""select account, debit, credit from `tabGL Entry` + where against_voucher_type='Asset' and against_voucher = %s + order by account""", asset.name) + + self.assertEqual(gle, expected_gle) + self.assertEqual(asset.get("value_after_depreciation"), 0) + def create_asset_data(): if not frappe.db.exists("Asset Category", "Computers"): create_asset_category() From d189ea8d37f337a476361a757397de20c17a4240 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 5 Oct 2021 21:38:39 +0530 Subject: [PATCH 12/40] fix: Rename tests (cherry picked from commit 62fea8a5aa02b14e05eeb7aa5eb6496d65ceef2d) --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 46349b1abaf..99571ffca3b 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2192,7 +2192,7 @@ class TestSalesInvoice(unittest.TestCase): check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1)) enable_discount_accounting(enable=0) - def test_asset_depreciation_on_sale(self): + def test_asset_depreciation_on_sale_with_pro_rata(self): """ Tests if an Asset set to depreciate yearly on June 30, that gets sold on Sept 30, creates an additional depreciation entry on its date of sale. """ @@ -2216,7 +2216,7 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) self.assertTrue(schedule.journal_entry) - def test_depreciation_on_sale_for_depreciated_asset(self): + def test_asset_depreciation_on_sale_without_pro_rata(self): """ Tests if an Asset set to depreciate yearly on Dec 31, that gets sold on Dec 31 after two years, created an additional depreciation entry on its date of sale. """ From 4735162bdc52c2593c9729b1b415a796cceeb3aa Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 6 Oct 2021 01:18:05 +0530 Subject: [PATCH 13/40] fix: Unlink Depreciation Entry made on sale if the Asset is returned (cherry picked from commit f51bd44929275949652dfc97f1b5a8107f64e6cf) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 9cecac07783..62dd6417391 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1051,10 +1051,15 @@ class SalesInvoice(SellingController): if schedule.schedule_date == posting_date_of_original_invoice: if not self.sale_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_original_invoice) \ or self.sale_happens_in_the_future(posting_date_of_original_invoice): + reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) reverse_journal_entry.posting_date = nowdate() reverse_journal_entry.submit() + asset.flags.ignore_validate_update_after_submit = True + schedule.journal_entry = None + asset.save() + def get_posting_date_of_sales_invoice(self): return frappe.db.get_value('Sales Invoice', self.return_against, 'posting_date') From 53789ae4d66c7be31c76b93d1c9b5718f5567e01 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 6 Oct 2021 02:04:05 +0530 Subject: [PATCH 14/40] fix: Adjust depreciation_amount in final row (cherry picked from commit adebf2d71b2336037e45e85b214920e1f91deaae) --- erpnext/assets/doctype/asset/asset.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index ebeecba8833..45cf507611a 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -255,11 +255,15 @@ class Asset(AccountsController): self.to_date = add_months(self.available_for_use_date, n * cint(d.frequency_of_depreciation)) + depreciation_amount_without_pro_rata = depreciation_amount + depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount, schedule_date, self.to_date) - monthly_schedule_date = add_months(schedule_date, 1) + depreciation_amount = self.get_adjusted_depreciation_amount(depreciation_amount_without_pro_rata, + depreciation_amount, d.finance_book) + monthly_schedule_date = add_months(schedule_date, 1) schedule_date = add_days(schedule_date, days) last_schedule_date = schedule_date @@ -395,6 +399,27 @@ class Asset(AccountsController): frappe.throw(_("Depreciation Row {0}: Next Depreciation Date cannot be before Available-for-use Date") .format(row.idx)) + # to ensure that final accumulated depreciation amount is accurate + def get_adjusted_depreciation_amount(self, depreciation_amount_without_pro_rata, depreciation_amount_for_last_row, finance_book): + depreciation_amount_for_first_row = self.get_depreciation_amount_for_first_row(finance_book) + + if depreciation_amount_for_first_row + depreciation_amount_for_last_row != depreciation_amount_without_pro_rata: + depreciation_amount_for_last_row = depreciation_amount_without_pro_rata - depreciation_amount_for_first_row + + return depreciation_amount_for_last_row + + def get_depreciation_amount_for_first_row(self, finance_book): + if self.has_only_one_finance_book(): + return self.schedules[0].depreciation_amount + else: + for schedule in self.schedules: + if schedule.finance_book == finance_book: + return schedule.depreciation_amount + + def has_only_one_finance_book(self): + if len(self.finance_books) == 1: + return True + def set_accumulated_depreciation(self, date_of_sale=None, date_of_return=None, ignore_booked_entry = False): straight_line_idx = [d.idx for d in self.get("schedules") if d.depreciation_method == 'Straight Line'] finance_books = [] From 5972acf0ec23d347a9ed237f011ea033a89259ed Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 6 Oct 2021 02:08:28 +0530 Subject: [PATCH 15/40] fix: Add test for depreciation on return of sold Asset (cherry picked from commit 273fccf0ddfd5e6d79150b0a2c7e010b12753e21) --- .../sales_invoice/test_sales_invoice.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 99571ffca3b..6696d4ad2a8 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2242,6 +2242,33 @@ class TestSalesInvoice(unittest.TestCase): self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) self.assertTrue(schedule.journal_entry) + def test_depreciation_on_return_of_sold_asset(self): + from erpnext.controllers.sales_and_purchase_return import make_return_doc + + create_asset_data() + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, submit=1) + post_depreciation_entries(getdate("2021-09-30")) + + si = create_sales_invoice(item_code="Macbook Pro", asset=asset.name, qty=1, rate=90000, posting_date=getdate("2021-09-30")) + return_si = make_return_doc("Sales Invoice", si.name) + return_si.submit() + asset.load_from_db() + + expected_values = [ + ["2020-06-30", 1311.48, 1311.48, True], + ["2021-06-30", 20000.0, 21311.48, True], + ["2022-06-30", 20000.0, 41311.48, False], + ["2023-06-30", 20000.0, 61311.48, False], + ["2024-06-30", 20000.0, 81311.48, False], + ["2025-06-06", 18688.52, 100000.0, False] + ] + + for i, schedule in enumerate(asset.schedules): + self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) + self.assertEqual(expected_values[i][1], schedule.depreciation_amount) + self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) + self.assertEqual(schedule.journal_entry, schedule.journal_entry) + def test_sales_invoice_against_supplier(self): from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import ( make_customer, From e28a7f11b76b3c2f6b5415014e2f7249d3a22eef Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Sun, 10 Oct 2021 03:50:45 +0530 Subject: [PATCH 16/40] fix: Replace setUp() with setUpClass() (cherry picked from commit ef3f2fcb3a9ccd4be37b9359b31458ba48e91865) --- erpnext/assets/doctype/asset/test_asset.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 672be336087..99d997a39e2 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -19,7 +19,8 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt class AssetSetup(unittest.TestCase): - def setUp(self): + @classmethod + def setUpClass(cls): set_depreciation_settings_in_company() create_asset_data() frappe.db.sql("delete from `tabTax Rule`") From 3cc8dd2b47682a8579a366c7de5faa779085d297 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Sun, 10 Oct 2021 03:51:35 +0530 Subject: [PATCH 17/40] fix: Add tearDownClass() (cherry picked from commit 4918e9533b10bbc56461a5514d9e8556352d7dd2) --- erpnext/assets/doctype/asset/test_asset.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 99d997a39e2..641f13e4db9 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -25,6 +25,10 @@ class AssetSetup(unittest.TestCase): create_asset_data() frappe.db.sql("delete from `tabTax Rule`") + @classmethod + def tearDownClass(cls): + frappe.db.rollback() + class TestAsset(AssetSetup): def test_purchase_asset(self): pr = make_purchase_receipt(item_code="Macbook Pro", From d81f4e625af16e301a379521360689ff55436119 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 12 Oct 2021 01:07:11 +0530 Subject: [PATCH 18/40] fix: Add tests to validate Asset values (cherry picked from commit d8aaf3d389366544b39c05d26e0bc29312f0e797) --- erpnext/assets/doctype/asset/test_asset.py | 62 +++++++++++++++++++--- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 641f13e4db9..642a6ae7011 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -30,6 +30,49 @@ class AssetSetup(unittest.TestCase): frappe.db.rollback() class TestAsset(AssetSetup): + def test_asset_category_is_fetched(self): + """Tests if the Item's Asset Category value is assigned to the Asset, if the field is empty.""" + + asset = create_asset(item_code="Macbook Pro", do_not_save=1) + asset.asset_category = None + asset.save() + + self.assertEqual(asset.asset_category, "Computers") + + def test_gross_purchase_amount_is_mandatory(self): + asset = create_asset(item_code="Macbook Pro", do_not_save=1) + asset.gross_purchase_amount = 0 + + self.assertRaises(frappe.MandatoryError, asset.save) + + def test_pr_or_pi_mandatory_if_not_existing_asset(self): + """Tests if either PI or PR is present if CWIP is enabled and is_existing_asset=0.""" + + asset = create_asset(item_code="Macbook Pro", do_not_save=1) + enable_cwip_accounting(asset.asset_category) + asset.is_existing_asset=0 + + self.assertRaises(frappe.ValidationError, asset.save) + + enable_cwip_accounting(asset.asset_category, enable=0) + + def test_finance_books_are_present_if_calculate_depreciation_is_enabled(self): + asset = create_asset(item_code="Macbook Pro", do_not_save=1) + asset.calculate_depreciation = 1 + + self.assertRaises(frappe.ValidationError, asset.save) + + # def test_available_for_use_date_is_after_purchase_date(self): + # pr = make_purchase_receipt(item_code="Macbook Pro", + # qty=1, rate=100000.0, location="Test Location", posting_date=add_days(nowdate(), -15)) + + # asset = create_asset(item_code="Macbook Pro", do_not_save=1) + # asset.is_existing_asset = 0 + # asset.purchase_receipt = pr + # asset.available_for_use_date = nowdate() + + # self.assertRaises(frappe.ValidationError, asset.save) + def test_purchase_asset(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") @@ -980,20 +1023,20 @@ def create_asset(**args): asset = frappe.get_doc({ "doctype": "Asset", "asset_name": args.asset_name or "Macbook Pro 1", - "asset_category": "Computers", + "asset_category": args.asset_category or "Computers", "item_code": args.item_code or "Macbook Pro", - "company": args.company or"_Test Company", - "purchase_date": "2015-01-01", + "company": args.company or "_Test Company", + "purchase_date": args.purchase_date or "2015-01-01", "calculate_depreciation": args.calculate_depreciation or 0, "opening_accumulated_depreciation": args.opening_accumulated_depreciation or 0, "number_of_depreciations_booked": args.number_of_depreciations_booked or 0, - "gross_purchase_amount": 100000, - "purchase_receipt_amount": 100000, + "gross_purchase_amount": args.gross_purchase_amount or 100000, + "purchase_receipt_amount": args.purchase_receipt_amount or 100000, "warehouse": args.warehouse or "_Test Warehouse - _TC", "available_for_use_date": args.available_for_use_date or "2020-06-06", - "location": "Test Location", - "asset_owner": "Company", - "is_existing_asset": 1 + "location": args.location or "Test Location", + "asset_owner": args.asset_owner or "Company", + "is_existing_asset": args.is_existing_asset or 1 }) if asset.calculate_depreciation: @@ -1060,3 +1103,6 @@ def set_depreciation_settings_in_company(): # Enable booking asset depreciation entry automatically frappe.db.set_value("Accounts Settings", None, "book_asset_depreciation_entry_automatically", 1) + +def enable_cwip_accounting(asset_category, enable=1): + frappe.db.set_value("Asset Category", asset_category, "enable_cwip_accounting", enable) From 86fcc94b7aa63a9cf5050bb53a5691238fb6caf8 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 12 Oct 2021 01:33:46 +0530 Subject: [PATCH 19/40] fix: Add tests to validate item (cherry picked from commit a7ec007dcff77f99d1af9e8f8c473cba629f6efe) --- erpnext/assets/doctype/asset/test_asset.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 642a6ae7011..646125437d2 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -73,6 +73,27 @@ class TestAsset(AssetSetup): # self.assertRaises(frappe.ValidationError, asset.save) + def test_item_exists(self): + asset = create_asset(item_code="MacBook", do_not_save=1) + + self.assertRaises(frappe.DoesNotExistError, asset.save) + + def test_validate_item(self): + asset = create_asset(item_code="MacBook Pro", do_not_save=1) + item = frappe.get_doc("Item", "MacBook Pro") + + item.disabled = 1 + item.save() + self.assertRaises(frappe.ValidationError, asset.save) + item.disabled = 0 + + item.is_fixed_asset = 0 + self.assertRaises(frappe.ValidationError, asset.save) + item.is_fixed_asset = 1 + + item.is_stock_item = 1 + self.assertRaises(frappe.ValidationError, asset.save) + def test_purchase_asset(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") From e1f4672023b946e3d767ac5555d8de383f212260 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 13 Oct 2021 20:47:39 +0530 Subject: [PATCH 20/40] fix: Only validate against JV if it's not a reverse depreciation entry (cherry picked from commit 8ea1ad9232ceac388c3fc4117752af3fa6880276) --- erpnext/accounts/doctype/journal_entry/journal_entry.py | 6 ++++-- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index b6c4425fd6d..bb8e1e046a5 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -57,7 +57,10 @@ class JournalEntry(AccountsController): if not frappe.flags.in_import: self.validate_total_debit_and_credit() - self.validate_against_jv() + if not self.flags.is_reverse_depr_entry: + self.validate_against_jv() + self.validate_stock_accounts() + self.validate_reference_doc() if self.docstatus == 0: self.set_against_account() @@ -68,7 +71,6 @@ class JournalEntry(AccountsController): self.validate_empty_accounts_table() self.set_account_and_party_balance() self.validate_inter_company_accounts() - self.validate_stock_accounts() if self.docstatus == 0: self.apply_tax_withholding() diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 62dd6417391..123d7782b6f 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1054,6 +1054,7 @@ class SalesInvoice(SellingController): reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) reverse_journal_entry.posting_date = nowdate() + reverse_journal_entry.flags.is_reverse_depr_entry = True reverse_journal_entry.submit() asset.flags.ignore_validate_update_after_submit = True From 0442230d9805b7f2867fe4263a03526ea7e5e02a Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 13 Oct 2021 20:49:07 +0530 Subject: [PATCH 21/40] fix: Enable cwip accounting (cherry picked from commit 749d1b6ee68603984c99045c3d4115678523893e) --- erpnext/assets/doctype/asset/test_asset.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 646125437d2..fb905baf6ae 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -23,6 +23,7 @@ class AssetSetup(unittest.TestCase): def setUpClass(cls): set_depreciation_settings_in_company() create_asset_data() + enable_cwip_accounting("Computers") frappe.db.sql("delete from `tabTax Rule`") @classmethod @@ -49,13 +50,10 @@ class TestAsset(AssetSetup): """Tests if either PI or PR is present if CWIP is enabled and is_existing_asset=0.""" asset = create_asset(item_code="Macbook Pro", do_not_save=1) - enable_cwip_accounting(asset.asset_category) asset.is_existing_asset=0 self.assertRaises(frappe.ValidationError, asset.save) - enable_cwip_accounting(asset.asset_category, enable=0) - def test_finance_books_are_present_if_calculate_depreciation_is_enabled(self): asset = create_asset(item_code="Macbook Pro", do_not_save=1) asset.calculate_depreciation = 1 @@ -328,7 +326,6 @@ class TestAsset(AssetSetup): def test_expense_head(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=2, rate=200000.0, location="Test Location") - doc = make_invoice(pr.name) self.assertEqual('Asset Received But Not Billed - _TC', doc.items[0].expense_account) From 026d72aff8bc188c1dc9facbb9737c6374462f40 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 13 Oct 2021 21:21:50 +0530 Subject: [PATCH 22/40] fix: Add test to validate available_for_use_date (cherry picked from commit 83ec9879ee963c3e8b3b7551df93679eb3643689) --- erpnext/assets/doctype/asset/test_asset.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index fb905baf6ae..36a91d9b00c 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -60,16 +60,17 @@ class TestAsset(AssetSetup): self.assertRaises(frappe.ValidationError, asset.save) - # def test_available_for_use_date_is_after_purchase_date(self): - # pr = make_purchase_receipt(item_code="Macbook Pro", - # qty=1, rate=100000.0, location="Test Location", posting_date=add_days(nowdate(), -15)) + def test_available_for_use_date_is_after_purchase_date(self): + pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, + location="Test Location", posting_date=getdate("2021-10-10")) - # asset = create_asset(item_code="Macbook Pro", do_not_save=1) - # asset.is_existing_asset = 0 - # asset.purchase_receipt = pr - # asset.available_for_use_date = nowdate() + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, do_not_save=1) + asset.is_existing_asset = 0 + asset.purchase_receipt = pr.name + asset.purchase_date = getdate("2021-10-10") + asset.available_for_use_date = getdate("2021-10-1") - # self.assertRaises(frappe.ValidationError, asset.save) + self.assertRaises(frappe.ValidationError, asset.save) def test_item_exists(self): asset = create_asset(item_code="MacBook", do_not_save=1) From 511c742fd982e08ae7ee69e1c2f3b5bbdd652f37 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 13 Oct 2021 21:36:10 +0530 Subject: [PATCH 23/40] fix: Move test for Finance Books to Depreciation test suite (cherry picked from commit e8986df3cafa49d1b317429036f4c145ca4f8d86) --- erpnext/assets/doctype/asset/test_asset.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 36a91d9b00c..740ec1d4e81 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -54,12 +54,6 @@ class TestAsset(AssetSetup): self.assertRaises(frappe.ValidationError, asset.save) - def test_finance_books_are_present_if_calculate_depreciation_is_enabled(self): - asset = create_asset(item_code="Macbook Pro", do_not_save=1) - asset.calculate_depreciation = 1 - - self.assertRaises(frappe.ValidationError, asset.save) - def test_available_for_use_date_is_after_purchase_date(self): pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location", posting_date=getdate("2021-10-10")) @@ -881,6 +875,12 @@ class TestDepreciationBasics(AssetSetup): self.assertRaises(frappe.ValidationError, asset.save) + def test_finance_books_are_present_if_calculate_depreciation_is_enabled(self): + asset = create_asset(item_code="Macbook Pro", do_not_save=1) + asset.calculate_depreciation = 1 + + self.assertRaises(frappe.ValidationError, asset.save) + def test_post_depreciation_entries(self): """Tests if post_depreciation_entries() works as expected.""" From 627d9633b2118c0c36ff64f221794f8aad90c07a Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Thu, 14 Oct 2021 20:28:57 +0530 Subject: [PATCH 24/40] fix: Move Purchase Receipt creation to setUpClass (cherry picked from commit 4bf01bb4b7b6770b5f957824d912397b1556f168) --- erpnext/assets/doctype/asset/test_asset.py | 56 ++++++---------------- 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 740ec1d4e81..b8ab9682d49 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -24,6 +24,7 @@ class AssetSetup(unittest.TestCase): set_depreciation_settings_in_company() create_asset_data() enable_cwip_accounting("Computers") + make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location") frappe.db.sql("delete from `tabTax Rule`") @classmethod @@ -55,12 +56,8 @@ class TestAsset(AssetSetup): self.assertRaises(frappe.ValidationError, asset.save) def test_available_for_use_date_is_after_purchase_date(self): - pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=100000.0, - location="Test Location", posting_date=getdate("2021-10-10")) - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, do_not_save=1) asset.is_existing_asset = 0 - asset.purchase_receipt = pr.name asset.purchase_date = getdate("2021-10-10") asset.available_for_use_date = getdate("2021-10-1") @@ -150,21 +147,9 @@ class TestAsset(AssetSetup): self.assertEqual(doc.items[0].is_fixed_asset, 1) def test_scrap_asset(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-01-01' - asset.purchase_date = '2020-01-01' - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 10, - "frequency_of_depreciation": 1 - }) - asset.submit() + asset = create_asset(calculate_depreciation=1, available_for_use_date='2020-01-01', + purchase_date = '2020-01-01', expected_value_after_useful_life=10000, + total_number_of_depreciations=10, frequency_of_depreciation=1, submit=1) post_depreciation_entries(date=add_months('2020-01-01', 4)) @@ -192,22 +177,11 @@ class TestAsset(AssetSetup): self.assertEqual(asset.status, "Partially Depreciated") def test_gle_made_by_asset_sale(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") + asset = create_asset(calculate_depreciation=1, available_for_use_date='2020-06-06', + purchase_date = '2020-01-01', expected_value_after_useful_life=10000, + total_number_of_depreciations=3, frequency_of_depreciation=10, + depreciation_start_date='2020-12-31', submit=1) - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-06-06' - asset.purchase_date = '2020-06-06' - 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" - }) - asset.submit() post_depreciation_entries(date="2021-01-01") si = make_sales_invoice(asset=asset.name, item_code="Macbook Pro", company="_Test Company") @@ -235,6 +209,13 @@ class TestAsset(AssetSetup): si.cancel() self.assertEqual(frappe.db.get_value("Asset", asset.name, "status"), "Partially Depreciated") + def test_expense_head(self): + pr = make_purchase_receipt(item_code="Macbook Pro", + qty=2, rate=200000.0, location="Test Location") + doc = make_invoice(pr.name) + + self.assertEqual('Asset Received But Not Billed - _TC', doc.items[0].expense_account) + # CWIP: Capital Work In Progress def test_cwip_accounting(self): pr = make_purchase_receipt(item_code="Macbook Pro", @@ -318,13 +299,6 @@ class TestAsset(AssetSetup): self.assertEqual(gle, expected_gle) - def test_expense_head(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=2, rate=200000.0, location="Test Location") - doc = make_invoice(pr.name) - - self.assertEqual('Asset Received But Not Billed - _TC', doc.items[0].expense_account) - def test_asset_cwip_toggling_cases(self): cwip = frappe.db.get_value("Asset Category", "Computers", "enable_cwip_accounting") name = frappe.db.get_value("Asset Category Account", filters={"parent": "Computers"}, fieldname=["name"]) From 38ec9c80fcad2a918f4e13bfe02efa2a77378309 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Thu, 14 Oct 2021 22:15:10 +0530 Subject: [PATCH 25/40] fix: Remove PR creation from all tests for Depreciation Methods (cherry picked from commit 09215a9781379e78b78b3d7e5a5c6546558256a6) # Conflicts: # erpnext/assets/doctype/asset/test_asset.py --- erpnext/assets/doctype/asset/test_asset.py | 181 +++++++-------------- 1 file changed, 57 insertions(+), 124 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index b8ab9682d49..79c68a9f157 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -369,23 +369,10 @@ class TestAsset(AssetSetup): class TestDepreciationMethods(AssetSetup): def test_schedule_for_straight_line_method(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-01-01' - asset.purchase_date = '2030-01-01' - - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save() + asset = create_asset(calculate_depreciation=1, + available_for_use_date="2030-01-01", purchase_date="2030-01-01", + expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", + total_number_of_depreciations=3, frequency_of_depreciation=12) self.assertEqual(asset.status, "Draft") expected_schedules = [ @@ -400,21 +387,13 @@ class TestDepreciationMethods(AssetSetup): self.assertEqual(schedules, expected_schedules) def test_schedule_for_straight_line_method_for_existing_asset(self): - create_asset(is_existing_asset=1) - asset = frappe.get_doc("Asset", {"asset_name": "Macbook Pro 1"}) - asset.calculate_depreciation = 1 - asset.number_of_depreciations_booked = 1 - asset.opening_accumulated_depreciation = 40000 - asset.available_for_use_date = "2030-06-06" - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) + asset = create_asset(calculate_depreciation=1, + available_for_use_date="2030-06-06", is_existing_asset=1, + number_of_depreciations_booked = 1, opening_accumulated_depreciation=40000, + expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", + total_number_of_depreciations=3, frequency_of_depreciation=12) + self.assertEqual(asset.status, "Draft") - asset.save() expected_schedules = [ ["2030-12-31", 14246.58, 54246.58], ["2031-12-31", 25000.00, 79246.58], @@ -426,22 +405,12 @@ class TestDepreciationMethods(AssetSetup): self.assertEqual(schedules, expected_schedules) def test_schedule_for_double_declining_method(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") + asset = create_asset(calculate_depreciation=1, + available_for_use_date="2030-01-01", purchase_date="2030-01-01", + depreciation_method="Double Declining Balance", + expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", + total_number_of_depreciations=3, frequency_of_depreciation=12) - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-01-01' - asset.purchase_date = '2030-01-01' - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Double Declining Balance", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": '2030-12-31' - }) - asset.save() self.assertEqual(asset.status, "Draft") expected_schedules = [ @@ -456,22 +425,13 @@ class TestDepreciationMethods(AssetSetup): self.assertEqual(schedules, expected_schedules) def test_schedule_for_double_declining_method_for_existing_asset(self): - create_asset(is_existing_asset = 1) - 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 - asset.available_for_use_date = '2030-01-01' - asset.purchase_date = '2029-11-30' - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Double Declining Balance", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save() + asset = create_asset(calculate_depreciation=1, + available_for_use_date="2030-01-01", is_existing_asset=1, + depreciation_method="Double Declining Balance", + number_of_depreciations_booked = 1, opening_accumulated_depreciation=50000, + expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", + total_number_of_depreciations=3, frequency_of_depreciation=12) + self.assertEqual(asset.status, "Draft") expected_schedules = [ @@ -485,24 +445,11 @@ class TestDepreciationMethods(AssetSetup): self.assertEqual(schedules, expected_schedules) def test_schedule_for_prorated_straight_line_method(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.purchase_date = '2030-01-30' - asset.is_existing_asset = 0 - asset.available_for_use_date = "2030-01-30" - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - - asset.save() + asset = create_asset(calculate_depreciation=1, + available_for_use_date="2030-01-30", purchase_date="2030-01-30", + depreciation_method="Straight Line", + expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", + total_number_of_depreciations=3, frequency_of_depreciation=12) expected_schedules = [ ["2030-12-31", 27534.25, 27534.25], @@ -518,29 +465,18 @@ class TestDepreciationMethods(AssetSetup): # WDV: Written Down Value method def test_depreciation_entry_for_wdv_without_pro_rata(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=8000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-01-01' - asset.purchase_date = '2030-01-01' - asset.append("finance_books", { - "expected_value_after_useful_life": 1000, - "depreciation_method": "Written Down Value", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save(ignore_permissions=True) + asset = create_asset(calculate_depreciation=1, + available_for_use_date="2030-01-01", purchase_date="2030-01-01", + depreciation_method="Written Down Value", + expected_value_after_useful_life=12500, depreciation_start_date="2030-12-31", + total_number_of_depreciations=3, frequency_of_depreciation=12) self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) expected_schedules = [ - ["2030-12-31", 4000.00, 4000.00], - ["2031-12-31", 2000.00, 6000.00], - ["2032-12-31", 1000.00, 7000.0], + ["2030-12-31", 50000.0, 50000.0], + ["2031-12-31", 25000.0, 75000.0], + ["2032-12-31", 12500.0, 87500.0], ] schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] @@ -550,30 +486,19 @@ class TestDepreciationMethods(AssetSetup): # WDV: Written Down Value method def test_pro_rata_depreciation_entry_for_wdv(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=8000.0, location="Test Location") - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-06-06' - asset.purchase_date = '2030-01-01' - asset.append("finance_books", { - "expected_value_after_useful_life": 1000, - "depreciation_method": "Written Down Value", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save(ignore_permissions=True) + asset = create_asset(calculate_depreciation=1, + available_for_use_date="2030-06-06", purchase_date="2030-01-01", + depreciation_method="Written Down Value", + expected_value_after_useful_life=12500, depreciation_start_date="2030-12-31", + total_number_of_depreciations=3, frequency_of_depreciation=12) self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) expected_schedules = [ - ["2030-12-31", 2279.45, 2279.45], - ["2031-12-31", 2860.28, 5139.73], - ["2032-12-31", 1430.14, 6569.87], - ["2033-06-06", 430.13, 7000.0], + ["2030-12-31", 28493.15, 28493.15], + ["2031-12-31", 35753.43, 64246.58], + ["2032-12-31", 17876.71, 82123.29], + ["2033-06-06", 5376.71, 87500.0] ] schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] @@ -586,6 +511,7 @@ class TestDepreciationMethods(AssetSetup): company_flag = frappe.flags.company frappe.flags.company = "_Test Company" +<<<<<<< HEAD pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=8000.0, location="Test Location") @@ -608,14 +534,21 @@ class TestDepreciationMethods(AssetSetup): "depreciation_start_date": "2030-12-31" }) asset.save(ignore_permissions=True) +======= + asset = create_asset(calculate_depreciation=1, + available_for_use_date="2030-07-12", purchase_date="2030-01-01", + depreciation_method="Written Down Value", + expected_value_after_useful_life=12500, depreciation_start_date="2030-12-31", + total_number_of_depreciations=3, frequency_of_depreciation=12) +>>>>>>> 09215a9781 (fix: Remove PR creation from all tests for Depreciation Methods) self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) expected_schedules = [ - ["2030-12-31", 942.47, 942.47], - ["2031-12-31", 3528.77, 4471.24], - ["2032-12-31", 1764.38, 6235.62], - ["2033-07-12", 764.38, 7000.00] + ["2030-12-31", 11780.82, 11780.82], + ["2031-12-31", 44109.59, 55890.41], + ["2032-12-31", 22054.8, 77945.21], + ["2033-07-12", 9554.79, 87500.0] ] schedules = [[cstr(d.schedule_date), flt(d.depreciation_amount, 2), flt(d.accumulated_depreciation_amount, 2)] @@ -1034,7 +967,7 @@ def create_asset(**args): if asset.calculate_depreciation: asset.append("finance_books", { - "depreciation_method": "Straight Line", + "depreciation_method": args.depreciation_method or "Straight Line", "frequency_of_depreciation": args.frequency_of_depreciation or 12, "total_number_of_depreciations": args.total_number_of_depreciations or 5, "expected_value_after_useful_life": args.expected_value_after_useful_life or 0, From a5b8b4ac410858afe22cf74005098dc11716e57a Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Thu, 14 Oct 2021 22:32:27 +0530 Subject: [PATCH 26/40] fix: Remove PR creation from all tests in TestDepreciationBasics (cherry picked from commit 968be70bd1c0011792ea2c3887dc2f794b15d300) # Conflicts: # erpnext/assets/doctype/asset/test_asset.py --- erpnext/assets/doctype/asset/test_asset.py | 76 +++++++--------------- 1 file changed, 23 insertions(+), 53 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 79c68a9f157..6388edbeac6 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -792,17 +792,9 @@ class TestDepreciationBasics(AssetSetup): """Tests if post_depreciation_entries() works as expected.""" asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), do_not_save=1) - - asset.finance_books = [] - asset.append("finance_books", { - "depreciation_method": "Straight Line", - "frequency_of_depreciation": 12, - "total_number_of_depreciations": 3, - "expected_value_after_useful_life": 10000, - "depreciation_start_date": getdate("2020-12-31") - }) - asset.submit() + available_for_use_date="2019-12-31", depreciation_start_date="2020-12-31", + frequency_of_depreciation=12, total_number_of_depreciations=3, + expected_value_after_useful_life=10000, submit=1) post_depreciation_entries(date="2021-06-01") asset.load_from_db() @@ -815,17 +807,9 @@ class TestDepreciationBasics(AssetSetup): """Tests if clear_depreciation_schedule() works as expected.""" asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), do_not_save=1) - - asset.finance_books = [] - asset.append("finance_books", { - "depreciation_method": "Straight Line", - "frequency_of_depreciation": 12, - "total_number_of_depreciations": 3, - "expected_value_after_useful_life": 10000, - "depreciation_start_date": getdate("2020-12-31") - }) - asset.submit() + available_for_use_date="2019-12-31", depreciation_start_date="2020-12-31", + frequency_of_depreciation=12, total_number_of_depreciations=3, + expected_value_after_useful_life=10000, submit=1) post_depreciation_entries(date="2021-06-01") asset.load_from_db() @@ -836,22 +820,12 @@ class TestDepreciationBasics(AssetSetup): >>>>>>> 40ec2d622b (fix: Add tests for depreciation) def test_depreciation_entry_cancellation(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") + asset = create_asset(item_code="Macbook Pro", + calculate_depreciation=1, purchase_date="2020-06-06", + available_for_use_date="2020-06-06", depreciation_start_date="2020-12-31", + frequency_of_depreciation=10, total_number_of_depreciations=3, + expected_value_after_useful_life=10000, submit=1) - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-06-06' - asset.purchase_date = '2020-06-06' - 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" - }) - asset.submit() post_depreciation_entries(date="2021-01-01") asset.load_from_db() @@ -866,21 +840,11 @@ class TestDepreciationBasics(AssetSetup): self.assertFalse(depr_entry) def test_asset_expected_value_after_useful_life(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") + asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, + available_for_use_date="2020-06-06", purchase_date="2020-06-06", + frequency_of_depreciation=10, total_number_of_depreciations=3, + expected_value_after_useful_life=10000) - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2020-06-06' - asset.purchase_date = '2020-06-06' - asset.append("finance_books", { - "expected_value_after_useful_life": 10000, - "depreciation_method": "Straight Line", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 10 - }) - asset.save() accumulated_depreciation_after_full_schedule = \ max(d.accumulated_depreciation_amount for d in asset.get("schedules")) @@ -890,9 +854,13 @@ class TestDepreciationBasics(AssetSetup): self.assertTrue(asset.finance_books[0].expected_value_after_useful_life >= asset_value_after_full_schedule) def test_gle_made_by_depreciation_entries(self): - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=100000.0, location="Test Location") + asset = create_asset(item_code="Macbook Pro", + calculate_depreciation=1, purchase_date="2020-01-30", + available_for_use_date="2020-01-30", depreciation_start_date="2020-12-31", + frequency_of_depreciation=10, total_number_of_depreciations=3, + expected_value_after_useful_life=10000, submit=1) +<<<<<<< HEAD asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') asset = frappe.get_doc('Asset', asset_name) asset.calculate_depreciation = 1 @@ -907,6 +875,8 @@ class TestDepreciationBasics(AssetSetup): }) asset.submit() asset.load_from_db() +======= +>>>>>>> 968be70bd1 (fix: Remove PR creation from all tests in TestDepreciationBasics) self.assertEqual(asset.status, "Submitted") frappe.db.set_value("Company", "_Test Company", "series_for_depreciation_entry", "DEPR-") From db06373fa63457a17279ca981de0a00575832f21 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 15 Oct 2021 01:45:53 +0530 Subject: [PATCH 27/40] fix: Format tests (cherry picked from commit e9d310a13e902d7208a925bb577faba2604cd684) # Conflicts: # erpnext/assets/doctype/asset/test_asset.py --- erpnext/assets/doctype/asset/test_asset.py | 404 ++++++++++++++------- 1 file changed, 272 insertions(+), 132 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 6388edbeac6..6af065d4ef6 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -147,9 +147,15 @@ class TestAsset(AssetSetup): self.assertEqual(doc.items[0].is_fixed_asset, 1) def test_scrap_asset(self): - asset = create_asset(calculate_depreciation=1, available_for_use_date='2020-01-01', - purchase_date = '2020-01-01', expected_value_after_useful_life=10000, - total_number_of_depreciations=10, frequency_of_depreciation=1, submit=1) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = '2020-01-01', + purchase_date = '2020-01-01', + expected_value_after_useful_life = 10000, + total_number_of_depreciations = 10, + frequency_of_depreciation = 1, + submit = 1 + ) post_depreciation_entries(date=add_months('2020-01-01', 4)) @@ -177,10 +183,16 @@ class TestAsset(AssetSetup): self.assertEqual(asset.status, "Partially Depreciated") def test_gle_made_by_asset_sale(self): - asset = create_asset(calculate_depreciation=1, available_for_use_date='2020-06-06', - purchase_date = '2020-01-01', expected_value_after_useful_life=10000, - total_number_of_depreciations=3, frequency_of_depreciation=10, - depreciation_start_date='2020-12-31', submit=1) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = '2020-06-06', + purchase_date = '2020-01-01', + expected_value_after_useful_life = 10000, + total_number_of_depreciations = 3, + frequency_of_depreciation = 10, + depreciation_start_date = '2020-12-31', + submit = 1 + ) post_depreciation_entries(date="2021-01-01") @@ -369,10 +381,15 @@ class TestAsset(AssetSetup): class TestDepreciationMethods(AssetSetup): def test_schedule_for_straight_line_method(self): - asset = create_asset(calculate_depreciation=1, - available_for_use_date="2030-01-01", purchase_date="2030-01-01", - expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", - total_number_of_depreciations=3, frequency_of_depreciation=12) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = "2030-01-01", + purchase_date = "2030-01-01", + expected_value_after_useful_life = 10000, + depreciation_start_date = "2030-12-31", + total_number_of_depreciations = 3, + frequency_of_depreciation = 12 + ) self.assertEqual(asset.status, "Draft") expected_schedules = [ @@ -387,11 +404,17 @@ class TestDepreciationMethods(AssetSetup): self.assertEqual(schedules, expected_schedules) def test_schedule_for_straight_line_method_for_existing_asset(self): - asset = create_asset(calculate_depreciation=1, - available_for_use_date="2030-06-06", is_existing_asset=1, - number_of_depreciations_booked = 1, opening_accumulated_depreciation=40000, - expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", - total_number_of_depreciations=3, frequency_of_depreciation=12) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = "2030-06-06", + is_existing_asset = 1, + number_of_depreciations_booked = 1, + opening_accumulated_depreciation = 40000, + expected_value_after_useful_life = 10000, + depreciation_start_date = "2030-12-31", + total_number_of_depreciations = 3, + frequency_of_depreciation = 12 + ) self.assertEqual(asset.status, "Draft") expected_schedules = [ @@ -405,11 +428,16 @@ class TestDepreciationMethods(AssetSetup): self.assertEqual(schedules, expected_schedules) def test_schedule_for_double_declining_method(self): - asset = create_asset(calculate_depreciation=1, - available_for_use_date="2030-01-01", purchase_date="2030-01-01", - depreciation_method="Double Declining Balance", - expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", - total_number_of_depreciations=3, frequency_of_depreciation=12) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = "2030-01-01", + purchase_date = "2030-01-01", + depreciation_method = "Double Declining Balance", + expected_value_after_useful_life = 10000, + depreciation_start_date = "2030-12-31", + total_number_of_depreciations = 3, + frequency_of_depreciation = 12 + ) self.assertEqual(asset.status, "Draft") @@ -425,12 +453,18 @@ class TestDepreciationMethods(AssetSetup): self.assertEqual(schedules, expected_schedules) def test_schedule_for_double_declining_method_for_existing_asset(self): - asset = create_asset(calculate_depreciation=1, - available_for_use_date="2030-01-01", is_existing_asset=1, - depreciation_method="Double Declining Balance", - number_of_depreciations_booked = 1, opening_accumulated_depreciation=50000, - expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", - total_number_of_depreciations=3, frequency_of_depreciation=12) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = "2030-01-01", + is_existing_asset = 1, + depreciation_method = "Double Declining Balance", + number_of_depreciations_booked = 1, + opening_accumulated_depreciation = 50000, + expected_value_after_useful_life = 10000, + depreciation_start_date = "2030-12-31", + total_number_of_depreciations = 3, + frequency_of_depreciation = 12 + ) self.assertEqual(asset.status, "Draft") @@ -445,11 +479,16 @@ class TestDepreciationMethods(AssetSetup): self.assertEqual(schedules, expected_schedules) def test_schedule_for_prorated_straight_line_method(self): - asset = create_asset(calculate_depreciation=1, - available_for_use_date="2030-01-30", purchase_date="2030-01-30", - depreciation_method="Straight Line", - expected_value_after_useful_life=10000, depreciation_start_date="2030-12-31", - total_number_of_depreciations=3, frequency_of_depreciation=12) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = "2030-01-30", + purchase_date = "2030-01-30", + depreciation_method = "Straight Line", + expected_value_after_useful_life = 10000, + depreciation_start_date = "2030-12-31", + total_number_of_depreciations = 3, + frequency_of_depreciation = 12 + ) expected_schedules = [ ["2030-12-31", 27534.25, 27534.25], @@ -465,11 +504,16 @@ class TestDepreciationMethods(AssetSetup): # WDV: Written Down Value method def test_depreciation_entry_for_wdv_without_pro_rata(self): - asset = create_asset(calculate_depreciation=1, - available_for_use_date="2030-01-01", purchase_date="2030-01-01", - depreciation_method="Written Down Value", - expected_value_after_useful_life=12500, depreciation_start_date="2030-12-31", - total_number_of_depreciations=3, frequency_of_depreciation=12) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = "2030-01-01", + purchase_date = "2030-01-01", + depreciation_method = "Written Down Value", + expected_value_after_useful_life = 12500, + depreciation_start_date = "2030-12-31", + total_number_of_depreciations = 3, + frequency_of_depreciation = 12 + ) self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) @@ -486,11 +530,16 @@ class TestDepreciationMethods(AssetSetup): # WDV: Written Down Value method def test_pro_rata_depreciation_entry_for_wdv(self): - asset = create_asset(calculate_depreciation=1, - available_for_use_date="2030-06-06", purchase_date="2030-01-01", - depreciation_method="Written Down Value", - expected_value_after_useful_life=12500, depreciation_start_date="2030-12-31", - total_number_of_depreciations=3, frequency_of_depreciation=12) + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = "2030-06-06", + purchase_date = "2030-01-01", + depreciation_method = "Written Down Value", + expected_value_after_useful_life = 12500, + depreciation_start_date = "2030-12-31", + total_number_of_depreciations = 3, + frequency_of_depreciation = 12 + ) self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) @@ -511,6 +560,7 @@ class TestDepreciationMethods(AssetSetup): company_flag = frappe.flags.company frappe.flags.company = "_Test Company" +<<<<<<< HEAD <<<<<<< HEAD pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=8000.0, location="Test Location") @@ -541,6 +591,18 @@ class TestDepreciationMethods(AssetSetup): expected_value_after_useful_life=12500, depreciation_start_date="2030-12-31", total_number_of_depreciations=3, frequency_of_depreciation=12) >>>>>>> 09215a9781 (fix: Remove PR creation from all tests for Depreciation Methods) +======= + asset = create_asset( + calculate_depreciation = 1, + available_for_use_date = "2030-07-12", + purchase_date = "2030-01-01", + depreciation_method = "Written Down Value", + expected_value_after_useful_life = 12500, + depreciation_start_date = "2030-12-31", + total_number_of_depreciations = 3, + frequency_of_depreciation = 12 + ) +>>>>>>> e9d310a13e (fix: Format tests) self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) @@ -586,9 +648,15 @@ class TestDepreciationMethods(AssetSetup): class TestDepreciationBasics(AssetSetup): >>>>>>> c84c983073 (fix: Categorize into test suites) def test_depreciation_without_pro_rata(self): - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, - expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-12-31"), submit=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = getdate("2019-12-31"), + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + depreciation_start_date = getdate("2020-12-31"), + submit = 1 + ) expected_values = [ ["2020-12-31", 30000, 30000], @@ -602,9 +670,15 @@ class TestDepreciationBasics(AssetSetup): self.assertEqual(expected_values[i][2], schedule.accumulated_depreciation_amount) def test_depreciation_with_pro_rata(self): - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, - expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-07-01"), submit=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = getdate("2019-12-31"), + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + depreciation_start_date = getdate("2020-07-01"), + submit = 1 + ) expected_values = [ ["2020-07-01", 15000, 15000], @@ -623,16 +697,18 @@ class TestDepreciationBasics(AssetSetup): from erpnext.assets.doctype.asset.asset import get_depreciation_amount - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31")) + asset = create_asset( + item_code = "Macbook Pro", + available_for_use_date = "2019-12-31" + ) - asset.finance_books = [] + asset.calculate_depreciation = 1 asset.append("finance_books", { "depreciation_method": "Straight Line", "frequency_of_depreciation": 12, "total_number_of_depreciations": 3, "expected_value_after_useful_life": 10000, - "depreciation_start_date": getdate("2020-12-31") + "depreciation_start_date": "2020-12-31" }) depreciation_amount = get_depreciation_amount(asset, 100000, asset.finance_books[0]) @@ -641,19 +717,16 @@ class TestDepreciationBasics(AssetSetup): def test_make_depreciation_schedule(self): """Tests if make_depreciation_schedule() returns the right values.""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), do_not_save=1) - - asset.finance_books = [] - asset.append("finance_books", { - "depreciation_method": "Straight Line", - "frequency_of_depreciation": 12, - "total_number_of_depreciations": 3, - "expected_value_after_useful_life": 10000, - "depreciation_start_date": getdate("2020-12-31") - }) - - asset.make_depreciation_schedule(date_of_sale=None) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + depreciation_method = "Straight Line", + frequency_of_depreciation = 12, + total_number_of_depreciations = 3, + expected_value_after_useful_life = 1000, + depreciation_start_date = "2020-12-31" + ) expected_values = [ ['2020-12-31', 30000.0], @@ -668,20 +741,16 @@ class TestDepreciationBasics(AssetSetup): def test_set_accumulated_depreciation(self): """Tests if set_accumulated_depreciation() returns the right values.""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), do_not_save=1) - - asset.finance_books = [] - asset.append("finance_books", { - "depreciation_method": "Straight Line", - "frequency_of_depreciation": 12, - "total_number_of_depreciations": 3, - "expected_value_after_useful_life": 10000, - "depreciation_start_date": getdate("2020-12-31") - }) - - asset.make_depreciation_schedule(date_of_sale=None) - asset.set_accumulated_depreciation() + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + depreciation_method = "Straight Line", + frequency_of_depreciation = 12, + total_number_of_depreciations = 3, + expected_value_after_useful_life = 1000, + depreciation_start_date = "2020-12-31" + ) expected_values = [30000.0, 60000.0, 90000.0] @@ -691,16 +760,19 @@ class TestDepreciationBasics(AssetSetup): def test_check_is_pro_rata(self): """Tests if check_is_pro_rata() returns the right value(i.e. checks if has_pro_rata is accurate).""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), do_not_save=1) + asset = create_asset( + item_code = "Macbook Pro", + available_for_use_date = "2019-12-31", + do_not_save = 1 + ) - asset.finance_books = [] + asset.calculate_depreciation = 1 asset.append("finance_books", { "depreciation_method": "Straight Line", "frequency_of_depreciation": 12, "total_number_of_depreciations": 3, "expected_value_after_useful_life": 10000, - "depreciation_start_date": getdate("2020-12-31") + "depreciation_start_date": "2020-12-31" }) has_pro_rata = asset.check_is_pro_rata(asset.finance_books[0]) @@ -712,7 +784,7 @@ class TestDepreciationBasics(AssetSetup): "frequency_of_depreciation": 12, "total_number_of_depreciations": 3, "expected_value_after_useful_life": 10000, - "depreciation_start_date": getdate("2020-07-01") + "depreciation_start_date": "2020-07-01" }) has_pro_rata = asset.check_is_pro_rata(asset.finance_books[0]) @@ -721,64 +793,103 @@ class TestDepreciationBasics(AssetSetup): def test_expected_value_after_useful_life_greater_than_purchase_amount(self): """Tests if an error is raised when expected_value_after_useful_life(110,000) > gross_purchase_amount(100,000).""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, - expected_value_after_useful_life=110000, depreciation_start_date=getdate("2020-07-01"), do_not_save=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + total_number_of_depreciations = 3, + expected_value_after_useful_life = 110000, + depreciation_start_date = "2020-07-01", + do_not_save = 1 + ) self.assertRaises(frappe.ValidationError, asset.save) def test_depreciation_start_date(self): """Tests if an error is raised when neither depreciation_start_date nor available_for_use_date are specified.""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - total_number_of_depreciations=3, expected_value_after_useful_life=110000, do_not_save=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + total_number_of_depreciations = 3, + expected_value_after_useful_life = 110000, + do_not_save = 1 + ) self.assertRaises(frappe.ValidationError, asset.save) def test_opening_accumulated_depreciation(self): """Tests if an error is raised when opening_accumulated_depreciation > (gross_purchase_amount - expected_value_after_useful_life).""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, - expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-07-01"), - opening_accumulated_depreciation=100000, do_not_save=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + depreciation_start_date = "2020-07-01", + opening_accumulated_depreciation = 100000, + do_not_save = 1 + ) self.assertRaises(frappe.ValidationError, asset.save) def test_number_of_depreciations_booked(self): """Tests if an error is raised when number_of_depreciations_booked is not specified when opening_accumulated_depreciation is.""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, - expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-07-01"), - opening_accumulated_depreciation=10000, do_not_save=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + depreciation_start_date = "2020-07-01", + opening_accumulated_depreciation = 10000, + do_not_save = 1 + ) self.assertRaises(frappe.ValidationError, asset.save) def test_number_of_depreciations(self): """Tests if an error is raised when number_of_depreciations_booked > total_number_of_depreciations.""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, - expected_value_after_useful_life=10000, depreciation_start_date=getdate("2020-07-01"), - opening_accumulated_depreciation=10000, number_of_depreciations_booked=5, - do_not_save=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + depreciation_start_date = "2020-07-01", + opening_accumulated_depreciation = 10000, + number_of_depreciations_booked = 5, + do_not_save = 1 + ) self.assertRaises(frappe.ValidationError, asset.save) def test_depreciation_start_date_is_before_purchase_date(self): - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, - expected_value_after_useful_life=10000, depreciation_start_date=getdate("2014-07-01"), - do_not_save=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + depreciation_start_date = "2014-07-01", + do_not_save = 1 + ) self.assertRaises(frappe.ValidationError, asset.save) def test_depreciation_start_date_is_before_available_for_use_date(self): - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date=getdate("2019-12-31"), total_number_of_depreciations=3, - expected_value_after_useful_life=10000, depreciation_start_date=getdate("2018-07-01"), - do_not_save=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + depreciation_start_date = "2018-07-01", + do_not_save = 1 + ) self.assertRaises(frappe.ValidationError, asset.save) @@ -791,10 +902,16 @@ class TestDepreciationBasics(AssetSetup): def test_post_depreciation_entries(self): """Tests if post_depreciation_entries() works as expected.""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date="2019-12-31", depreciation_start_date="2020-12-31", - frequency_of_depreciation=12, total_number_of_depreciations=3, - expected_value_after_useful_life=10000, submit=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + depreciation_start_date = "2020-12-31", + frequency_of_depreciation = 12, + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + submit = 1 + ) post_depreciation_entries(date="2021-06-01") asset.load_from_db() @@ -806,10 +923,16 @@ class TestDepreciationBasics(AssetSetup): def test_clear_depreciation_schedule(self): """Tests if clear_depreciation_schedule() works as expected.""" - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date="2019-12-31", depreciation_start_date="2020-12-31", - frequency_of_depreciation=12, total_number_of_depreciations=3, - expected_value_after_useful_life=10000, submit=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2019-12-31", + depreciation_start_date = "2020-12-31", + frequency_of_depreciation = 12, + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + submit = 1 + ) post_depreciation_entries(date="2021-06-01") asset.load_from_db() @@ -820,11 +943,17 @@ class TestDepreciationBasics(AssetSetup): >>>>>>> 40ec2d622b (fix: Add tests for depreciation) def test_depreciation_entry_cancellation(self): - asset = create_asset(item_code="Macbook Pro", - calculate_depreciation=1, purchase_date="2020-06-06", - available_for_use_date="2020-06-06", depreciation_start_date="2020-12-31", - frequency_of_depreciation=10, total_number_of_depreciations=3, - expected_value_after_useful_life=10000, submit=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + purchase_date = "2020-06-06", + available_for_use_date = "2020-06-06", + depreciation_start_date = "2020-12-31", + frequency_of_depreciation = 10, + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + submit = 1 + ) post_depreciation_entries(date="2021-01-01") @@ -840,10 +969,15 @@ class TestDepreciationBasics(AssetSetup): self.assertFalse(depr_entry) def test_asset_expected_value_after_useful_life(self): - asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, - available_for_use_date="2020-06-06", purchase_date="2020-06-06", - frequency_of_depreciation=10, total_number_of_depreciations=3, - expected_value_after_useful_life=10000) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + available_for_use_date = "2020-06-06", + purchase_date = "2020-06-06", + frequency_of_depreciation = 10, + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000 + ) accumulated_depreciation_after_full_schedule = \ max(d.accumulated_depreciation_amount for d in asset.get("schedules")) @@ -854,11 +988,17 @@ class TestDepreciationBasics(AssetSetup): self.assertTrue(asset.finance_books[0].expected_value_after_useful_life >= asset_value_after_full_schedule) def test_gle_made_by_depreciation_entries(self): - asset = create_asset(item_code="Macbook Pro", - calculate_depreciation=1, purchase_date="2020-01-30", - available_for_use_date="2020-01-30", depreciation_start_date="2020-12-31", - frequency_of_depreciation=10, total_number_of_depreciations=3, - expected_value_after_useful_life=10000, submit=1) + asset = create_asset( + item_code = "Macbook Pro", + calculate_depreciation = 1, + purchase_date = "2020-01-30", + available_for_use_date = "2020-01-30", + depreciation_start_date = "2020-12-31", + frequency_of_depreciation = 10, + total_number_of_depreciations = 3, + expected_value_after_useful_life = 10000, + submit = 1 + ) <<<<<<< HEAD asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') From 6657a15898c0d6bf115a6e435656920144bb3d12 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 15 Oct 2021 04:02:27 +0530 Subject: [PATCH 28/40] fix: Compare date strings (cherry picked from commit 371b62136454f720a02b12644d6e57e7d9840a34) --- erpnext/assets/doctype/asset/test_asset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 6af065d4ef6..97c83382161 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -735,7 +735,7 @@ class TestDepreciationBasics(AssetSetup): ] for i, schedule in enumerate(asset.schedules): - self.assertEqual(getdate(expected_values[i][0]), schedule.schedule_date) + self.assertEqual(expected_values[i][0], schedule.schedule_date) self.assertEqual(expected_values[i][1], schedule.depreciation_amount) def test_set_accumulated_depreciation(self): From 9595f7cc3fad2c77b14c0179b10d92dfb957d403 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 15 Oct 2021 04:03:30 +0530 Subject: [PATCH 29/40] fix: Add missing digit (cherry picked from commit 60aae4423dcf9e26557f0a44c2f7c206d54eb07b) --- erpnext/assets/doctype/asset/test_asset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 97c83382161..1e3d2fc1bfe 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -748,7 +748,7 @@ class TestDepreciationBasics(AssetSetup): depreciation_method = "Straight Line", frequency_of_depreciation = 12, total_number_of_depreciations = 3, - expected_value_after_useful_life = 1000, + expected_value_after_useful_life = 10000, depreciation_start_date = "2020-12-31" ) From c104a2a2f46fae1be9d538e837dbcd1b28d79af0 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 15 Oct 2021 04:53:23 +0530 Subject: [PATCH 30/40] fix: Sider issues (cherry picked from commit fdeb273fa06670d802847199d57ecd40dbecd476) --- erpnext/assets/doctype/asset/test_asset.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 1e3d2fc1bfe..6d46e57bbc9 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -408,7 +408,7 @@ class TestDepreciationMethods(AssetSetup): calculate_depreciation = 1, available_for_use_date = "2030-06-06", is_existing_asset = 1, - number_of_depreciations_booked = 1, + number_of_depreciations_booked = 1, opening_accumulated_depreciation = 40000, expected_value_after_useful_life = 10000, depreciation_start_date = "2030-12-31", @@ -458,7 +458,7 @@ class TestDepreciationMethods(AssetSetup): available_for_use_date = "2030-01-01", is_existing_asset = 1, depreciation_method = "Double Declining Balance", - number_of_depreciations_booked = 1, + number_of_depreciations_booked = 1, opening_accumulated_depreciation = 50000, expected_value_after_useful_life = 10000, depreciation_start_date = "2030-12-31", From 595d6c31b5d160ab9ebde30a9324846412220134 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Fri, 15 Oct 2021 04:56:00 +0530 Subject: [PATCH 31/40] fix: Add missing digit (cherry picked from commit 0b8cb5dd47816b87cfea2176ffa76c889bb9d383) --- erpnext/assets/doctype/asset/test_asset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 6d46e57bbc9..26e43134534 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -724,7 +724,7 @@ class TestDepreciationBasics(AssetSetup): depreciation_method = "Straight Line", frequency_of_depreciation = 12, total_number_of_depreciations = 3, - expected_value_after_useful_life = 1000, + expected_value_after_useful_life = 10000, depreciation_start_date = "2020-12-31" ) From 92ebe52432ca36c08493c7cc3750571a3d0fa485 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Mon, 25 Oct 2021 01:34:42 +0530 Subject: [PATCH 32/40] fix: Only add additional depreciation schedule row on sale if depreciation_amount > 0 (cherry picked from commit 9e7022830e058c3ba95f034942cad054e045e8f6) --- erpnext/assets/doctype/asset/asset.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 45cf507611a..cfe7edca710 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -230,13 +230,15 @@ class Asset(AccountsController): depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount, from_date, date_of_sale) - self.append("schedules", { - "schedule_date": date_of_sale, - "depreciation_amount": depreciation_amount, - "depreciation_method": d.depreciation_method, - "finance_book": d.finance_book, - "finance_book_id": d.idx - }) + if depreciation_amount > 0: + self.append("schedules", { + "schedule_date": date_of_sale, + "depreciation_amount": depreciation_amount, + "depreciation_method": d.depreciation_method, + "finance_book": d.finance_book, + "finance_book_id": d.idx + }) + break # For first row From 5146985a66b20b06c19b0da997390feb9fc181a6 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 26 Oct 2021 20:53:47 +0530 Subject: [PATCH 33/40] fix: Replace post_depreciation_entries() with make_depreciation_entry() (cherry picked from commit 82bf5e55393520f7681615e1addf4ceee4319ee5) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 123d7782b6f..2c740e2fecf 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -36,7 +36,7 @@ from erpnext.assets.doctype.asset.depreciation import ( get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal, get_gl_entries_on_asset_regain, - post_depreciation_entries, + make_depreciation_entry ) from erpnext.controllers.selling_controller import SellingController from erpnext.healthcare.utils import manage_invoice_submit_cancel @@ -1010,7 +1010,7 @@ class SalesInvoice(SellingController): asset.prepare_depreciation_data(date_of_sale=self.posting_date) asset.save() - post_depreciation_entries(self.posting_date) + make_depreciation_entry(asset.name, self.posting_date) def reset_depreciation_schedule(self, asset): asset.flags.ignore_validate_update_after_submit = True From f0076ca3f9d68c6e79583bbcbfdca3ad104fb020 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 26 Oct 2021 21:04:06 +0530 Subject: [PATCH 34/40] fix: Add flag for reverse depreciation entries (cherry picked from commit cde0dae98733563c02c7e364de2b97d9831a3e97) --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 3 ++- erpnext/accounts/doctype/journal_entry/journal_entry.py | 2 +- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index f5c08a7b1fa..f184b95a92d 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -57,7 +57,8 @@ class GLEntry(Document): # Update outstanding amt on against voucher if (self.against_voucher_type in ['Journal Entry', 'Sales Invoice', 'Purchase Invoice', 'Fees'] - and self.against_voucher and self.flags.update_outstanding == 'Yes'): + and self.against_voucher and self.flags.update_outstanding == 'Yes' + and not frappe.flags.is_reverse_depr_entry): update_outstanding_amt(self.account, self.party_type, self.party, self.against_voucher_type, self.against_voucher) diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py index bb8e1e046a5..3aed3c89d53 100644 --- a/erpnext/accounts/doctype/journal_entry/journal_entry.py +++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py @@ -57,7 +57,7 @@ class JournalEntry(AccountsController): if not frappe.flags.in_import: self.validate_total_debit_and_credit() - if not self.flags.is_reverse_depr_entry: + if not frappe.flags.is_reverse_depr_entry: self.validate_against_jv() self.validate_stock_accounts() diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 2c740e2fecf..9c2982cfc7e 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1054,7 +1054,7 @@ class SalesInvoice(SellingController): reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry) reverse_journal_entry.posting_date = nowdate() - reverse_journal_entry.flags.is_reverse_depr_entry = True + frappe.flags.is_reverse_depr_entry = True reverse_journal_entry.submit() asset.flags.ignore_validate_update_after_submit = True From 445f1b2a099b2201df0fe0cf7a79de1e9a96d2a6 Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Wed, 27 Oct 2021 05:23:01 +0530 Subject: [PATCH 35/40] fix: Linters (cherry picked from commit 06c505ddc2c3529703a35a986896112de7107ae3) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 2 +- erpnext/assets/doctype/asset/test_asset.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 9c2982cfc7e..9c02920e292 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -36,7 +36,7 @@ from erpnext.assets.doctype.asset.depreciation import ( get_disposal_account_and_cost_center, get_gl_entries_on_asset_disposal, get_gl_entries_on_asset_regain, - make_depreciation_entry + make_depreciation_entry, ) from erpnext.controllers.selling_controller import SellingController from erpnext.healthcare.utils import manage_invoice_submit_cancel diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 26e43134534..c2bcd7aad5c 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -18,6 +18,7 @@ from erpnext.stock.doctype.purchase_receipt.purchase_receipt import ( ) from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + class AssetSetup(unittest.TestCase): @classmethod def setUpClass(cls): From b937c55b859da0b593e9e6abfe02253180c96896 Mon Sep 17 00:00:00 2001 From: Saqib Date: Wed, 27 Oct 2021 18:30:37 +0530 Subject: [PATCH 36/40] fix: reset temporary flag after use (cherry picked from commit a261d08dd868ff6c306a2c8392dddd73d006ab85) --- erpnext/accounts/doctype/sales_invoice/sales_invoice.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 9c02920e292..41599e8bdf6 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1057,6 +1057,7 @@ class SalesInvoice(SellingController): frappe.flags.is_reverse_depr_entry = True reverse_journal_entry.submit() + frappe.flags.is_reverse_depr_entry = False asset.flags.ignore_validate_update_after_submit = True schedule.journal_entry = None asset.save() From a424f55943d696922f56dc648304229d99aad5bf Mon Sep 17 00:00:00 2001 From: GangaManoj Date: Tue, 2 Nov 2021 16:43:31 +0530 Subject: [PATCH 37/40] fix: Test for WDV (cherry picked from commit f047c6ffc80775789be50707d9a1c0320c87a4fe) # Conflicts: # erpnext/assets/doctype/asset/test_asset.py --- erpnext/assets/doctype/asset/test_asset.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index c2bcd7aad5c..3ef370c945b 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -561,6 +561,7 @@ class TestDepreciationMethods(AssetSetup): company_flag = frappe.flags.company frappe.flags.company = "_Test Company" +<<<<<<< HEAD <<<<<<< HEAD <<<<<<< HEAD pr = make_purchase_receipt(item_code="Macbook Pro", @@ -593,10 +594,18 @@ class TestDepreciationMethods(AssetSetup): total_number_of_depreciations=3, frequency_of_depreciation=12) >>>>>>> 09215a9781 (fix: Remove PR creation from all tests for Depreciation Methods) ======= +======= + finance_book = frappe.new_doc("Finance Book") + finance_book.finance_book_name = "Income Tax" + finance_book.for_income_tax = 1 + finance_book.insert(ignore_if_duplicate = True) + +>>>>>>> f047c6ffc8 (fix: Test for WDV) asset = create_asset( calculate_depreciation = 1, available_for_use_date = "2030-07-12", purchase_date = "2030-01-01", + finance_book = finance_book.name, depreciation_method = "Written Down Value", expected_value_after_useful_life = 12500, depreciation_start_date = "2030-12-31", From 2a6d202061384648859a5546eaf782e8c526c51a Mon Sep 17 00:00:00 2001 From: Saqib Date: Tue, 2 Nov 2021 17:47:44 +0530 Subject: [PATCH 38/40] fix: test wdv method for indian region (cherry picked from commit 7681600b5e6e2421dfdfee39661aaf87d8327e3b) --- erpnext/assets/doctype/asset/test_asset.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index 3ef370c945b..d3ccaa55fc6 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -1087,6 +1087,7 @@ def create_asset(**args): if asset.calculate_depreciation: asset.append("finance_books", { + "finance_book": args.finance_book, "depreciation_method": args.depreciation_method or "Straight Line", "frequency_of_depreciation": args.frequency_of_depreciation or 12, "total_number_of_depreciations": args.total_number_of_depreciations or 5, From 635fd5e8f8ee9274956fbfc7df4631433d36ea64 Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Mon, 6 Dec 2021 11:33:37 +0530 Subject: [PATCH 39/40] fix: conflicts --- erpnext/assets/doctype/asset/test_asset.py | 60 +--------------------- 1 file changed, 1 insertion(+), 59 deletions(-) diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py index d3ccaa55fc6..151a8a47d93 100644 --- a/erpnext/assets/doctype/asset/test_asset.py +++ b/erpnext/assets/doctype/asset/test_asset.py @@ -561,46 +561,11 @@ class TestDepreciationMethods(AssetSetup): company_flag = frappe.flags.company frappe.flags.company = "_Test Company" -<<<<<<< HEAD -<<<<<<< HEAD -<<<<<<< HEAD - pr = make_purchase_receipt(item_code="Macbook Pro", - qty=1, rate=8000.0, location="Test Location") - - finance_book = frappe.new_doc('Finance Book') - finance_book.finance_book_name = 'Income Tax' - finance_book.for_income_tax = 1 - finance_book.insert(ignore_if_duplicate=1) - - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.available_for_use_date = '2030-07-12' - asset.purchase_date = '2030-01-01' - asset.append("finance_books", { - "finance_book": finance_book.name, - "expected_value_after_useful_life": 1000, - "depreciation_method": "Written Down Value", - "total_number_of_depreciations": 3, - "frequency_of_depreciation": 12, - "depreciation_start_date": "2030-12-31" - }) - asset.save(ignore_permissions=True) -======= - asset = create_asset(calculate_depreciation=1, - available_for_use_date="2030-07-12", purchase_date="2030-01-01", - depreciation_method="Written Down Value", - expected_value_after_useful_life=12500, depreciation_start_date="2030-12-31", - total_number_of_depreciations=3, frequency_of_depreciation=12) ->>>>>>> 09215a9781 (fix: Remove PR creation from all tests for Depreciation Methods) -======= -======= finance_book = frappe.new_doc("Finance Book") finance_book.finance_book_name = "Income Tax" finance_book.for_income_tax = 1 finance_book.insert(ignore_if_duplicate = True) ->>>>>>> f047c6ffc8 (fix: Test for WDV) asset = create_asset( calculate_depreciation = 1, available_for_use_date = "2030-07-12", @@ -612,7 +577,6 @@ class TestDepreciationMethods(AssetSetup): total_number_of_depreciations = 3, frequency_of_depreciation = 12 ) ->>>>>>> e9d310a13e (fix: Format tests) self.assertEqual(asset.finance_books[0].rate_of_depreciation, 50.0) @@ -631,8 +595,6 @@ class TestDepreciationMethods(AssetSetup): # reset indian company frappe.flags.company = company_flag -<<<<<<< HEAD -<<<<<<< HEAD def test_expected_value_change(self): """ tests if changing `expected_value_after_useful_life` @@ -653,10 +615,8 @@ class TestDepreciationMethods(AssetSetup): asset.save() asset.reload() self.assertEquals(asset.finance_books[0].value_after_depreciation, 98000.0) -======= -======= + class TestDepreciationBasics(AssetSetup): ->>>>>>> c84c983073 (fix: Categorize into test suites) def test_depreciation_without_pro_rata(self): asset = create_asset( item_code = "Macbook Pro", @@ -950,7 +910,6 @@ class TestDepreciationBasics(AssetSetup): asset.clear_depreciation_schedule() self.assertEqual(len(asset.schedules), 1) ->>>>>>> 40ec2d622b (fix: Add tests for depreciation) def test_depreciation_entry_cancellation(self): asset = create_asset( @@ -1010,23 +969,6 @@ class TestDepreciationBasics(AssetSetup): submit = 1 ) -<<<<<<< HEAD - asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, 'name') - asset = frappe.get_doc('Asset', asset_name) - asset.calculate_depreciation = 1 - asset.purchase_date = '2020-01-30' - asset.available_for_use_date = "2020-01-30" - 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" - }) - asset.submit() - asset.load_from_db() -======= ->>>>>>> 968be70bd1 (fix: Remove PR creation from all tests in TestDepreciationBasics) self.assertEqual(asset.status, "Submitted") frappe.db.set_value("Company", "_Test Company", "series_for_depreciation_entry", "DEPR-") From 1a2e815e6a1ce496e1836707c1277a58c4ff7a6e Mon Sep 17 00:00:00 2001 From: Saqib Ansari Date: Mon, 6 Dec 2021 15:16:25 +0530 Subject: [PATCH 40/40] fix: asset not copied on creating invoice return --- .../accounts/doctype/sales_invoice_item/sales_invoice_item.json | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json index cc6843060a2..a9412d86396 100644 --- a/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json +++ b/erpnext/accounts/doctype/sales_invoice_item/sales_invoice_item.json @@ -746,7 +746,6 @@ "fieldname": "asset", "fieldtype": "Link", "label": "Asset", - "no_copy": 1, "options": "Asset" }, {