refactor: asset value adjustment

This commit is contained in:
Nabin Hait
2024-12-23 18:24:10 +05:30
committed by Khushi Rawat
parent c567a08470
commit 44e45b55d4
6 changed files with 119 additions and 157 deletions

View File

@@ -196,7 +196,6 @@ class JournalEntry(AccountsController):
self.update_asset_value() self.update_asset_value()
self.update_inter_company_jv() self.update_inter_company_jv()
self.update_invoice_discounting() self.update_invoice_discounting()
self.update_booked_depreciation()
def on_update_after_submit(self): def on_update_after_submit(self):
# Flag will be set on Reconciliation # Flag will be set on Reconciliation
@@ -232,7 +231,6 @@ class JournalEntry(AccountsController):
self.unlink_inter_company_jv() self.unlink_inter_company_jv()
self.unlink_asset_adjustment_entry() self.unlink_asset_adjustment_entry()
self.update_invoice_discounting() self.update_invoice_discounting()
self.update_booked_depreciation(1)
def get_title(self): def get_title(self):
return self.pay_to_recd_from or self.accounts[0].account return self.pay_to_recd_from or self.accounts[0].account
@@ -405,6 +403,7 @@ class JournalEntry(AccountsController):
asset.db_set("value_after_depreciation", asset.value_after_depreciation - d.debit) asset.db_set("value_after_depreciation", asset.value_after_depreciation - d.debit)
asset.set_status() asset.set_status()
asset.set_total_booked_depreciations()
def update_inter_company_jv(self): def update_inter_company_jv(self):
if self.voucher_type == "Inter Company Journal Entry" and self.inter_company_journal_entry_reference: if self.voucher_type == "Inter Company Journal Entry" and self.inter_company_journal_entry_reference:
@@ -459,25 +458,6 @@ class JournalEntry(AccountsController):
if status: if status:
inv_disc_doc.set_status(status=status) inv_disc_doc.set_status(status=status)
def update_booked_depreciation(self, cancel=0):
for d in self.get("accounts"):
if (
self.voucher_type == "Depreciation Entry"
and d.reference_type == "Asset"
and d.reference_name
and frappe.get_cached_value("Account", d.account, "root_type") == "Expense"
and d.debit
):
asset = frappe.get_doc("Asset", d.reference_name)
for fb_row in asset.get("finance_books"):
if fb_row.finance_book == self.finance_book:
if cancel:
fb_row.total_number_of_booked_depreciations -= 1
else:
fb_row.total_number_of_booked_depreciations += 1
fb_row.db_update()
break
def unlink_advance_entry_reference(self): def unlink_advance_entry_reference(self):
for d in self.get("accounts"): for d in self.get("accounts"):
if d.is_advance == "Yes" and d.reference_type in ("Sales Invoice", "Purchase Invoice"): if d.is_advance == "Yes" and d.reference_type in ("Sales Invoice", "Purchase Invoice"):
@@ -530,6 +510,7 @@ class JournalEntry(AccountsController):
else: else:
asset.db_set("value_after_depreciation", asset.value_after_depreciation + d.debit) asset.db_set("value_after_depreciation", asset.value_after_depreciation + d.debit)
asset.set_status() asset.set_status()
asset.set_total_booked_depreciations()
elif self.voucher_type == "Journal Entry" and d.reference_type == "Asset" and d.reference_name: elif self.voucher_type == "Journal Entry" and d.reference_type == "Asset" and d.reference_name:
journal_entry_for_scrap = frappe.db.get_value( journal_entry_for_scrap = frappe.db.get_value(
"Asset", d.reference_name, "journal_entry_for_scrap" "Asset", d.reference_name, "journal_entry_for_scrap"

View File

@@ -130,8 +130,6 @@ class Asset(AccountsController):
self.set_missing_values() self.set_missing_values()
self.validate_gross_and_purchase_amount() self.validate_gross_and_purchase_amount()
self.validate_finance_books() self.validate_finance_books()
self.validate_expected_value_after_useful_life()
self.set_total_booked_depreciations()
self.total_asset_cost = self.gross_purchase_amount self.total_asset_cost = self.gross_purchase_amount
self.status = self.get_status() self.status = self.get_status()
@@ -178,6 +176,8 @@ class Asset(AccountsController):
def on_update(self): def on_update(self):
self.create_asset_depreciation_schedule() self.create_asset_depreciation_schedule()
self.validate_expected_value_after_useful_life()
self.set_total_booked_depreciations()
def on_submit(self): def on_submit(self):
self.validate_in_use_date() self.validate_in_use_date()

View File

@@ -351,11 +351,11 @@ class AssetDepreciationSchedule(Document):
return has_wdv_or_dd_non_yearly_pro_rata return has_wdv_or_dd_non_yearly_pro_rata
def get_number_of_pending_months(self, asset_doc, row, start): 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( total_months = cint(row.total_number_of_depreciations) * cint(row.frequency_of_depreciation) + cint(
row.increase_in_asset_life row.increase_in_asset_life
) )
depr_booked_for_months = 0 depr_booked_for_months = 0
last_depr_date = None
if start > 0: if start > 0:
last_depr_date = self.depreciation_schedule[start - 1].schedule_date last_depr_date = self.depreciation_schedule[start - 1].schedule_date
elif asset_doc.opening_number_of_booked_depreciations > 0: elif asset_doc.opening_number_of_booked_depreciations > 0:
@@ -363,7 +363,7 @@ class AssetDepreciationSchedule(Document):
if last_depr_date: if last_depr_date:
depr_booked_for_months = date_diff(last_depr_date, asset_doc.available_for_use_date) / (365 / 12) 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 return total_months - depr_booked_for_months
def has_fiscal_year_changed(self, row, row_no): def has_fiscal_year_changed(self, row, row_no):
@@ -516,7 +516,7 @@ class AssetDepreciationSchedule(Document):
return depreciation_amount, skip_row return depreciation_amount, skip_row
def validate_depreciation_amount_for_low_value_assets(self, asset_doc, row, depreciation_amount): def validate_depreciation_amount_for_low_value_assets(self, asset_doc, row, depreciation_amount):
""" " """
If gross purchase amount is too low, then depreciation amount If gross purchase amount is too low, then depreciation amount
can come zero sometimes based on the frequency and number of depreciations. can come zero sometimes based on the frequency and number of depreciations.
""" """
@@ -553,42 +553,23 @@ class AssetDepreciationSchedule(Document):
row, row,
date_of_disposal=None, date_of_disposal=None,
date_of_return=None, date_of_return=None,
ignore_booked_entry=False,
): ):
straight_line_idx = [ accumulated_depreciation = flt(self.opening_accumulated_depreciation)
d.idx
for d in self.get("depreciation_schedule")
if self.depreciation_method == "Straight Line" or self.depreciation_method == "Manual"
]
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 d.journal_entry:
accumulated_depreciation = d.accumulated_depreciation_amount
continue continue
if not accumulated_depreciation: value_after_depreciation = flt(
if i > 0 and ( value_after_depreciation - flt(d.depreciation_amount), d.precision("depreciation_amount")
asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment )
or asset_doc.flags.increase_in_asset_value_due_to_repair
):
accumulated_depreciation = self.get("depreciation_schedule")[
i - 1
].accumulated_depreciation_amount
else:
accumulated_depreciation = flt(
self.opening_accumulated_depreciation,
asset_doc.precision("opening_accumulated_depreciation"),
)
value_after_depreciation -= flt(d.depreciation_amount)
value_after_depreciation = flt(value_after_depreciation, d.precision("depreciation_amount"))
# for the last row, if depreciation method = Straight Line # for the last row, if depreciation method = Straight Line
if ( if (
straight_line_idx self.depreciation_method in ("Straight Line", "Manual")
and i == max(straight_line_idx) - 1 and i == len(self.get("depreciation_schedule")) - 1
and not date_of_disposal and not date_of_disposal
and not date_of_return and not date_of_return
and not row.shift_based and not row.shift_based
@@ -757,7 +738,6 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones(
date_of_disposal=None, date_of_disposal=None,
date_of_return=None, date_of_return=None,
value_after_depreciation=None, value_after_depreciation=None,
ignore_booked_entry=False,
difference_amount=None, difference_amount=None,
): ):
for row in asset_doc.get("finance_books"): for row in asset_doc.get("finance_books"):
@@ -773,6 +753,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones(
) )
new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc) new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc)
if asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment and not value_after_depreciation: if asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment and not value_after_depreciation:
value_after_depreciation = row.value_after_depreciation - difference_amount value_after_depreciation = row.value_after_depreciation - difference_amount
@@ -790,7 +771,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones(
asset_doc, row, date_of_disposal, value_after_depreciation=value_after_depreciation asset_doc, row, date_of_disposal, value_after_depreciation=value_after_depreciation
) )
new_asset_depr_schedule_doc.set_accumulated_depreciation( new_asset_depr_schedule_doc.set_accumulated_depreciation(
asset_doc, row, date_of_disposal, date_of_return, ignore_booked_entry asset_doc, row, date_of_disposal, date_of_return
) )
new_asset_depr_schedule_doc.notes = notes new_asset_depr_schedule_doc.notes = notes

