refactor: Straight line depreciation after asset repair

This commit is contained in:
Nabin Hait
2024-12-23 12:53:57 +05:30
committed by Khushi Rawat
parent 0e4706b074
commit c567a08470
7 changed files with 141 additions and 110 deletions

View File

@@ -175,12 +175,6 @@ class AssetDepreciationSchedule(Document):
update_asset_finance_book_row=True,
value_after_depreciation=None,
):
# if not self.get("depreciation_schedule"):
# self.depreciation_schedule = []
# if not asset_doc.available_for_use_date:
# return
start = self.clear_depr_schedule()
self._make_depr_schedule(
@@ -230,7 +224,7 @@ class AssetDepreciationSchedule(Document):
prev_per_day_depr = True
self.current_fiscal_year_end_date = None
yearly_opening_wdv = value_after_depreciation
number_of_pending_depreciations = final_number_of_depreciations - start
pending_months = self.get_number_of_pending_months(asset_doc, row, start)
for n in range(start, final_number_of_depreciations):
# If depreciation is already completed (for double declining balance)
@@ -251,7 +245,7 @@ class AssetDepreciationSchedule(Document):
n,
prev_depreciation_amount,
has_wdv_or_dd_non_yearly_pro_rata,
number_of_pending_depreciations,
pending_months,
prev_per_day_depr,
)
@@ -314,8 +308,38 @@ class AssetDepreciationSchedule(Document):
if has_pro_rata:
final_number_of_depreciations += 1
if row.increase_in_asset_life:
final_number_of_depreciations = (
self.get_final_number_of_depreciations_considering_increase_in_asset_life(
asset_doc, row, final_number_of_depreciations
)
)
return final_number_of_depreciations, has_pro_rata
def get_final_number_of_depreciations_considering_increase_in_asset_life(
self, asset_doc, row, final_number_of_depreciations
):
# final schedule date after increasing asset life
self.final_schedule_date = add_months(
asset_doc.available_for_use_date,
(row.total_number_of_depreciations * cint(row.frequency_of_depreciation))
+ row.increase_in_asset_life,
)
number_of_pending_depreciations = cint(row.total_number_of_depreciations) - cint(
asset_doc.opening_number_of_booked_depreciations
)
schedule_date = add_months(
row.depreciation_start_date,
number_of_pending_depreciations * cint(row.frequency_of_depreciation),
)
if self.final_schedule_date > schedule_date:
final_number_of_depreciations += 1
return final_number_of_depreciations
def is_wdv_or_dd_non_yearly_pro_rata(self, asset_doc, row):
has_wdv_or_dd_non_yearly_pro_rata = False
if (
@@ -326,6 +350,22 @@ class AssetDepreciationSchedule(Document):
return has_wdv_or_dd_non_yearly_pro_rata
def get_number_of_pending_months(self, asset_doc, row, start):
print(row.total_number_of_depreciations)
total_months = cint(row.total_number_of_depreciations) * cint(row.frequency_of_depreciation) + cint(
row.increase_in_asset_life
)
depr_booked_for_months = 0
if start > 0:
last_depr_date = self.depreciation_schedule[start - 1].schedule_date
elif asset_doc.opening_number_of_booked_depreciations > 0:
last_depr_date = add_months(row.depreciation_start_date, -1 * row.frequency_of_depreciation)
if last_depr_date:
depr_booked_for_months = date_diff(last_depr_date, asset_doc.available_for_use_date) / (365 / 12)
print(total_months, depr_booked_for_months)
return total_months - depr_booked_for_months
def has_fiscal_year_changed(self, row, row_no):
fiscal_year_changed = False
@@ -352,13 +392,9 @@ class AssetDepreciationSchedule(Document):
def get_next_schedule_date(
self, row, n, has_pro_rata, should_get_last_day, final_number_of_depreciations=None
):
if not has_pro_rata or (
n < (cint(final_number_of_depreciations) - 1) or final_number_of_depreciations == 2
):
schedule_date = add_months(row.depreciation_start_date, n * cint(row.frequency_of_depreciation))
if should_get_last_day:
schedule_date = get_last_day(schedule_date)
schedule_date = add_months(row.depreciation_start_date, n * cint(row.frequency_of_depreciation))
if should_get_last_day:
schedule_date = get_last_day(schedule_date)
return schedule_date
@@ -435,27 +471,28 @@ class AssetDepreciationSchedule(Document):
def get_depreciation_amount_for_last_row(
self, asset_doc, row, n, depreciation_amount, schedule_date, has_wdv_or_dd_non_yearly_pro_rata
):
if not asset_doc.flags.increase_in_asset_life:
if not row.increase_in_asset_life:
# In case of increase_in_asset_life, the asset.to_date is already set on asset_repair submission
asset_doc.to_date = add_months(
self.final_schedule_date = add_months(
asset_doc.available_for_use_date,
(n + self.opening_number_of_booked_depreciations) * cint(row.frequency_of_depreciation),
)
if is_last_day_of_the_month(getdate(asset_doc.available_for_use_date)):
asset_doc.to_date = get_last_day(asset_doc.to_date)
self.final_schedule_date = get_last_day(self.final_schedule_date)
if self.opening_accumulated_depreciation:
depreciation_amount, days, months = _get_pro_rata_amt(
row,
depreciation_amount,
schedule_date,
asset_doc.to_date,
self.final_schedule_date,
has_wdv_or_dd_non_yearly_pro_rata,
)
else:
# if not existing asset, remaining amount of first row is depreciated in the last row
depreciation_amount -= self.get("depreciation_schedule")[0].depreciation_amount
days = date_diff(asset_doc.to_date, schedule_date) + 1
if not row.increase_in_asset_life:
depreciation_amount -= self.get("depreciation_schedule")[0].depreciation_amount
days = date_diff(self.final_schedule_date, schedule_date) + 1
schedule_date = add_days(schedule_date, days - 1)
return depreciation_amount, schedule_date

View File

@@ -4,6 +4,7 @@ from frappe.utils import (
add_months,
add_years,
cint,
cstr,
date_diff,
flt,
get_last_day,
@@ -16,7 +17,7 @@ import erpnext
def get_depreciation_amount(
asset_depr_schedule,
asset,
depreciable_value,
value_after_depreciation,
yearly_opening_wdv,
fb_row,
schedule_idx=0,
@@ -27,13 +28,18 @@ def get_depreciation_amount(
):
if fb_row.depreciation_method in ("Straight Line", "Manual"):
return get_straight_line_or_manual_depr_amount(
asset_depr_schedule, asset, fb_row, schedule_idx, number_of_pending_depreciations
asset_depr_schedule,
asset,
fb_row,
schedule_idx,
value_after_depreciation,
number_of_pending_depreciations,
), None
else:
return get_wdv_or_dd_depr_amount(
asset,
fb_row,
depreciable_value,
value_after_depreciation,
yearly_opening_wdv,
schedule_idx,
prev_depreciation_amount,
@@ -44,83 +50,59 @@ def get_depreciation_amount(
def get_straight_line_or_manual_depr_amount(
asset_depr_schedule, asset, row, schedule_idx, number_of_pending_depreciations
asset_depr_schedule,
asset,
fb_row,
schedule_idx,
value_after_depreciation,
number_of_pending_depreciations,
):
if row.shift_based:
return get_shift_depr_amount(asset_depr_schedule, asset, row, schedule_idx)
if fb_row.shift_based:
return get_shift_depr_amount(asset_depr_schedule, asset, fb_row, schedule_idx)
# if the Depreciation Schedule is being modified after Asset Repair due to increase in asset life and value
if asset.flags.increase_in_asset_life:
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / (
date_diff(asset.to_date, asset.available_for_use_date) / 365
if fb_row.daily_prorata_based:
amount = flt(asset.gross_purchase_amount) - flt(fb_row.expected_value_after_useful_life)
return get_daily_prorata_based_straight_line_depr(
asset, fb_row, schedule_idx, number_of_pending_depreciations, amount
)
# if the Depreciation Schedule is being modified after Asset Repair due to increase in asset value
elif asset.flags.increase_in_asset_value_due_to_repair:
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / flt(
number_of_pending_depreciations
)
# if the Depreciation Schedule is being modified after Asset Value Adjustment due to decrease in asset value
elif asset.flags.decrease_in_asset_value_due_to_value_adjustment:
if row.daily_prorata_based:
amount = flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)
return get_daily_prorata_based_straight_line_depr(
asset,
row,
schedule_idx,
number_of_pending_depreciations,
amount,
)
else:
return (
flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)
) / number_of_pending_depreciations
# if the Depreciation Schedule is being prepared for the first time
else:
if row.daily_prorata_based:
amount = flt(asset.gross_purchase_amount) - flt(row.expected_value_after_useful_life)
return get_daily_prorata_based_straight_line_depr(
asset, row, schedule_idx, number_of_pending_depreciations, amount
)
else:
depreciation_amount = (
flt(asset.gross_purchase_amount) - flt(row.expected_value_after_useful_life)
) / flt(row.total_number_of_depreciations)
return depreciation_amount
return (flt(fb_row.value_after_depreciation) - flt(fb_row.expected_value_after_useful_life)) / (
flt(number_of_pending_depreciations) / flt(fb_row.frequency_of_depreciation)
)
def get_daily_prorata_based_straight_line_depr(
asset, row, schedule_idx, number_of_pending_depreciations, amount
asset, fb_row, schedule_idx, number_of_pending_depreciations, amount
):
daily_depr_amount = get_daily_depr_amount(asset, row, schedule_idx, amount)
daily_depr_amount = get_daily_depr_amount(asset, fb_row, schedule_idx, amount)
from_date, total_depreciable_days = _get_total_days(
row.depreciation_start_date, schedule_idx, row.frequency_of_depreciation
fb_row.depreciation_start_date, schedule_idx, fb_row.frequency_of_depreciation
)
return daily_depr_amount * total_depreciable_days
def get_daily_depr_amount(asset, row, schedule_idx, amount):
def get_daily_depr_amount(asset, fb_row, schedule_idx, amount):
if cint(frappe.db.get_single_value("Accounts Settings", "calculate_depr_using_total_days")):
total_days = (
date_diff(
get_last_day(
add_months(
row.depreciation_start_date,
fb_row.depreciation_start_date,
flt(
row.total_number_of_depreciations
fb_row.total_number_of_depreciations
- asset.opening_number_of_booked_depreciations
- 1
)
* row.frequency_of_depreciation,
* fb_row.frequency_of_depreciation,
)
),
add_days(
get_last_day(
add_months(
row.depreciation_start_date,
fb_row.depreciation_start_date,
(
row.frequency_of_depreciation
fb_row.frequency_of_depreciation
* (asset.opening_number_of_booked_depreciations + 1)
)
* -1,
@@ -136,8 +118,8 @@ def get_daily_depr_amount(asset, row, schedule_idx, amount):
else:
total_years = (
flt(
(row.total_number_of_depreciations - row.total_number_of_booked_depreciations)
* row.frequency_of_depreciation
(fb_row.total_number_of_depreciations - fb_row.total_number_of_booked_depreciations)
* fb_row.frequency_of_depreciation
)
/ 12
)
@@ -145,24 +127,24 @@ def get_daily_depr_amount(asset, row, schedule_idx, amount):
every_year_depr = amount / total_years
depr_period_start_date = add_days(
get_last_day(add_months(row.depreciation_start_date, row.frequency_of_depreciation * -1)), 1
get_last_day(add_months(fb_row.depreciation_start_date, fb_row.frequency_of_depreciation * -1)), 1
)
year_start_date = add_years(
depr_period_start_date, ((row.frequency_of_depreciation * schedule_idx) // 12)
depr_period_start_date, ((fb_row.frequency_of_depreciation * schedule_idx) // 12)
)
year_end_date = add_days(add_years(year_start_date, 1), -1)
return every_year_depr / (date_diff(year_end_date, year_start_date) + 1)
def get_shift_depr_amount(asset_depr_schedule, asset, row, schedule_idx):
def get_shift_depr_amount(asset_depr_schedule, asset, fb_row, schedule_idx):
if asset_depr_schedule.get("__islocal") and not asset.flags.shift_allocation:
return (
flt(asset.gross_purchase_amount)
- flt(asset.opening_accumulated_depreciation)
- flt(row.expected_value_after_useful_life)
) / flt(row.total_number_of_depreciations - asset.opening_number_of_booked_depreciations)
- flt(fb_row.expected_value_after_useful_life)
) / flt(fb_row.total_number_of_depreciations - asset.opening_number_of_booked_depreciations)
asset_shift_factors_map = get_asset_shift_factors_map()
shift = (
@@ -181,7 +163,7 @@ def get_shift_depr_amount(asset_depr_schedule, asset, row, schedule_idx):
(
flt(asset.gross_purchase_amount)
- flt(asset.opening_accumulated_depreciation)
- flt(row.expected_value_after_useful_life)
- flt(fb_row.expected_value_after_useful_life)
)
/ flt(shift_factors_sum)
) * shift_factor
@@ -195,7 +177,7 @@ def get_asset_shift_factors_map():
def get_wdv_or_dd_depr_amount(
asset,
fb_row,
depreciable_value,
value_after_depreciation,
yearly_opening_wdv,
schedule_idx,
prev_depreciation_amount,
@@ -206,7 +188,7 @@ def get_wdv_or_dd_depr_amount(
return get_default_wdv_or_dd_depr_amount(
asset,
fb_row,
depreciable_value,
value_after_depreciation,
schedule_idx,
prev_depreciation_amount,
has_wdv_or_dd_non_yearly_pro_rata,
@@ -218,7 +200,7 @@ def get_wdv_or_dd_depr_amount(
def get_default_wdv_or_dd_depr_amount(
asset,
fb_row,
depreciable_value,
value_after_depreciation,
schedule_idx,
prev_depreciation_amount,
has_wdv_or_dd_non_yearly_pro_rata,
@@ -229,7 +211,7 @@ def get_default_wdv_or_dd_depr_amount(
return _get_default_wdv_or_dd_depr_amount(
asset,
fb_row,
depreciable_value,
value_after_depreciation,
schedule_idx,
prev_depreciation_amount,
has_wdv_or_dd_non_yearly_pro_rata,
@@ -239,7 +221,7 @@ def get_default_wdv_or_dd_depr_amount(
return _get_daily_prorata_based_default_wdv_or_dd_depr_amount(
asset,
fb_row,
depreciable_value,
value_after_depreciation,
schedule_idx,
prev_depreciation_amount,
has_wdv_or_dd_non_yearly_pro_rata,
@@ -251,21 +233,21 @@ def get_default_wdv_or_dd_depr_amount(
def _get_default_wdv_or_dd_depr_amount(
asset,
fb_row,
depreciable_value,
value_after_depreciation,
schedule_idx,
prev_depreciation_amount,
has_wdv_or_dd_non_yearly_pro_rata,
asset_depr_schedule,
):
if cint(fb_row.frequency_of_depreciation) == 12:
return flt(depreciable_value) * (flt(fb_row.rate_of_depreciation) / 100)
return flt(value_after_depreciation) * (flt(fb_row.rate_of_depreciation) / 100)
else:
if has_wdv_or_dd_non_yearly_pro_rata:
if schedule_idx == 0:
return flt(depreciable_value) * (flt(fb_row.rate_of_depreciation) / 100)
return flt(value_after_depreciation) * (flt(fb_row.rate_of_depreciation) / 100)
elif schedule_idx % (12 / cint(fb_row.frequency_of_depreciation)) == 1:
return (
flt(depreciable_value)
flt(value_after_depreciation)
* flt(fb_row.frequency_of_depreciation)
* (flt(fb_row.rate_of_depreciation) / 1200)
)
@@ -274,7 +256,7 @@ def _get_default_wdv_or_dd_depr_amount(
else:
if schedule_idx % (12 / cint(fb_row.frequency_of_depreciation)) == 0:
return (
flt(depreciable_value)
flt(value_after_depreciation)
* flt(fb_row.frequency_of_depreciation)
* (flt(fb_row.rate_of_depreciation) / 1200)
)
@@ -285,7 +267,7 @@ def _get_default_wdv_or_dd_depr_amount(
def _get_daily_prorata_based_default_wdv_or_dd_depr_amount(
asset,
fb_row,
depreciable_value,
value_after_depreciation,
schedule_idx,
prev_depreciation_amount,
has_wdv_or_dd_non_yearly_pro_rata,
@@ -294,20 +276,20 @@ def _get_daily_prorata_based_default_wdv_or_dd_depr_amount(
):
if has_wdv_or_dd_non_yearly_pro_rata: # If applicable days for ther first month is less than full month
if schedule_idx == 0:
return flt(depreciable_value) * (flt(fb_row.rate_of_depreciation) / 100), None
return flt(value_after_depreciation) * (flt(fb_row.rate_of_depreciation) / 100), None
elif schedule_idx % (12 / cint(fb_row.frequency_of_depreciation)) == 1: # Year changes
return get_monthly_depr_amount(fb_row, schedule_idx, depreciable_value)
return get_monthly_depr_amount(fb_row, schedule_idx, value_after_depreciation)
else:
return get_monthly_depr_amount_based_on_prev_per_day_depr(fb_row, schedule_idx, prev_per_day_depr)
else:
if schedule_idx % (12 / cint(fb_row.frequency_of_depreciation)) == 0: # year changes
return get_monthly_depr_amount(fb_row, schedule_idx, depreciable_value)
return get_monthly_depr_amount(fb_row, schedule_idx, value_after_depreciation)
else:
return get_monthly_depr_amount_based_on_prev_per_day_depr(fb_row, schedule_idx, prev_per_day_depr)
def get_monthly_depr_amount(fb_row, schedule_idx, depreciable_value):
def get_monthly_depr_amount(fb_row, schedule_idx, value_after_depreciation):
"""
Returns monthly depreciation amount when year changes
1. Calculate per day depr based on new year
@@ -316,7 +298,7 @@ def get_monthly_depr_amount(fb_row, schedule_idx, depreciable_value):
from_date, days_in_month = _get_total_days(
fb_row.depreciation_start_date, schedule_idx, cint(fb_row.frequency_of_depreciation)
)
per_day_depr = get_per_day_depr(fb_row, depreciable_value, from_date)
per_day_depr = get_per_day_depr(fb_row, value_after_depreciation, from_date)
return (per_day_depr * days_in_month), per_day_depr
@@ -333,12 +315,12 @@ def get_monthly_depr_amount_based_on_prev_per_day_depr(fb_row, schedule_idx, pre
def get_per_day_depr(
fb_row,
depreciable_value,
value_after_depreciation,
from_date,
):
to_date = add_days(add_years(from_date, 1), -1)
total_days = date_diff(to_date, from_date) + 1
per_day_depr = (flt(depreciable_value) * (flt(fb_row.rate_of_depreciation) / 100)) / total_days
per_day_depr = (flt(value_after_depreciation) * (flt(fb_row.rate_of_depreciation) / 100)) / total_days
return per_day_depr

View File

@@ -9,6 +9,7 @@
"depreciation_method",
"frequency_of_depreciation",
"total_number_of_depreciations",
"increase_in_asset_life",
"depreciation_start_date",
"column_break_5",
"salvage_value_percentage",
@@ -61,7 +62,6 @@
{
"fieldname": "depreciation_start_date",
"fieldtype": "Date",
"hidden": 1,
"in_list_view": 1,
"label": "Depreciation Posting Date",
"mandatory_depends_on": "eval:parent.doctype == 'Asset'"
@@ -101,7 +101,7 @@
"default": "0",
"fieldname": "daily_prorata_based",
"fieldtype": "Check",
"label": "Depreciate based on days per period"
"label": "Depreciate based on daily pro-rata"
},
{
"default": "0",
@@ -125,12 +125,20 @@
{
"fieldname": "column_break_sigk",
"fieldtype": "Column Break"
},
{
"description": "via Asset Repair",
"fieldname": "increase_in_asset_life",
"fieldtype": "Int",
"label": "Increase In Asset Life (Months)",
"no_copy": 1,
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-12-13 12:11:03.743209",
"modified": "2024-12-19 17:50:24.012434",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Finance Book",

View File

@@ -22,6 +22,7 @@ class AssetFinanceBook(Document):
expected_value_after_useful_life: DF.Currency
finance_book: DF.Link | None
frequency_of_depreciation: DF.Int
increase_in_asset_life: DF.Int
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data

View File

@@ -419,5 +419,6 @@ def get_expense_accounts(doctype, txt, searchfield, start, page_len, filters):
return (
frappe.qb.from_(PurchaseInvoiceItem)
.select(PurchaseInvoiceItem.expense_account)
.distinct()
.where(PurchaseInvoiceItem.parent == filters.get("purchase_invoice"))
).run(as_list=1)

View File

@@ -45,6 +45,9 @@ frappe.ui.form.on("Asset Value Adjustment", {
asset: function (frm) {
frm.trigger("set_acc_dimension");
if (frm.doc.asset) {
frm.trigger("set_current_asset_value");
}
},
finance_book: function (frm) {

View File

@@ -54,8 +54,8 @@
"fieldname": "journal_entry",
"fieldtype": "Link",
"label": "Journal Entry",
"options": "Journal Entry",
"no_copy": 1,
"options": "Journal Entry",
"read_only": 1
},
{
@@ -125,18 +125,18 @@
"fieldtype": "Column Break"
},
{
"fieldname": "difference_account",
"fieldtype": "Link",
"label": "Difference Account",
"no_copy": 1,
"options": "Account",
"reqd": 1
"fieldname": "difference_account",
"fieldtype": "Link",
"label": "Difference Account",
"no_copy": 1,
"options": "Account",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-08-13 16:21:18.639208",
"modified": "2024-12-18 15:04:18.726505",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Value Adjustment",
@@ -188,7 +188,6 @@
"write": 1
}
],
"quick_entry": 1,
"sort_field": "creation",
"sort_order": "DESC",
"states": [],