mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-24 05:32:46 +01:00
refactor: asset value adjustment
This commit is contained in:
@@ -196,7 +196,6 @@ class JournalEntry(AccountsController):
|
||||
self.update_asset_value()
|
||||
self.update_inter_company_jv()
|
||||
self.update_invoice_discounting()
|
||||
self.update_booked_depreciation()
|
||||
|
||||
def on_update_after_submit(self):
|
||||
# Flag will be set on Reconciliation
|
||||
@@ -232,7 +231,6 @@ class JournalEntry(AccountsController):
|
||||
self.unlink_inter_company_jv()
|
||||
self.unlink_asset_adjustment_entry()
|
||||
self.update_invoice_discounting()
|
||||
self.update_booked_depreciation(1)
|
||||
|
||||
def get_title(self):
|
||||
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.set_status()
|
||||
asset.set_total_booked_depreciations()
|
||||
|
||||
def update_inter_company_jv(self):
|
||||
if self.voucher_type == "Inter Company Journal Entry" and self.inter_company_journal_entry_reference:
|
||||
@@ -459,25 +458,6 @@ class JournalEntry(AccountsController):
|
||||
if 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):
|
||||
for d in self.get("accounts"):
|
||||
if d.is_advance == "Yes" and d.reference_type in ("Sales Invoice", "Purchase Invoice"):
|
||||
@@ -530,6 +510,7 @@ class JournalEntry(AccountsController):
|
||||
else:
|
||||
asset.db_set("value_after_depreciation", asset.value_after_depreciation + d.debit)
|
||||
asset.set_status()
|
||||
asset.set_total_booked_depreciations()
|
||||
elif self.voucher_type == "Journal Entry" and d.reference_type == "Asset" and d.reference_name:
|
||||
journal_entry_for_scrap = frappe.db.get_value(
|
||||
"Asset", d.reference_name, "journal_entry_for_scrap"
|
||||
|
||||
@@ -130,8 +130,6 @@ class Asset(AccountsController):
|
||||
self.set_missing_values()
|
||||
self.validate_gross_and_purchase_amount()
|
||||
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.status = self.get_status()
|
||||
|
||||
@@ -178,6 +176,8 @@ class Asset(AccountsController):
|
||||
|
||||
def on_update(self):
|
||||
self.create_asset_depreciation_schedule()
|
||||
self.validate_expected_value_after_useful_life()
|
||||
self.set_total_booked_depreciations()
|
||||
|
||||
def on_submit(self):
|
||||
self.validate_in_use_date()
|
||||
|
||||
@@ -351,11 +351,11 @@ 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
|
||||
last_depr_date = None
|
||||
if start > 0:
|
||||
last_depr_date = self.depreciation_schedule[start - 1].schedule_date
|
||||
elif asset_doc.opening_number_of_booked_depreciations > 0:
|
||||
@@ -363,7 +363,7 @@ class AssetDepreciationSchedule(Document):
|
||||
|
||||
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):
|
||||
@@ -516,7 +516,7 @@ class AssetDepreciationSchedule(Document):
|
||||
return depreciation_amount, skip_row
|
||||
|
||||
def validate_depreciation_amount_for_low_value_assets(self, asset_doc, row, depreciation_amount):
|
||||
""" "
|
||||
"""
|
||||
If gross purchase amount is too low, then depreciation amount
|
||||
can come zero sometimes based on the frequency and number of depreciations.
|
||||
"""
|
||||
@@ -553,42 +553,23 @@ class AssetDepreciationSchedule(Document):
|
||||
row,
|
||||
date_of_disposal=None,
|
||||
date_of_return=None,
|
||||
ignore_booked_entry=False,
|
||||
):
|
||||
straight_line_idx = [
|
||||
d.idx
|
||||
for d in self.get("depreciation_schedule")
|
||||
if self.depreciation_method == "Straight Line" or self.depreciation_method == "Manual"
|
||||
]
|
||||
|
||||
accumulated_depreciation = None
|
||||
accumulated_depreciation = flt(self.opening_accumulated_depreciation)
|
||||
value_after_depreciation = flt(row.value_after_depreciation)
|
||||
|
||||
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
|
||||
|
||||
if not accumulated_depreciation:
|
||||
if i > 0 and (
|
||||
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"))
|
||||
value_after_depreciation = flt(
|
||||
value_after_depreciation - flt(d.depreciation_amount), d.precision("depreciation_amount")
|
||||
)
|
||||
|
||||
# for the last row, if depreciation method = Straight Line
|
||||
if (
|
||||
straight_line_idx
|
||||
and i == max(straight_line_idx) - 1
|
||||
self.depreciation_method in ("Straight Line", "Manual")
|
||||
and i == len(self.get("depreciation_schedule")) - 1
|
||||
and not date_of_disposal
|
||||
and not date_of_return
|
||||
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_return=None,
|
||||
value_after_depreciation=None,
|
||||
ignore_booked_entry=False,
|
||||
difference_amount=None,
|
||||
):
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
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
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
"column_break_ajbh",
|
||||
"column_break_hkem",
|
||||
"repair_cost",
|
||||
"asset_depreciation_details_section",
|
||||
"accounting_dimensions_section",
|
||||
"cost_center",
|
||||
"column_break_14",
|
||||
"project",
|
||||
@@ -185,12 +185,6 @@
|
||||
"label": "Total Repair Cost",
|
||||
"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",
|
||||
"fieldname": "increase_in_asset_life",
|
||||
@@ -253,12 +247,18 @@
|
||||
{
|
||||
"fieldname": "column_break_xebe",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "capitalize_repair_cost",
|
||||
"fieldname": "accounting_dimensions_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Accounting Dimensions"
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-12-20 13:10:31.540666",
|
||||
"modified": "2024-12-23 18:08:35.159964",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Repair",
|
||||
|
||||
@@ -148,15 +148,12 @@ class AssetRepair(AccountsController):
|
||||
self.decrease_stock_quantity()
|
||||
|
||||
if self.get("capitalize_repair_cost"):
|
||||
self.asset_doc.flags.ignore_validate_update_after_submit = True
|
||||
self.update_asset_value()
|
||||
self.make_gl_entries()
|
||||
self.set_increase_in_asset_life()
|
||||
|
||||
depreciation_note = self.get_depreciation_note()
|
||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
||||
self.asset_doc, depreciation_note, ignore_booked_entry=True
|
||||
)
|
||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, depreciation_note)
|
||||
self.add_asset_activity()
|
||||
|
||||
def on_cancel(self):
|
||||
@@ -164,16 +161,13 @@ class AssetRepair(AccountsController):
|
||||
|
||||
if self.get("capitalize_repair_cost"):
|
||||
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.make_gl_entries(cancel=True)
|
||||
self.set_increase_in_asset_life()
|
||||
|
||||
depreciation_note = self.get_depreciation_note()
|
||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
||||
self.asset_doc, depreciation_note, ignore_booked_entry=True
|
||||
)
|
||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, depreciation_note)
|
||||
self.add_asset_activity()
|
||||
|
||||
def after_delete(self):
|
||||
@@ -184,16 +178,16 @@ class AssetRepair(AccountsController):
|
||||
frappe.throw(_("Please update Repair Status."))
|
||||
|
||||
def update_asset_value(self):
|
||||
if self.docstaus == 2:
|
||||
self.total_repair_cost *= -1
|
||||
total_repair_cost = self.total_repair_cost if self.docstatus == 1 else -1 * self.total_repair_cost
|
||||
|
||||
self.asset_doc.total_asset_cost += flt(self.total_repair_cost)
|
||||
self.asset_doc.additional_asset_cost += flt(self.total_repair_cost)
|
||||
self.asset_doc.total_asset_cost += flt(total_repair_cost)
|
||||
self.asset_doc.additional_asset_cost += flt(total_repair_cost)
|
||||
|
||||
if self.asset_doc.calculate_depreciation:
|
||||
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()
|
||||
|
||||
def get_total_value_of_stock_consumed(self):
|
||||
@@ -377,9 +371,8 @@ class AssetRepair(AccountsController):
|
||||
def add_asset_activity(self, subject=None):
|
||||
if not subject:
|
||||
subject = _("Asset updated due to Asset Repair {0} {1}.").format(
|
||||
get_link_to_form(
|
||||
self.doctype, self.name, "submission" if self.docstatus == 1 else "cancellation"
|
||||
),
|
||||
get_link_to_form(self.doctype, self.name),
|
||||
"submission" if self.docstatus == 1 else "cancellation",
|
||||
)
|
||||
|
||||
add_asset_activity(self.asset, subject)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
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 (
|
||||
get_checks_for_pl_and_bs_accounts,
|
||||
@@ -46,10 +46,26 @@ class AssetValueAdjustment(Document):
|
||||
self.set_current_asset_value()
|
||||
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):
|
||||
self.make_depreciation_entry()
|
||||
self.set_value_after_depreciation()
|
||||
self.update_asset(self.new_asset_value)
|
||||
self.update_asset()
|
||||
add_asset_activity(
|
||||
self.asset,
|
||||
_("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):
|
||||
asset = frappe.get_doc("Asset", self.asset)
|
||||
(
|
||||
@@ -114,46 +110,15 @@ class AssetValueAdjustment(Document):
|
||||
}
|
||||
|
||||
if self.difference_amount < 0:
|
||||
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,
|
||||
}
|
||||
credit_entry, debit_entry = self.get_entry_for_asset_value_decrease(
|
||||
fixed_asset_account, entry_template
|
||||
)
|
||||
elif self.difference_amount > 0:
|
||||
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,
|
||||
}
|
||||
credit_entry, debit_entry = self.get_entry_for_asset_value_increase(
|
||||
fixed_asset_account, entry_template
|
||||
)
|
||||
|
||||
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
|
||||
|
||||
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")
|
||||
}
|
||||
)
|
||||
self.update_accounting_dimensions(credit_entry, debit_entry)
|
||||
|
||||
je.append("accounts", credit_entry)
|
||||
je.append("accounts", debit_entry)
|
||||
@@ -163,40 +128,82 @@ class AssetValueAdjustment(Document):
|
||||
|
||||
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)
|
||||
|
||||
if not asset.calculate_depreciation:
|
||||
asset.value_after_depreciation = asset_value
|
||||
asset.save()
|
||||
return
|
||||
asset.value_after_depreciation += flt(difference_amount)
|
||||
asset.db_update()
|
||||
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:
|
||||
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("Asset", self.asset),
|
||||
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("Asset", self.asset),
|
||||
get_link_to_form(self.get("doctype"), self.get("name")),
|
||||
)
|
||||
|
||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
||||
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()
|
||||
return notes
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
||||
Reference in New Issue
Block a user