View File

@@ -27,7 +27,7 @@
"column_break_ajbh", "column_break_ajbh",
"column_break_hkem", "column_break_hkem",
"repair_cost", "repair_cost",
"asset_depreciation_details_section", "accounting_dimensions_section",
"cost_center", "cost_center",
"column_break_14", "column_break_14",
"project", "project",
@@ -185,12 +185,6 @@
"label": "Total Repair Cost", "label": "Total Repair Cost",
"read_only": 1 "read_only": 1
}, },
{
"depends_on": "capitalize_repair_cost",
"fieldname": "asset_depreciation_details_section",
"fieldtype": "Section Break",
"label": "Asset Depreciation Details"
},
{ {
"depends_on": "capitalize_repair_cost", "depends_on": "capitalize_repair_cost",
"fieldname": "increase_in_asset_life", "fieldname": "increase_in_asset_life",
@@ -253,12 +247,18 @@
{ {
"fieldname": "column_break_xebe", "fieldname": "column_break_xebe",
"fieldtype": "Column Break" "fieldtype": "Column Break"
},
{
"depends_on": "capitalize_repair_cost",
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
"label": "Accounting Dimensions"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2024-12-20 13:10:31.540666", "modified": "2024-12-23 18:08:35.159964",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Assets", "module": "Assets",
"name": "Asset Repair", "name": "Asset Repair",

View File

@@ -148,15 +148,12 @@ class AssetRepair(AccountsController):
self.decrease_stock_quantity() self.decrease_stock_quantity()
if self.get("capitalize_repair_cost"): if self.get("capitalize_repair_cost"):
self.asset_doc.flags.ignore_validate_update_after_submit = True
self.update_asset_value() self.update_asset_value()
self.make_gl_entries() self.make_gl_entries()
self.set_increase_in_asset_life() self.set_increase_in_asset_life()
depreciation_note = self.get_depreciation_note() depreciation_note = self.get_depreciation_note()
make_new_active_asset_depr_schedules_and_cancel_current_ones( make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, depreciation_note)
self.asset_doc, depreciation_note, ignore_booked_entry=True
)
self.add_asset_activity() self.add_asset_activity()
def on_cancel(self): def on_cancel(self):
@@ -164,16 +161,13 @@ class AssetRepair(AccountsController):
if self.get("capitalize_repair_cost"): if self.get("capitalize_repair_cost"):
self.asset_doc.flags.increase_in_asset_value_due_to_repair = True self.asset_doc.flags.increase_in_asset_value_due_to_repair = True
self.asset_doc.flags.ignore_validate_update_after_submit = True
self.update_asset_value() self.update_asset_value()
self.make_gl_entries(cancel=True) self.make_gl_entries(cancel=True)
self.set_increase_in_asset_life() self.set_increase_in_asset_life()
depreciation_note = self.get_depreciation_note() depreciation_note = self.get_depreciation_note()
make_new_active_asset_depr_schedules_and_cancel_current_ones( make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, depreciation_note)
self.asset_doc, depreciation_note, ignore_booked_entry=True
)
self.add_asset_activity() self.add_asset_activity()
def after_delete(self): def after_delete(self):
@@ -184,16 +178,16 @@ class AssetRepair(AccountsController):
frappe.throw(_("Please update Repair Status.")) frappe.throw(_("Please update Repair Status."))
def update_asset_value(self): def update_asset_value(self):
if self.docstaus == 2: total_repair_cost = self.total_repair_cost if self.docstatus == 1 else -1 * self.total_repair_cost
self.total_repair_cost *= -1
self.asset_doc.total_asset_cost += flt(self.total_repair_cost) self.asset_doc.total_asset_cost += flt(total_repair_cost)
self.asset_doc.additional_asset_cost += flt(self.total_repair_cost) self.asset_doc.additional_asset_cost += flt(total_repair_cost)
if self.asset_doc.calculate_depreciation: if self.asset_doc.calculate_depreciation:
for row in self.asset_doc.finance_books: for row in self.asset_doc.finance_books:
row.value_after_depreciation += flt(self.total_repair_cost) row.value_after_depreciation += flt(total_repair_cost)
self.asset_doc.flags.ignore_validate_update_after_submit = True
self.asset_doc.save() self.asset_doc.save()
def get_total_value_of_stock_consumed(self): def get_total_value_of_stock_consumed(self):
@@ -377,9 +371,8 @@ class AssetRepair(AccountsController):
def add_asset_activity(self, subject=None): def add_asset_activity(self, subject=None):
if not subject: if not subject:
subject = _("Asset updated due to Asset Repair {0} {1}.").format( subject = _("Asset updated due to Asset Repair {0} {1}.").format(
get_link_to_form( get_link_to_form(self.doctype, self.name),
self.doctype, self.name, "submission" if self.docstatus == 1 else "cancellation" "submission" if self.docstatus == 1 else "cancellation",
),
) )
add_asset_activity(self.asset, subject) add_asset_activity(self.asset, subject)

View File

@@ -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 flt, formatdate, get_link_to_form, getdate from frappe.utils import cstr, 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,
@@ -46,10 +46,26 @@ class AssetValueAdjustment(Document):
self.set_current_asset_value() self.set_current_asset_value()
self.set_difference_amount() self.set_difference_amount()
def validate_date(self):
asset_purchase_date = frappe.db.get_value("Asset", self.asset, "purchase_date")
if getdate(self.date) < getdate(asset_purchase_date):
frappe.throw(
_("Asset Value Adjustment cannot be posted before Asset's purchase date <b>{0}</b>.").format(
formatdate(asset_purchase_date)
),
title=_("Incorrect Date"),
)
def set_difference_amount(self):
self.difference_amount = flt(self.new_asset_value - self.current_asset_value)
def set_current_asset_value(self):
if not self.current_asset_value and self.asset:
self.current_asset_value = get_asset_value_after_depreciation(self.asset, self.finance_book)
def on_submit(self): def on_submit(self):
self.make_depreciation_entry() self.make_depreciation_entry()
self.set_value_after_depreciation() self.update_asset()
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(
@@ -67,26 +83,6 @@ class AssetValueAdjustment(Document):
), ),
) )
def validate_date(self):
asset_purchase_date = frappe.db.get_value("Asset", self.asset, "purchase_date")
if getdate(self.date) < getdate(asset_purchase_date):
frappe.throw(
_("Asset Value Adjustment cannot be posted before Asset's purchase date <b>{0}</b>.").format(
formatdate(asset_purchase_date)
),
title=_("Incorrect Date"),
)
def set_difference_amount(self):
self.difference_amount = flt(self.new_asset_value - self.current_asset_value)
def set_value_after_depreciation(self):
frappe.db.set_value("Asset", self.asset, "value_after_depreciation", self.new_asset_value)
def set_current_asset_value(self):
if not self.current_asset_value and self.asset:
self.current_asset_value = get_asset_value_after_depreciation(self.asset, self.finance_book)
def make_depreciation_entry(self): def make_depreciation_entry(self):
asset = frappe.get_doc("Asset", self.asset) asset = frappe.get_doc("Asset", self.asset)
( (
@@ -114,46 +110,15 @@ class AssetValueAdjustment(Document):
} }
if self.difference_amount < 0: if self.difference_amount < 0:
credit_entry = { credit_entry, debit_entry = self.get_entry_for_asset_value_decrease(
"account": fixed_asset_account, fixed_asset_account, entry_template
"credit_in_account_currency": -self.difference_amount, )
**entry_template,
}
debit_entry = {
"account": self.difference_account,
"debit_in_account_currency": -self.difference_amount,
**entry_template,
}
elif self.difference_amount > 0: elif self.difference_amount > 0:
credit_entry = { credit_entry, debit_entry = self.get_entry_for_asset_value_increase(
"account": self.difference_account, fixed_asset_account, entry_template
"credit_in_account_currency": self.difference_amount, )
**entry_template,
}
debit_entry = {
"account": fixed_asset_account,
"debit_in_account_currency": self.difference_amount,
**entry_template,
}
accounting_dimensions = get_checks_for_pl_and_bs_accounts() self.update_accounting_dimensions(credit_entry, debit_entry)
for dimension in accounting_dimensions:
if dimension.get("mandatory_for_bs"):
credit_entry.update(
{
dimension["fieldname"]: self.get(dimension["fieldname"])
or dimension.get("default_dimension")
}
)
if dimension.get("mandatory_for_pl"):
debit_entry.update(
{
dimension["fieldname"]: self.get(dimension["fieldname"])
or dimension.get("default_dimension")
}
)
je.append("accounts", credit_entry) je.append("accounts", credit_entry)
je.append("accounts", debit_entry) je.append("accounts", debit_entry)
@@ -163,40 +128,82 @@ class AssetValueAdjustment(Document):
self.db_set("journal_entry", je.name) self.db_set("journal_entry", je.name)
def update_asset(self, asset_value=None): def get_entry_for_asset_value_decrease(self, fixed_asset_account, entry_template):
credit_entry = {
"account": fixed_asset_account,
"credit_in_account_currency": -self.difference_amount,
**entry_template,
}
debit_entry = {
"account": self.difference_account,
"debit_in_account_currency": -self.difference_amount,
**entry_template,
}
return credit_entry, debit_entry
def get_entry_for_asset_value_increase(self, fixed_asset_account, entry_template):
credit_entry = {
"account": self.difference_account,
"credit_in_account_currency": self.difference_amount,
**entry_template,
}
debit_entry = {
"account": fixed_asset_account,
"debit_in_account_currency": self.difference_amount,
**entry_template,
}
return credit_entry, debit_entry
def update_accounting_dimensions(self, credit_entry, debit_entry):
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
for dimension in accounting_dimensions:
dimension_value = self.get(dimension["fieldname"]) or dimension.get("default_dimension")
if dimension.get("mandatory_for_bs"):
credit_entry.update({dimension["fieldname"]: dimension_value})
if dimension.get("mandatory_for_pl"):
debit_entry.update({dimension["fieldname"]: dimension_value})
def update_asset(self):
asset = self.update_asset_value_after_depreciation()
note = self.get_adjustment_note()
make_new_active_asset_depr_schedules_and_cancel_current_ones(asset, note)
def update_asset_value_after_depreciation(self):
difference_amount = self.difference_amount if self.docstatus == 1 else -1 * self.difference_amount
asset = frappe.get_doc("Asset", self.asset) asset = frappe.get_doc("Asset", self.asset)
if not asset.calculate_depreciation: if not asset.calculate_depreciation:
asset.value_after_depreciation = asset_value asset.value_after_depreciation += flt(difference_amount)
asset.save() asset.db_update()
return else:
for row in asset.finance_books:
if cstr(row.finance_book) == cstr(self.finance_book):
row.value_after_depreciation += flt(difference_amount)
row.db_update()
asset.flags.decrease_in_asset_value_due_to_value_adjustment = True return asset
def get_adjustment_note(self):
if self.docstatus == 1: if self.docstatus == 1:
notes = _( notes = _(
"This schedule was created when Asset {0} was adjusted through Asset Value Adjustment {1}." "This schedule was created when Asset {0} was adjusted through Asset Value Adjustment {1}."
).format( ).format(
get_link_to_form("Asset", asset.name), get_link_to_form("Asset", self.asset),
get_link_to_form(self.get("doctype"), self.get("name")), get_link_to_form(self.get("doctype"), self.get("name")),
) )
elif self.docstatus == 2: elif self.docstatus == 2:
notes = _( notes = _(
"This schedule was created when Asset {0}'s Asset Value Adjustment {1} was cancelled." "This schedule was created when Asset {0}'s Asset Value Adjustment {1} was cancelled."
).format( ).format(
get_link_to_form("Asset", asset.name), get_link_to_form("Asset", self.asset),
get_link_to_form(self.get("doctype"), self.get("name")), get_link_to_form(self.get("doctype"), self.get("name")),
) )
make_new_active_asset_depr_schedules_and_cancel_current_ones( return notes
asset,
notes,
value_after_depreciation=asset_value,
ignore_booked_entry=True,
difference_amount=self.difference_amount,
)
asset.flags.ignore_validate_update_after_submit = True
asset.save()
@frappe.whitelist() @frappe.whitelist()