fix(Asset Capitalization): update code for changes in depreciation logic
diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
index 2b3850e..7ed45ce 100644
--- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
+++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py
@@ -27,7 +27,6 @@
get_disposal_account_and_cost_center,
get_gl_entries_on_asset_disposal,
get_gl_entries_on_asset_regain,
- make_depreciation_entry,
)
from erpnext.controllers.selling_controller import SellingController
from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data
@@ -924,7 +923,7 @@
asset.db_set("disposal_date", None)
if asset.calculate_depreciation:
- self.reverse_depreciation_entry_made_after_sale(asset)
+ self.reverse_depreciation_entry_made_after_disposal(asset)
self.reset_depreciation_schedule(asset)
else:
@@ -980,89 +979,6 @@
self.check_finance_books(item, asset)
return asset
- def check_finance_books(self, item, asset):
- if (len(asset.finance_books) > 1 and not item.finance_book
- and asset.finance_books[0].finance_book):
- frappe.throw(_("Select finance book for the item {0} at row {1}")
- .format(item.item_code, item.idx))
-
- def depreciate_asset(self, asset):
- asset.flags.ignore_validate_update_after_submit = True
- asset.prepare_depreciation_data(date_of_sale=self.posting_date)
- asset.save()
-
- make_depreciation_entry(asset.name, self.posting_date)
-
- def reset_depreciation_schedule(self, asset):
- asset.flags.ignore_validate_update_after_submit = True
-
- # recreate original depreciation schedule of the asset
- asset.prepare_depreciation_data(date_of_return=self.posting_date)
-
- self.modify_depreciation_schedule_for_asset_repairs(asset)
- asset.save()
-
- def modify_depreciation_schedule_for_asset_repairs(self, asset):
- asset_repairs = frappe.get_all(
- 'Asset Repair',
- filters = {'asset': asset.name},
- fields = ['name', 'increase_in_asset_life']
- )
-
- for repair in asset_repairs:
- if repair.increase_in_asset_life:
- asset_repair = frappe.get_doc('Asset Repair', repair.name)
- asset_repair.modify_depreciation_schedule()
- asset.prepare_depreciation_data()
-
- 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()
-
- row = -1
- finance_book = asset.get('schedules')[0].get('finance_book')
- for schedule in asset.get('schedules'):
- if schedule.finance_book != finance_book:
- row = 0
- finance_book = schedule.finance_book
- else:
- 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) \
- 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()
- 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()
-
- def get_posting_date_of_sales_invoice(self):
- return frappe.db.get_value('Sales Invoice', self.return_against, 'posting_date')
-
- # if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
- def sale_was_made_on_original_schedule_date(self, asset, schedule, row, posting_date_of_original_invoice):
- for finance_book in asset.get('finance_books'):
- if schedule.finance_book == finance_book.finance_book:
- orginal_schedule_date = add_months(finance_book.depreciation_start_date,
- row * cint(finance_book.frequency_of_depreciation))
-
- if orginal_schedule_date == posting_date_of_original_invoice:
- 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"):
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index cf62f49..7c05488 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -75,12 +75,12 @@
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, date_of_return=None):
+ def prepare_depreciation_data(self, date_of_disposal=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, date_of_return)
+ self.make_depreciation_schedule(date_of_disposal)
+ self.set_accumulated_depreciation(date_of_disposal, date_of_return)
else:
self.finance_books = []
self.value_after_depreciation = (flt(self.gross_purchase_amount) -
@@ -181,7 +181,7 @@
d.rate_of_depreciation = flt(self.get_depreciation_rate(d, on_validate=True),
d.precision("rate_of_depreciation"))
- def make_depreciation_schedule(self, date_of_sale):
+ def make_depreciation_schedule(self, date_of_disposal):
if 'Manual' not in [d.depreciation_method for d in self.finance_books] and not self.get('schedules'):
self.schedules = []
@@ -227,14 +227,14 @@
monthly_schedule_date = add_months(schedule_date, - d.frequency_of_depreciation + 1)
# if asset is being sold
- if date_of_sale:
+ if date_of_disposal:
from_date = self.get_from_date(d.finance_book)
depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
- from_date, date_of_sale)
+ from_date, date_of_disposal)
if depreciation_amount > 0:
self.append("schedules", {
- "schedule_date": date_of_sale,
+ "schedule_date": date_of_disposal,
"depreciation_amount": depreciation_amount,
"depreciation_method": d.depreciation_method,
"finance_book": d.finance_book,
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index 5a23986..7d08581 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -375,8 +375,8 @@
else:
if asset.calculate_depreciation:
self.depreciate_asset(asset)
+ asset.reload()
- asset.reload()
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset,
item.asset_value, item.get('finance_book') or self.get('finance_book'))
asset.db_set("disposal_date", self.posting_date)
diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
index 9bfc88b..5a342f7 100644
--- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
@@ -118,11 +118,11 @@
depreciation_before_disposal_amount = 15_000
accumulated_depreciation = 45_000
- # to accomodate for depreciation on disposal calculation bugs TODO remove this when bug is fixed
- consumed_asset_value_before_disposal = 60_082.19
- target_incoming_rate = 6008.219
- depreciation_before_disposal_amount = 9917.81
- accumulated_depreciation = 39_917.81
+ # to accomodate for depreciation on disposal calculation minor difference
+ consumed_asset_value_before_disposal = 55_123.29
+ target_incoming_rate = 5512.329
+ depreciation_before_disposal_amount = 14_876.71
+ accumulated_depreciation = 44_876.71
# Create assets
consumed_asset = create_depreciation_asset(
diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py
index 9d19639..6b681ff 100644
--- a/erpnext/controllers/accounts_controller.py
+++ b/erpnext/controllers/accounts_controller.py
@@ -38,7 +38,7 @@
validate_party_frozen_disabled,
)
from erpnext.accounts.utils import get_account_currency, get_fiscal_years, validate_fiscal_year
-from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
+from erpnext.assets.doctype.asset.depreciation import make_depreciation_entry
from erpnext.buying.utils import update_last_purchase_rate
from erpnext.controllers.print_settings import (
set_print_templates_for_item_table,
@@ -1516,17 +1516,16 @@
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_disposal=self.posting_date)
asset.save()
- post_depreciation_entries(self.posting_date, commit=False)
+ make_depreciation_entry(asset.name, self.posting_date)
def reset_depreciation_schedule(self, asset):
asset.flags.ignore_validate_update_after_submit = True
# recreate original depreciation schedule of the asset
- self.delete_depreciation_entry_made_after_disposal(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()
@@ -1544,10 +1543,10 @@
asset_repair.modify_depreciation_schedule()
asset.prepare_depreciation_data()
- def delete_depreciation_entry_made_after_disposal(self, asset):
+ def reverse_depreciation_entry_made_after_disposal(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_disposal_entry()
+ posting_date_of_original_disposal = self.get_posting_date_of_disposal_entry()
row = -1
finance_book = asset.get('schedules')[0].get('finance_book')
@@ -1558,19 +1557,19 @@
else:
row += 1
- if schedule.schedule_date == posting_date_of_original_invoice:
- if not self.disposal_was_made_on_original_schedule_date(asset, schedule, row,
- posting_date_of_original_invoice) or getdate(schedule.schedule_date) > getdate(today()):
+ if schedule.schedule_date == posting_date_of_original_disposal:
+ if not self.disposal_was_made_on_original_schedule_date(asset, schedule, row, posting_date_of_original_disposal) \
+ or self.disposal_happens_in_the_future(posting_date_of_original_disposal):
+
reverse_journal_entry = make_reverse_journal_entry(schedule.journal_entry)
reverse_journal_entry.posting_date = nowdate()
-
- for d in reverse_journal_entry.accounts:
- d.reference_type = "Asset"
- d.reference_name = asset.name
-
+ frappe.flags.is_reverse_depr_entry = True
reverse_journal_entry.submit()
- schedule.db_set('journal_entry', None)
+ frappe.flags.is_reverse_depr_entry = False
+ asset.flags.ignore_validate_update_after_submit = True
+ schedule.journal_entry = None
+ asset.save()
def get_posting_date_of_disposal_entry(self):
if self.doctype == "Sales Invoice" and self.return_against:
@@ -1579,16 +1578,22 @@
return self.posting_date
# if the invoice had been posted on the date the depreciation was initially supposed to happen, the depreciation shouldn't be undone
- def disposal_was_made_on_original_schedule_date(self, asset, schedule, row, posting_date_of_original_disposal):
+ def disposal_was_made_on_original_schedule_date(self, asset, schedule, row, posting_date_of_disposal):
for finance_book in asset.get('finance_books'):
if schedule.finance_book == finance_book.finance_book:
orginal_schedule_date = add_months(finance_book.depreciation_start_date,
row * cint(finance_book.frequency_of_depreciation))
- if orginal_schedule_date == posting_date_of_original_disposal:
+ if orginal_schedule_date == posting_date_of_disposal:
return True
return False
+ def disposal_happens_in_the_future(self, posting_date_of_disposal):
+ if posting_date_of_disposal > getdate():
+ return True
+
+ return False
+
@frappe.whitelist()
def get_tax_rate(account_head):
return frappe.db.get_value("Account", account_head, ["tax_rate", "account_name"], as_dict=True)