fix: Clear Depreciation Schedule before modification (#28507)
This commit is contained in:
commit
ce80585d51
@ -185,83 +185,84 @@ class Asset(AccountsController):
|
|||||||
if not self.available_for_use_date:
|
if not self.available_for_use_date:
|
||||||
return
|
return
|
||||||
|
|
||||||
for d in self.get('finance_books'):
|
start = self.clear_depreciation_schedule()
|
||||||
self.validate_asset_finance_books(d)
|
|
||||||
|
|
||||||
start = self.clear_depreciation_schedule()
|
for finance_book in self.get('finance_books'):
|
||||||
|
self.validate_asset_finance_books(finance_book)
|
||||||
|
|
||||||
# value_after_depreciation - current Asset value
|
# value_after_depreciation - current Asset value
|
||||||
if self.docstatus == 1 and d.value_after_depreciation:
|
if self.docstatus == 1 and finance_book.value_after_depreciation:
|
||||||
value_after_depreciation = flt(d.value_after_depreciation)
|
value_after_depreciation = flt(finance_book.value_after_depreciation)
|
||||||
else:
|
else:
|
||||||
value_after_depreciation = (flt(self.gross_purchase_amount) -
|
value_after_depreciation = (flt(self.gross_purchase_amount) -
|
||||||
flt(self.opening_accumulated_depreciation))
|
flt(self.opening_accumulated_depreciation))
|
||||||
|
|
||||||
d.value_after_depreciation = value_after_depreciation
|
finance_book.value_after_depreciation = value_after_depreciation
|
||||||
|
|
||||||
number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \
|
number_of_pending_depreciations = cint(finance_book.total_number_of_depreciations) - \
|
||||||
cint(self.number_of_depreciations_booked)
|
cint(self.number_of_depreciations_booked)
|
||||||
|
|
||||||
has_pro_rata = self.check_is_pro_rata(d)
|
has_pro_rata = self.check_is_pro_rata(finance_book)
|
||||||
|
|
||||||
if has_pro_rata:
|
if has_pro_rata:
|
||||||
number_of_pending_depreciations += 1
|
number_of_pending_depreciations += 1
|
||||||
|
|
||||||
skip_row = False
|
skip_row = False
|
||||||
for n in range(start, number_of_pending_depreciations):
|
|
||||||
|
for n in range(start[finance_book.idx-1], number_of_pending_depreciations):
|
||||||
# If depreciation is already completed (for double declining balance)
|
# If depreciation is already completed (for double declining balance)
|
||||||
if skip_row: continue
|
if skip_row: continue
|
||||||
|
|
||||||
depreciation_amount = get_depreciation_amount(self, value_after_depreciation, d)
|
depreciation_amount = get_depreciation_amount(self, value_after_depreciation, finance_book)
|
||||||
|
|
||||||
if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
|
if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
|
||||||
schedule_date = add_months(d.depreciation_start_date,
|
schedule_date = add_months(finance_book.depreciation_start_date,
|
||||||
n * cint(d.frequency_of_depreciation))
|
n * cint(finance_book.frequency_of_depreciation))
|
||||||
|
|
||||||
# schedule date will be a year later from start date
|
# schedule date will be a year later from start date
|
||||||
# so monthly schedule date is calculated by removing 11 months from it
|
# so monthly schedule date is calculated by removing 11 months from it
|
||||||
monthly_schedule_date = add_months(schedule_date, - d.frequency_of_depreciation + 1)
|
monthly_schedule_date = add_months(schedule_date, - finance_book.frequency_of_depreciation + 1)
|
||||||
|
|
||||||
# if asset is being sold
|
# if asset is being sold
|
||||||
if date_of_sale:
|
if date_of_sale:
|
||||||
from_date = self.get_from_date(d.finance_book)
|
from_date = self.get_from_date(finance_book.finance_book)
|
||||||
depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
|
depreciation_amount, days, months = self.get_pro_rata_amt(finance_book, depreciation_amount,
|
||||||
from_date, date_of_sale)
|
from_date, date_of_sale)
|
||||||
|
|
||||||
if depreciation_amount > 0:
|
if depreciation_amount > 0:
|
||||||
self.append("schedules", {
|
self.append("schedules", {
|
||||||
"schedule_date": date_of_sale,
|
"schedule_date": date_of_sale,
|
||||||
"depreciation_amount": depreciation_amount,
|
"depreciation_amount": depreciation_amount,
|
||||||
"depreciation_method": d.depreciation_method,
|
"depreciation_method": finance_book.depreciation_method,
|
||||||
"finance_book": d.finance_book,
|
"finance_book": finance_book.finance_book,
|
||||||
"finance_book_id": d.idx
|
"finance_book_id": finance_book.idx
|
||||||
})
|
})
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
# For first row
|
# For first row
|
||||||
if has_pro_rata and not self.opening_accumulated_depreciation and n==0:
|
if has_pro_rata and not self.opening_accumulated_depreciation and n==0:
|
||||||
depreciation_amount, days, months = self.get_pro_rata_amt(d, depreciation_amount,
|
depreciation_amount, days, months = self.get_pro_rata_amt(finance_book, depreciation_amount,
|
||||||
self.available_for_use_date, d.depreciation_start_date)
|
self.available_for_use_date, finance_book.depreciation_start_date)
|
||||||
|
|
||||||
# For first depr schedule date will be the start date
|
# For first depr schedule date will be the start date
|
||||||
# so monthly schedule date is calculated by removing month difference between use date and start date
|
# so monthly schedule date is calculated by removing month difference between use date and start date
|
||||||
monthly_schedule_date = add_months(d.depreciation_start_date, - months + 1)
|
monthly_schedule_date = add_months(finance_book.depreciation_start_date, - months + 1)
|
||||||
|
|
||||||
# For last row
|
# For last row
|
||||||
elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
|
elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
|
||||||
if not self.flags.increase_in_asset_life:
|
if not self.flags.increase_in_asset_life:
|
||||||
# In case of increase_in_asset_life, the self.to_date is already set on asset_repair submission
|
# In case of increase_in_asset_life, the self.to_date is already set on asset_repair submission
|
||||||
self.to_date = add_months(self.available_for_use_date,
|
self.to_date = add_months(self.available_for_use_date,
|
||||||
(n + self.number_of_depreciations_booked) * cint(d.frequency_of_depreciation))
|
(n + self.number_of_depreciations_booked) * cint(finance_book.frequency_of_depreciation))
|
||||||
|
|
||||||
depreciation_amount_without_pro_rata = depreciation_amount
|
depreciation_amount_without_pro_rata = depreciation_amount
|
||||||
|
|
||||||
depreciation_amount, days, months = self.get_pro_rata_amt(d,
|
depreciation_amount, days, months = self.get_pro_rata_amt(finance_book,
|
||||||
depreciation_amount, schedule_date, self.to_date)
|
depreciation_amount, schedule_date, self.to_date)
|
||||||
|
|
||||||
depreciation_amount = self.get_adjusted_depreciation_amount(depreciation_amount_without_pro_rata,
|
depreciation_amount = self.get_adjusted_depreciation_amount(depreciation_amount_without_pro_rata,
|
||||||
depreciation_amount, d.finance_book)
|
depreciation_amount, finance_book.finance_book)
|
||||||
|
|
||||||
monthly_schedule_date = add_months(schedule_date, 1)
|
monthly_schedule_date = add_months(schedule_date, 1)
|
||||||
schedule_date = add_days(schedule_date, days)
|
schedule_date = add_days(schedule_date, days)
|
||||||
@ -272,10 +273,10 @@ class Asset(AccountsController):
|
|||||||
self.precision("gross_purchase_amount"))
|
self.precision("gross_purchase_amount"))
|
||||||
|
|
||||||
# Adjust depreciation amount in the last period based on the expected value after useful life
|
# Adjust depreciation amount in the last period based on the expected value after useful life
|
||||||
if d.expected_value_after_useful_life and ((n == cint(number_of_pending_depreciations) - 1
|
if finance_book.expected_value_after_useful_life and ((n == cint(number_of_pending_depreciations) - 1
|
||||||
and value_after_depreciation != d.expected_value_after_useful_life)
|
and value_after_depreciation != finance_book.expected_value_after_useful_life)
|
||||||
or value_after_depreciation < d.expected_value_after_useful_life):
|
or value_after_depreciation < finance_book.expected_value_after_useful_life):
|
||||||
depreciation_amount += (value_after_depreciation - d.expected_value_after_useful_life)
|
depreciation_amount += (value_after_depreciation - finance_book.expected_value_after_useful_life)
|
||||||
skip_row = True
|
skip_row = True
|
||||||
|
|
||||||
if depreciation_amount > 0:
|
if depreciation_amount > 0:
|
||||||
@ -285,7 +286,7 @@ class Asset(AccountsController):
|
|||||||
# In pro rata case, for first and last depreciation, month range would be different
|
# In pro rata case, for first and last depreciation, month range would be different
|
||||||
month_range = months \
|
month_range = months \
|
||||||
if (has_pro_rata and n==0) or (has_pro_rata and n == cint(number_of_pending_depreciations) - 1) \
|
if (has_pro_rata and n==0) or (has_pro_rata and n == cint(number_of_pending_depreciations) - 1) \
|
||||||
else d.frequency_of_depreciation
|
else finance_book.frequency_of_depreciation
|
||||||
|
|
||||||
for r in range(month_range):
|
for r in range(month_range):
|
||||||
if (has_pro_rata and n == 0):
|
if (has_pro_rata and n == 0):
|
||||||
@ -311,27 +312,52 @@ class Asset(AccountsController):
|
|||||||
self.append("schedules", {
|
self.append("schedules", {
|
||||||
"schedule_date": date,
|
"schedule_date": date,
|
||||||
"depreciation_amount": amount,
|
"depreciation_amount": amount,
|
||||||
"depreciation_method": d.depreciation_method,
|
"depreciation_method": finance_book.depreciation_method,
|
||||||
"finance_book": d.finance_book,
|
"finance_book": finance_book.finance_book,
|
||||||
"finance_book_id": d.idx
|
"finance_book_id": finance_book.idx
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
self.append("schedules", {
|
self.append("schedules", {
|
||||||
"schedule_date": schedule_date,
|
"schedule_date": schedule_date,
|
||||||
"depreciation_amount": depreciation_amount,
|
"depreciation_amount": depreciation_amount,
|
||||||
"depreciation_method": d.depreciation_method,
|
"depreciation_method": finance_book.depreciation_method,
|
||||||
"finance_book": d.finance_book,
|
"finance_book": finance_book.finance_book,
|
||||||
"finance_book_id": d.idx
|
"finance_book_id": finance_book.idx
|
||||||
})
|
})
|
||||||
|
|
||||||
# used when depreciation schedule needs to be modified due to increase in asset life
|
# depreciation schedules need to be cleared before modification due to increase in asset life/asset sales
|
||||||
|
# JE: Journal Entry, FB: Finance Book
|
||||||
def clear_depreciation_schedule(self):
|
def clear_depreciation_schedule(self):
|
||||||
start = 0
|
start = []
|
||||||
for n in range(len(self.schedules)):
|
num_of_depreciations_completed = 0
|
||||||
if not self.schedules[n].journal_entry:
|
depr_schedule = []
|
||||||
del self.schedules[n:]
|
|
||||||
start = n
|
for schedule in self.get('schedules'):
|
||||||
break
|
|
||||||
|
# to update start when there are JEs linked with all the schedule rows corresponding to an FB
|
||||||
|
if len(start) == (int(schedule.finance_book_id) - 2):
|
||||||
|
start.append(num_of_depreciations_completed)
|
||||||
|
num_of_depreciations_completed = 0
|
||||||
|
|
||||||
|
# to ensure that start will only be updated once for each FB
|
||||||
|
if len(start) == (int(schedule.finance_book_id) - 1):
|
||||||
|
if schedule.journal_entry:
|
||||||
|
num_of_depreciations_completed += 1
|
||||||
|
depr_schedule.append(schedule)
|
||||||
|
else:
|
||||||
|
start.append(num_of_depreciations_completed)
|
||||||
|
num_of_depreciations_completed = 0
|
||||||
|
|
||||||
|
# to update start when all the schedule rows corresponding to the last FB are linked with JEs
|
||||||
|
if len(start) == (len(self.finance_books) - 1):
|
||||||
|
start.append(num_of_depreciations_completed)
|
||||||
|
|
||||||
|
# when the Depreciation Schedule is being created for the first time
|
||||||
|
if start == []:
|
||||||
|
start = [0] * len(self.finance_books)
|
||||||
|
else:
|
||||||
|
self.schedules = depr_schedule
|
||||||
|
|
||||||
return start
|
return start
|
||||||
|
|
||||||
def get_from_date(self, finance_book):
|
def get_from_date(self, finance_book):
|
||||||
|
@ -955,6 +955,82 @@ class TestDepreciationBasics(AssetSetup):
|
|||||||
|
|
||||||
self.assertEqual(len(asset.schedules), 1)
|
self.assertEqual(len(asset.schedules), 1)
|
||||||
|
|
||||||
|
def test_clear_depreciation_schedule_for_multiple_finance_books(self):
|
||||||
|
asset = create_asset(
|
||||||
|
item_code = "Macbook Pro",
|
||||||
|
available_for_use_date = "2019-12-31",
|
||||||
|
do_not_save = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
asset.calculate_depreciation = 1
|
||||||
|
asset.append("finance_books", {
|
||||||
|
"depreciation_method": "Straight Line",
|
||||||
|
"frequency_of_depreciation": 1,
|
||||||
|
"total_number_of_depreciations": 3,
|
||||||
|
"expected_value_after_useful_life": 10000,
|
||||||
|
"depreciation_start_date": "2020-01-31"
|
||||||
|
})
|
||||||
|
asset.append("finance_books", {
|
||||||
|
"depreciation_method": "Straight Line",
|
||||||
|
"frequency_of_depreciation": 1,
|
||||||
|
"total_number_of_depreciations": 6,
|
||||||
|
"expected_value_after_useful_life": 10000,
|
||||||
|
"depreciation_start_date": "2020-01-31"
|
||||||
|
})
|
||||||
|
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": "2020-12-31"
|
||||||
|
})
|
||||||
|
asset.submit()
|
||||||
|
|
||||||
|
post_depreciation_entries(date="2020-04-01")
|
||||||
|
asset.load_from_db()
|
||||||
|
|
||||||
|
asset.clear_depreciation_schedule()
|
||||||
|
|
||||||
|
self.assertEqual(len(asset.schedules), 6)
|
||||||
|
|
||||||
|
for schedule in asset.schedules:
|
||||||
|
if schedule.idx <= 3:
|
||||||
|
self.assertEqual(schedule.finance_book_id, "1")
|
||||||
|
else:
|
||||||
|
self.assertEqual(schedule.finance_book_id, "2")
|
||||||
|
|
||||||
|
def test_depreciation_schedules_are_set_up_for_multiple_finance_books(self):
|
||||||
|
asset = create_asset(
|
||||||
|
item_code = "Macbook Pro",
|
||||||
|
available_for_use_date = "2019-12-31",
|
||||||
|
do_not_save = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
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": "2020-12-31"
|
||||||
|
})
|
||||||
|
asset.append("finance_books", {
|
||||||
|
"depreciation_method": "Straight Line",
|
||||||
|
"frequency_of_depreciation": 12,
|
||||||
|
"total_number_of_depreciations": 6,
|
||||||
|
"expected_value_after_useful_life": 10000,
|
||||||
|
"depreciation_start_date": "2020-12-31"
|
||||||
|
})
|
||||||
|
asset.save()
|
||||||
|
|
||||||
|
self.assertEqual(len(asset.schedules), 9)
|
||||||
|
|
||||||
|
for schedule in asset.schedules:
|
||||||
|
if schedule.idx <= 3:
|
||||||
|
self.assertEqual(schedule.finance_book_id, 1)
|
||||||
|
else:
|
||||||
|
self.assertEqual(schedule.finance_book_id, 2)
|
||||||
|
|
||||||
def test_depreciation_entry_cancellation(self):
|
def test_depreciation_entry_cancellation(self):
|
||||||
asset = create_asset(
|
asset = create_asset(
|
||||||
item_code = "Macbook Pro",
|
item_code = "Macbook Pro",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user