fix: incorrect schedule in asset value adjustment (#36747)
This commit is contained in:
parent
4b75b6f309
commit
8f04945cef
@ -56,7 +56,6 @@ class Asset(AccountsController):
|
|||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.validate_in_use_date()
|
self.validate_in_use_date()
|
||||||
self.set_status()
|
|
||||||
self.make_asset_movement()
|
self.make_asset_movement()
|
||||||
if not self.booked_fixed_asset and self.validate_make_gl_entry():
|
if not self.booked_fixed_asset and self.validate_make_gl_entry():
|
||||||
self.make_gl_entries()
|
self.make_gl_entries()
|
||||||
@ -72,6 +71,7 @@ class Asset(AccountsController):
|
|||||||
"Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
|
"Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
|
||||||
).format(asset_depr_schedules_links)
|
).format(asset_depr_schedules_links)
|
||||||
)
|
)
|
||||||
|
self.set_status()
|
||||||
add_asset_activity(self.name, _("Asset submitted"))
|
add_asset_activity(self.name, _("Asset submitted"))
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
|
|||||||
@ -19,6 +19,7 @@ from frappe.utils import (
|
|||||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||||
from erpnext.assets.doctype.asset.asset import (
|
from erpnext.assets.doctype.asset.asset import (
|
||||||
|
get_asset_value_after_depreciation,
|
||||||
make_sales_invoice,
|
make_sales_invoice,
|
||||||
split_asset,
|
split_asset,
|
||||||
update_maintenance_status,
|
update_maintenance_status,
|
||||||
|
|||||||
@ -107,7 +107,7 @@ class AssetDepreciationSchedule(Document):
|
|||||||
have_asset_details_been_modified, not_manual_depr_or_have_manual_depr_details_been_modified
|
have_asset_details_been_modified, not_manual_depr_or_have_manual_depr_details_been_modified
|
||||||
):
|
):
|
||||||
self.make_depr_schedule(asset_doc, row, date_of_disposal, update_asset_finance_book_row)
|
self.make_depr_schedule(asset_doc, row, date_of_disposal, update_asset_finance_book_row)
|
||||||
self.set_accumulated_depreciation(row, date_of_disposal, date_of_return)
|
self.set_accumulated_depreciation(asset_doc, row, date_of_disposal, date_of_return)
|
||||||
|
|
||||||
def have_asset_details_been_modified(self, asset_doc):
|
def have_asset_details_been_modified(self, asset_doc):
|
||||||
return (
|
return (
|
||||||
@ -157,7 +157,12 @@ class AssetDepreciationSchedule(Document):
|
|||||||
self.status = "Draft"
|
self.status = "Draft"
|
||||||
|
|
||||||
def make_depr_schedule(
|
def make_depr_schedule(
|
||||||
self, asset_doc, row, date_of_disposal, update_asset_finance_book_row=True
|
self,
|
||||||
|
asset_doc,
|
||||||
|
row,
|
||||||
|
date_of_disposal,
|
||||||
|
update_asset_finance_book_row=True,
|
||||||
|
value_after_depreciation=None,
|
||||||
):
|
):
|
||||||
if not self.get("depreciation_schedule"):
|
if not self.get("depreciation_schedule"):
|
||||||
self.depreciation_schedule = []
|
self.depreciation_schedule = []
|
||||||
@ -167,7 +172,9 @@ class AssetDepreciationSchedule(Document):
|
|||||||
|
|
||||||
start = self.clear_depr_schedule()
|
start = self.clear_depr_schedule()
|
||||||
|
|
||||||
self._make_depr_schedule(asset_doc, row, start, date_of_disposal, update_asset_finance_book_row)
|
self._make_depr_schedule(
|
||||||
|
asset_doc, row, start, date_of_disposal, update_asset_finance_book_row, value_after_depreciation
|
||||||
|
)
|
||||||
|
|
||||||
def clear_depr_schedule(self):
|
def clear_depr_schedule(self):
|
||||||
start = 0
|
start = 0
|
||||||
@ -187,23 +194,30 @@ class AssetDepreciationSchedule(Document):
|
|||||||
return start
|
return start
|
||||||
|
|
||||||
def _make_depr_schedule(
|
def _make_depr_schedule(
|
||||||
self, asset_doc, row, start, date_of_disposal, update_asset_finance_book_row
|
self,
|
||||||
|
asset_doc,
|
||||||
|
row,
|
||||||
|
start,
|
||||||
|
date_of_disposal,
|
||||||
|
update_asset_finance_book_row,
|
||||||
|
value_after_depreciation,
|
||||||
):
|
):
|
||||||
asset_doc.validate_asset_finance_books(row)
|
asset_doc.validate_asset_finance_books(row)
|
||||||
|
|
||||||
value_after_depreciation = _get_value_after_depreciation_for_making_schedule(asset_doc, row)
|
if not value_after_depreciation:
|
||||||
|
value_after_depreciation = _get_value_after_depreciation_for_making_schedule(asset_doc, row)
|
||||||
row.value_after_depreciation = value_after_depreciation
|
row.value_after_depreciation = value_after_depreciation
|
||||||
|
|
||||||
if update_asset_finance_book_row:
|
if update_asset_finance_book_row:
|
||||||
row.db_update()
|
row.db_update()
|
||||||
|
|
||||||
number_of_pending_depreciations = cint(row.total_number_of_depreciations) - cint(
|
final_number_of_depreciations = cint(row.total_number_of_depreciations) - cint(
|
||||||
self.number_of_depreciations_booked
|
self.number_of_depreciations_booked
|
||||||
)
|
)
|
||||||
|
|
||||||
has_pro_rata = _check_is_pro_rata(asset_doc, row)
|
has_pro_rata = _check_is_pro_rata(asset_doc, row)
|
||||||
if has_pro_rata:
|
if has_pro_rata:
|
||||||
number_of_pending_depreciations += 1
|
final_number_of_depreciations += 1
|
||||||
|
|
||||||
has_wdv_or_dd_non_yearly_pro_rata = False
|
has_wdv_or_dd_non_yearly_pro_rata = False
|
||||||
if (
|
if (
|
||||||
@ -219,7 +233,9 @@ class AssetDepreciationSchedule(Document):
|
|||||||
|
|
||||||
depreciation_amount = 0
|
depreciation_amount = 0
|
||||||
|
|
||||||
for n in range(start, number_of_pending_depreciations):
|
number_of_pending_depreciations = final_number_of_depreciations - start
|
||||||
|
|
||||||
|
for n in range(start, final_number_of_depreciations):
|
||||||
# If depreciation is already completed (for double declining balance)
|
# If depreciation is already completed (for double declining balance)
|
||||||
if skip_row:
|
if skip_row:
|
||||||
continue
|
continue
|
||||||
@ -236,10 +252,11 @@ class AssetDepreciationSchedule(Document):
|
|||||||
n,
|
n,
|
||||||
prev_depreciation_amount,
|
prev_depreciation_amount,
|
||||||
has_wdv_or_dd_non_yearly_pro_rata,
|
has_wdv_or_dd_non_yearly_pro_rata,
|
||||||
|
number_of_pending_depreciations,
|
||||||
)
|
)
|
||||||
|
|
||||||
if not has_pro_rata or (
|
if not has_pro_rata or (
|
||||||
n < (cint(number_of_pending_depreciations) - 1) or number_of_pending_depreciations == 2
|
n < (cint(final_number_of_depreciations) - 1) or final_number_of_depreciations == 2
|
||||||
):
|
):
|
||||||
schedule_date = add_months(
|
schedule_date = add_months(
|
||||||
row.depreciation_start_date, n * cint(row.frequency_of_depreciation)
|
row.depreciation_start_date, n * cint(row.frequency_of_depreciation)
|
||||||
@ -310,7 +327,7 @@ class AssetDepreciationSchedule(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 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(final_number_of_depreciations) - 1:
|
||||||
if not asset_doc.flags.increase_in_asset_life:
|
if not asset_doc.flags.increase_in_asset_life:
|
||||||
# In case of increase_in_asset_life, the asset.to_date is already set on asset_repair submission
|
# In case of increase_in_asset_life, the asset.to_date is already set on asset_repair submission
|
||||||
asset_doc.to_date = add_months(
|
asset_doc.to_date = add_months(
|
||||||
@ -343,7 +360,7 @@ class AssetDepreciationSchedule(Document):
|
|||||||
# 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 row.expected_value_after_useful_life and (
|
if row.expected_value_after_useful_life and (
|
||||||
(
|
(
|
||||||
n == cint(number_of_pending_depreciations) - 1
|
n == cint(final_number_of_depreciations) - 1
|
||||||
and value_after_depreciation != row.expected_value_after_useful_life
|
and value_after_depreciation != row.expected_value_after_useful_life
|
||||||
)
|
)
|
||||||
or value_after_depreciation < row.expected_value_after_useful_life
|
or value_after_depreciation < row.expected_value_after_useful_life
|
||||||
@ -392,6 +409,7 @@ class AssetDepreciationSchedule(Document):
|
|||||||
|
|
||||||
def set_accumulated_depreciation(
|
def set_accumulated_depreciation(
|
||||||
self,
|
self,
|
||||||
|
asset_doc,
|
||||||
row,
|
row,
|
||||||
date_of_disposal=None,
|
date_of_disposal=None,
|
||||||
date_of_return=None,
|
date_of_return=None,
|
||||||
@ -403,13 +421,21 @@ class AssetDepreciationSchedule(Document):
|
|||||||
if self.depreciation_method == "Straight Line" or self.depreciation_method == "Manual"
|
if self.depreciation_method == "Straight Line" or self.depreciation_method == "Manual"
|
||||||
]
|
]
|
||||||
|
|
||||||
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
|
accumulated_depreciation = None
|
||||||
value_after_depreciation = flt(row.value_after_depreciation)
|
value_after_depreciation = flt(row.value_after_depreciation)
|
||||||
|
|
||||||
for i, d in enumerate(self.get("depreciation_schedule")):
|
for i, d in enumerate(self.get("depreciation_schedule")):
|
||||||
if ignore_booked_entry and d.journal_entry:
|
if ignore_booked_entry and d.journal_entry:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if not accumulated_depreciation:
|
||||||
|
if i > 0 and asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment:
|
||||||
|
accumulated_depreciation = self.get("depreciation_schedule")[
|
||||||
|
i - 1
|
||||||
|
].accumulated_depreciation_amount
|
||||||
|
else:
|
||||||
|
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
|
||||||
|
|
||||||
depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
|
depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
|
||||||
value_after_depreciation -= flt(depreciation_amount)
|
value_after_depreciation -= flt(depreciation_amount)
|
||||||
|
|
||||||
@ -507,9 +533,12 @@ def get_depreciation_amount(
|
|||||||
schedule_idx=0,
|
schedule_idx=0,
|
||||||
prev_depreciation_amount=0,
|
prev_depreciation_amount=0,
|
||||||
has_wdv_or_dd_non_yearly_pro_rata=False,
|
has_wdv_or_dd_non_yearly_pro_rata=False,
|
||||||
|
number_of_pending_depreciations=0,
|
||||||
):
|
):
|
||||||
if fb_row.depreciation_method in ("Straight Line", "Manual"):
|
if fb_row.depreciation_method in ("Straight Line", "Manual"):
|
||||||
return get_straight_line_or_manual_depr_amount(asset, fb_row, schedule_idx)
|
return get_straight_line_or_manual_depr_amount(
|
||||||
|
asset, fb_row, schedule_idx, number_of_pending_depreciations
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
rate_of_depreciation = get_updated_rate_of_depreciation_for_wdv_and_dd(
|
rate_of_depreciation = get_updated_rate_of_depreciation_for_wdv_and_dd(
|
||||||
asset, depreciable_value, fb_row
|
asset, depreciable_value, fb_row
|
||||||
@ -529,7 +558,9 @@ def get_updated_rate_of_depreciation_for_wdv_and_dd(asset, depreciable_value, fb
|
|||||||
return fb_row.rate_of_depreciation
|
return fb_row.rate_of_depreciation
|
||||||
|
|
||||||
|
|
||||||
def get_straight_line_or_manual_depr_amount(asset, row, schedule_idx):
|
def get_straight_line_or_manual_depr_amount(
|
||||||
|
asset, row, schedule_idx, number_of_pending_depreciations
|
||||||
|
):
|
||||||
# if the Depreciation Schedule is being modified after Asset Repair due to increase in asset life and value
|
# 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:
|
if asset.flags.increase_in_asset_life:
|
||||||
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / (
|
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / (
|
||||||
@ -540,6 +571,36 @@ def get_straight_line_or_manual_depr_amount(asset, row, schedule_idx):
|
|||||||
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / flt(
|
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / flt(
|
||||||
row.total_number_of_depreciations
|
row.total_number_of_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_depreciation:
|
||||||
|
daily_depr_amount = (
|
||||||
|
flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)
|
||||||
|
) / date_diff(
|
||||||
|
add_months(
|
||||||
|
row.depreciation_start_date,
|
||||||
|
flt(row.total_number_of_depreciations - asset.number_of_depreciations_booked)
|
||||||
|
* row.frequency_of_depreciation,
|
||||||
|
),
|
||||||
|
add_months(
|
||||||
|
row.depreciation_start_date,
|
||||||
|
flt(
|
||||||
|
row.total_number_of_depreciations
|
||||||
|
- asset.number_of_depreciations_booked
|
||||||
|
- number_of_pending_depreciations
|
||||||
|
)
|
||||||
|
* row.frequency_of_depreciation,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
to_date = add_months(row.depreciation_start_date, schedule_idx * row.frequency_of_depreciation)
|
||||||
|
from_date = add_months(
|
||||||
|
row.depreciation_start_date, (schedule_idx - 1) * row.frequency_of_depreciation
|
||||||
|
)
|
||||||
|
return daily_depr_amount * date_diff(to_date, from_date)
|
||||||
|
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
|
# if the Depreciation Schedule is being prepared for the first time
|
||||||
else:
|
else:
|
||||||
if row.daily_depreciation:
|
if row.daily_depreciation:
|
||||||
@ -669,7 +730,12 @@ def cancel_asset_depr_schedules(asset_doc):
|
|||||||
|
|
||||||
|
|
||||||
def make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
def make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
||||||
asset_doc, notes, date_of_disposal=None, date_of_return=None
|
asset_doc,
|
||||||
|
notes,
|
||||||
|
date_of_disposal=None,
|
||||||
|
date_of_return=None,
|
||||||
|
value_after_depreciation=None,
|
||||||
|
ignore_booked_entry=False,
|
||||||
):
|
):
|
||||||
for row in asset_doc.get("finance_books"):
|
for row in asset_doc.get("finance_books"):
|
||||||
current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(
|
current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(
|
||||||
@ -695,8 +761,12 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
|||||||
row.rate_of_depreciation = new_rate_of_depreciation
|
row.rate_of_depreciation = new_rate_of_depreciation
|
||||||
new_asset_depr_schedule_doc.rate_of_depreciation = new_rate_of_depreciation
|
new_asset_depr_schedule_doc.rate_of_depreciation = new_rate_of_depreciation
|
||||||
|
|
||||||
new_asset_depr_schedule_doc.make_depr_schedule(asset_doc, row, date_of_disposal)
|
new_asset_depr_schedule_doc.make_depr_schedule(
|
||||||
new_asset_depr_schedule_doc.set_accumulated_depreciation(row, date_of_disposal, date_of_return)
|
asset_doc, row, date_of_disposal, value_after_depreciation=value_after_depreciation
|
||||||
|
)
|
||||||
|
new_asset_depr_schedule_doc.set_accumulated_depreciation(
|
||||||
|
asset_doc, row, date_of_disposal, date_of_return, ignore_booked_entry
|
||||||
|
)
|
||||||
|
|
||||||
new_asset_depr_schedule_doc.notes = notes
|
new_asset_depr_schedule_doc.notes = notes
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import date_diff, flt, formatdate, get_link_to_form, getdate
|
from frappe.utils import flt, formatdate, get_link_to_form, getdate
|
||||||
|
|
||||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||||
get_checks_for_pl_and_bs_accounts,
|
get_checks_for_pl_and_bs_accounts,
|
||||||
@ -14,8 +14,7 @@ from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciatio
|
|||||||
from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
|
from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
|
||||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||||
get_asset_depr_schedule_doc,
|
make_new_active_asset_depr_schedules_and_cancel_current_ones,
|
||||||
get_depreciation_amount,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ class AssetValueAdjustment(Document):
|
|||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.make_depreciation_entry()
|
self.make_depreciation_entry()
|
||||||
self.reschedule_depreciations(self.new_asset_value)
|
self.update_asset(self.new_asset_value)
|
||||||
add_asset_activity(
|
add_asset_activity(
|
||||||
self.asset,
|
self.asset,
|
||||||
_("Asset's value adjusted after submission of Asset Value Adjustment {0}").format(
|
_("Asset's value adjusted after submission of Asset Value Adjustment {0}").format(
|
||||||
@ -36,7 +35,7 @@ class AssetValueAdjustment(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.reschedule_depreciations(self.current_asset_value)
|
self.update_asset(self.current_asset_value)
|
||||||
add_asset_activity(
|
add_asset_activity(
|
||||||
self.asset,
|
self.asset,
|
||||||
_("Asset's value adjusted after cancellation of Asset Value Adjustment {0}").format(
|
_("Asset's value adjusted after cancellation of Asset Value Adjustment {0}").format(
|
||||||
@ -124,73 +123,33 @@ class AssetValueAdjustment(Document):
|
|||||||
|
|
||||||
self.db_set("journal_entry", je.name)
|
self.db_set("journal_entry", je.name)
|
||||||
|
|
||||||
def reschedule_depreciations(self, asset_value):
|
def update_asset(self, asset_value):
|
||||||
asset = frappe.get_doc("Asset", self.asset)
|
asset = frappe.get_doc("Asset", self.asset)
|
||||||
country = frappe.get_value("Company", self.company, "country")
|
|
||||||
|
|
||||||
for d in asset.finance_books:
|
if not asset.calculate_depreciation:
|
||||||
d.value_after_depreciation = asset_value
|
asset.value_after_depreciation = asset_value
|
||||||
|
asset.save()
|
||||||
|
return
|
||||||
|
|
||||||
current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(
|
asset.flags.decrease_in_asset_value_due_to_value_adjustment = True
|
||||||
asset.name, "Active", d.finance_book
|
|
||||||
|
if self.docstatus == 1:
|
||||||
|
notes = _(
|
||||||
|
"This schedule was created when Asset {0} was adjusted through Asset Value Adjustment {1}."
|
||||||
|
).format(
|
||||||
|
get_link_to_form("Asset", asset.name),
|
||||||
|
get_link_to_form(self.get("doctype"), self.get("name")),
|
||||||
|
)
|
||||||
|
elif self.docstatus == 2:
|
||||||
|
notes = _(
|
||||||
|
"This schedule was created when Asset {0}'s Asset Value Adjustment {1} was cancelled."
|
||||||
|
).format(
|
||||||
|
get_link_to_form("Asset", asset.name),
|
||||||
|
get_link_to_form(self.get("doctype"), self.get("name")),
|
||||||
)
|
)
|
||||||
|
|
||||||
new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc)
|
make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
||||||
new_asset_depr_schedule_doc.status = "Draft"
|
asset, notes, value_after_depreciation=asset_value, ignore_booked_entry=True
|
||||||
new_asset_depr_schedule_doc.docstatus = 0
|
)
|
||||||
|
asset.flags.ignore_validate_update_after_submit = True
|
||||||
current_asset_depr_schedule_doc.flags.should_not_cancel_depreciation_entries = True
|
asset.save()
|
||||||
current_asset_depr_schedule_doc.cancel()
|
|
||||||
|
|
||||||
if self.docstatus == 1:
|
|
||||||
notes = _(
|
|
||||||
"This schedule was created when Asset {0} was adjusted through Asset Value Adjustment {1}."
|
|
||||||
).format(
|
|
||||||
get_link_to_form(asset.doctype, asset.name),
|
|
||||||
get_link_to_form(self.get("doctype"), self.get("name")),
|
|
||||||
)
|
|
||||||
elif self.docstatus == 2:
|
|
||||||
notes = _(
|
|
||||||
"This schedule was created when Asset {0}'s Asset Value Adjustment {1} was cancelled."
|
|
||||||
).format(
|
|
||||||
get_link_to_form(asset.doctype, asset.name),
|
|
||||||
get_link_to_form(self.get("doctype"), self.get("name")),
|
|
||||||
)
|
|
||||||
new_asset_depr_schedule_doc.notes = notes
|
|
||||||
|
|
||||||
new_asset_depr_schedule_doc.insert()
|
|
||||||
|
|
||||||
depr_schedule = new_asset_depr_schedule_doc.get("depreciation_schedule")
|
|
||||||
|
|
||||||
if d.depreciation_method in ("Straight Line", "Manual"):
|
|
||||||
end_date = max(s.schedule_date for s in depr_schedule)
|
|
||||||
total_days = date_diff(end_date, self.date)
|
|
||||||
rate_per_day = flt(d.value_after_depreciation - d.expected_value_after_useful_life) / flt(
|
|
||||||
total_days
|
|
||||||
)
|
|
||||||
from_date = self.date
|
|
||||||
else:
|
|
||||||
no_of_depreciations = len([s.name for s in depr_schedule if not s.journal_entry])
|
|
||||||
|
|
||||||
value_after_depreciation = d.value_after_depreciation
|
|
||||||
for data in depr_schedule:
|
|
||||||
if not data.journal_entry:
|
|
||||||
if d.depreciation_method in ("Straight Line", "Manual"):
|
|
||||||
days = date_diff(data.schedule_date, from_date)
|
|
||||||
depreciation_amount = days * rate_per_day
|
|
||||||
from_date = data.schedule_date
|
|
||||||
else:
|
|
||||||
depreciation_amount = get_depreciation_amount(asset, value_after_depreciation, d)
|
|
||||||
|
|
||||||
if depreciation_amount:
|
|
||||||
value_after_depreciation -= flt(depreciation_amount)
|
|
||||||
data.depreciation_amount = depreciation_amount
|
|
||||||
|
|
||||||
d.db_update()
|
|
||||||
|
|
||||||
new_asset_depr_schedule_doc.set_accumulated_depreciation(d, ignore_booked_entry=True)
|
|
||||||
for asset_data in depr_schedule:
|
|
||||||
if not asset_data.journal_entry:
|
|
||||||
asset_data.db_update()
|
|
||||||
|
|
||||||
new_asset_depr_schedule_doc.submit()
|
|
||||||
|
|||||||
@ -4,9 +4,10 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import add_days, get_last_day, nowdate
|
from frappe.utils import add_days, cstr, get_last_day, getdate, nowdate
|
||||||
|
|
||||||
from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
|
from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
|
||||||
|
from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
|
||||||
from erpnext.assets.doctype.asset.test_asset import create_asset_data
|
from erpnext.assets.doctype.asset.test_asset import create_asset_data
|
||||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||||
get_asset_depr_schedule_doc,
|
get_asset_depr_schedule_doc,
|
||||||
@ -49,27 +50,23 @@ class TestAssetValueAdjustment(unittest.TestCase):
|
|||||||
|
|
||||||
def test_asset_depreciation_value_adjustment(self):
|
def test_asset_depreciation_value_adjustment(self):
|
||||||
pr = make_purchase_receipt(
|
pr = make_purchase_receipt(
|
||||||
item_code="Macbook Pro", qty=1, rate=100000.0, location="Test Location"
|
item_code="Macbook Pro", qty=1, rate=120000.0, location="Test Location"
|
||||||
)
|
)
|
||||||
|
|
||||||
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name")
|
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name")
|
||||||
asset_doc = frappe.get_doc("Asset", asset_name)
|
asset_doc = frappe.get_doc("Asset", asset_name)
|
||||||
asset_doc.calculate_depreciation = 1
|
asset_doc.calculate_depreciation = 1
|
||||||
|
asset_doc.available_for_use_date = "2023-01-15"
|
||||||
|
asset_doc.purchase_date = "2023-01-15"
|
||||||
|
|
||||||
month_end_date = get_last_day(nowdate())
|
|
||||||
purchase_date = nowdate() if nowdate() != month_end_date else add_days(nowdate(), -15)
|
|
||||||
|
|
||||||
asset_doc.available_for_use_date = purchase_date
|
|
||||||
asset_doc.purchase_date = purchase_date
|
|
||||||
asset_doc.calculate_depreciation = 1
|
|
||||||
asset_doc.append(
|
asset_doc.append(
|
||||||
"finance_books",
|
"finance_books",
|
||||||
{
|
{
|
||||||
"expected_value_after_useful_life": 200,
|
"expected_value_after_useful_life": 200,
|
||||||
"depreciation_method": "Straight Line",
|
"depreciation_method": "Straight Line",
|
||||||
"total_number_of_depreciations": 3,
|
"total_number_of_depreciations": 12,
|
||||||
"frequency_of_depreciation": 10,
|
"frequency_of_depreciation": 1,
|
||||||
"depreciation_start_date": month_end_date,
|
"depreciation_start_date": "2023-01-31",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
asset_doc.submit()
|
asset_doc.submit()
|
||||||
@ -77,9 +74,15 @@ class TestAssetValueAdjustment(unittest.TestCase):
|
|||||||
first_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active")
|
first_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active")
|
||||||
self.assertEquals(first_asset_depr_schedule.status, "Active")
|
self.assertEquals(first_asset_depr_schedule.status, "Active")
|
||||||
|
|
||||||
|
post_depreciation_entries(getdate("2023-08-21"))
|
||||||
|
|
||||||
current_value = get_asset_value_after_depreciation(asset_doc.name)
|
current_value = get_asset_value_after_depreciation(asset_doc.name)
|
||||||
|
|
||||||
adj_doc = make_asset_value_adjustment(
|
adj_doc = make_asset_value_adjustment(
|
||||||
asset=asset_doc.name, current_asset_value=current_value, new_asset_value=50000.0
|
asset=asset_doc.name,
|
||||||
|
current_asset_value=current_value,
|
||||||
|
new_asset_value=50000.0,
|
||||||
|
date="2023-08-21",
|
||||||
)
|
)
|
||||||
adj_doc.submit()
|
adj_doc.submit()
|
||||||
|
|
||||||
@ -90,8 +93,8 @@ class TestAssetValueAdjustment(unittest.TestCase):
|
|||||||
self.assertEquals(first_asset_depr_schedule.status, "Cancelled")
|
self.assertEquals(first_asset_depr_schedule.status, "Cancelled")
|
||||||
|
|
||||||
expected_gle = (
|
expected_gle = (
|
||||||
("_Test Accumulated Depreciations - _TC", 0.0, 50000.0),
|
("_Test Accumulated Depreciations - _TC", 0.0, 4625.29),
|
||||||
("_Test Depreciations - _TC", 50000.0, 0.0),
|
("_Test Depreciations - _TC", 4625.29, 0.0),
|
||||||
)
|
)
|
||||||
|
|
||||||
gle = frappe.db.sql(
|
gle = frappe.db.sql(
|
||||||
@ -103,6 +106,29 @@ class TestAssetValueAdjustment(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertSequenceEqual(gle, expected_gle)
|
self.assertSequenceEqual(gle, expected_gle)
|
||||||
|
|
||||||
|
expected_schedules = [
|
||||||
|
["2023-01-31", 5474.73, 5474.73],
|
||||||
|
["2023-02-28", 9983.33, 15458.06],
|
||||||
|
["2023-03-31", 9983.33, 25441.39],
|
||||||
|
["2023-04-30", 9983.33, 35424.72],
|
||||||
|
["2023-05-31", 9983.33, 45408.05],
|
||||||
|
["2023-06-30", 9983.33, 55391.38],
|
||||||
|
["2023-07-31", 9983.33, 65374.71],
|
||||||
|
["2023-08-31", 8300.0, 73674.71],
|
||||||
|
["2023-09-30", 8300.0, 81974.71],
|
||||||
|
["2023-10-31", 8300.0, 90274.71],
|
||||||
|
["2023-11-30", 8300.0, 98574.71],
|
||||||
|
["2023-12-31", 8300.0, 106874.71],
|
||||||
|
["2024-01-15", 8300.0, 115174.71],
|
||||||
|
]
|
||||||
|
|
||||||
|
schedules = [
|
||||||
|
[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
||||||
|
for d in second_asset_depr_schedule.get("depreciation_schedule")
|
||||||
|
]
|
||||||
|
|
||||||
|
self.assertEqual(schedules, expected_schedules)
|
||||||
|
|
||||||
|
|
||||||
def make_asset_value_adjustment(**args):
|
def make_asset_value_adjustment(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
@ -759,7 +759,7 @@ class BuyingController(SubcontractingController):
|
|||||||
"company": self.company,
|
"company": self.company,
|
||||||
"supplier": self.supplier,
|
"supplier": self.supplier,
|
||||||
"purchase_date": self.posting_date,
|
"purchase_date": self.posting_date,
|
||||||
"calculate_depreciation": 1,
|
"calculate_depreciation": 0,
|
||||||
"purchase_receipt_amount": purchase_amount,
|
"purchase_receipt_amount": purchase_amount,
|
||||||
"gross_purchase_amount": purchase_amount,
|
"gross_purchase_amount": purchase_amount,
|
||||||
"asset_quantity": row.qty if is_grouped_asset else 0,
|
"asset_quantity": row.qty if is_grouped_asset else 0,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user