Merge branch 'develop' into manual_depr_entries_develop
diff --git a/erpnext/accounts/doctype/journal_entry/journal_entry.py b/erpnext/accounts/doctype/journal_entry/journal_entry.py
index ea8b7d8..5b0322a 100644
--- a/erpnext/accounts/doctype/journal_entry/journal_entry.py
+++ b/erpnext/accounts/doctype/journal_entry/journal_entry.py
@@ -81,6 +81,7 @@
self.check_credit_limit()
self.make_gl_entries()
self.update_advance_paid()
+ self.update_asset_value()
self.update_inter_company_jv()
self.update_invoice_discounting()
@@ -225,6 +226,34 @@
for d in to_remove:
self.remove(d)
+ def update_asset_value(self):
+ if self.voucher_type != "Depreciation Entry":
+ return
+
+ processed_assets = []
+
+ for d in self.get("accounts"):
+ if (
+ d.reference_type == "Asset" and d.reference_name and d.reference_name not in processed_assets
+ ):
+ processed_assets.append(d.reference_name)
+
+ asset = frappe.db.get_value(
+ "Asset", d.reference_name, ["calculate_depreciation", "value_after_depreciation"], as_dict=1
+ )
+
+ if asset.calculate_depreciation:
+ continue
+
+ depr_value = d.debit or d.credit
+
+ frappe.db.set_value(
+ "Asset",
+ d.reference_name,
+ "value_after_depreciation",
+ asset.value_after_depreciation - depr_value,
+ )
+
def update_inter_company_jv(self):
if (
self.voucher_type == "Inter Company Journal Entry"
@@ -283,20 +312,48 @@
d.db_update()
def unlink_asset_reference(self):
+ if self.voucher_type != "Depreciation Entry":
+ return
+
+ processed_assets = []
+
for d in self.get("accounts"):
- if d.reference_type == "Asset" and d.reference_name:
+ if (
+ d.reference_type == "Asset" and d.reference_name and d.reference_name not in processed_assets
+ ):
+ processed_assets.append(d.reference_name)
+
asset = frappe.get_doc("Asset", d.reference_name)
- for row in asset.get("finance_books"):
- depr_schedule = get_depr_schedule(asset.name, "Active", row.finance_book)
- for s in depr_schedule or []:
- if s.journal_entry == self.name:
- s.db_set("journal_entry", None)
+ if asset.calculate_depreciation:
+ je_found = False
- row.value_after_depreciation += s.depreciation_amount
- row.db_update()
+ for row in asset.get("finance_books"):
+ if je_found:
+ break
- asset.set_status()
+ depr_schedule = get_depr_schedule(asset.name, "Active", row.finance_book)
+
+ for s in depr_schedule or []:
+ if s.journal_entry == self.name:
+ s.db_set("journal_entry", None)
+
+ row.value_after_depreciation += s.depreciation_amount
+ row.db_update()
+
+ asset.set_status()
+
+ je_found = True
+ break
+ else:
+ depr_value = d.debit or d.credit
+
+ frappe.db.set_value(
+ "Asset",
+ d.reference_name,
+ "value_after_depreciation",
+ asset.value_after_depreciation + depr_value,
+ )
def unlink_inter_company_jv(self):
if (
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index 8f5b85d..4ed99f7 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -221,34 +221,45 @@
asset_values.push(flt(frm.doc.gross_purchase_amount) -
flt(frm.doc.opening_accumulated_depreciation));
}
+ if(frm.doc.calculate_depreciation) {
+ if (frm.doc.finance_books.length == 1) {
+ let depr_schedule = (await frappe.call(
+ "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_depr_schedule",
+ {
+ asset_name: frm.doc.name,
+ status: frm.doc.docstatus ? "Active" : "Draft",
+ finance_book: frm.doc.finance_books[0].finance_book || null
+ }
+ )).message;
- let depr_schedule = [];
-
- if (frm.doc.finance_books.length == 1) {
- depr_schedule = (await frappe.call(
- "erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule.get_depr_schedule",
- {
- asset_name: frm.doc.name,
- status: frm.doc.docstatus ? "Active" : "Draft",
- finance_book: frm.doc.finance_books[0].finance_book || null
- }
- )).message;
- }
-
- $.each(depr_schedule || [], function(i, v) {
- x_intervals.push(v.schedule_date);
- var asset_value = flt(frm.doc.gross_purchase_amount) - flt(v.accumulated_depreciation_amount);
- if(v.journal_entry) {
- last_depreciation_date = v.schedule_date;
- asset_values.push(asset_value);
- } else {
- if (in_list(["Scrapped", "Sold"], frm.doc.status)) {
- asset_values.push(null);
- } else {
- asset_values.push(asset_value)
- }
+ $.each(depr_schedule || [], function(i, v) {
+ x_intervals.push(v.schedule_date);
+ var asset_value = flt(frm.doc.gross_purchase_amount) - flt(v.accumulated_depreciation_amount);
+ if(v.journal_entry) {
+ last_depreciation_date = v.schedule_date;
+ asset_values.push(asset_value);
+ } else {
+ if (in_list(["Scrapped", "Sold"], frm.doc.status)) {
+ asset_values.push(null);
+ } else {
+ asset_values.push(asset_value)
+ }
+ }
+ });
}
- });
+ } else {
+ let depr_entries = (await frappe.call({
+ method: "get_manual_depreciation_entries",
+ doc: frm.doc,
+ })).message;
+
+ $.each(depr_entries || [], function(i, v) {
+ x_intervals.push(v.posting_date);
+ last_depreciation_date = v.posting_date;
+ let last_asset_value = asset_values[asset_values.length - 1]
+ asset_values.push(last_asset_value - v.value);
+ });
+ }
if(in_list(["Scrapped", "Sold"], frm.doc.status)) {
x_intervals.push(frm.doc.disposal_date);
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index 8a64a95..ea575fd 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -509,9 +509,15 @@
"group": "Depreciation",
"link_doctype": "Asset Depreciation Schedule",
"link_fieldname": "asset"
+ },
+ {
+ "group": "Journal Entry",
+ "link_doctype": "Journal Entry",
+ "link_fieldname": "reference_name",
+ "table_fieldname": "accounts"
}
],
- "modified": "2023-01-17 00:25:30.387242",
+ "modified": "2023-02-02 00:03:11.706427",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index df05d5e..4f1caca 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -36,7 +36,6 @@
get_depr_schedule,
make_draft_asset_depr_schedules,
make_draft_asset_depr_schedules_if_not_present,
- set_draft_asset_depr_schedule_details,
update_draft_asset_depr_schedules,
)
from erpnext.controllers.accounts_controller import AccountsController
@@ -240,17 +239,6 @@
self.get_depreciation_rate(d, on_validate=True), d.precision("rate_of_depreciation")
)
- def _get_value_after_depreciation(self, finance_book):
- # value_after_depreciation - current Asset value
- if self.docstatus == 1 and finance_book.value_after_depreciation:
- value_after_depreciation = flt(finance_book.value_after_depreciation)
- else:
- value_after_depreciation = flt(self.gross_purchase_amount) - flt(
- self.opening_accumulated_depreciation
- )
-
- return value_after_depreciation
-
# if it returns True, depreciation_amount will not be equal for the first and last rows
def check_is_pro_rata(self, row):
has_pro_rata = False
@@ -392,18 +380,23 @@
movement.cancel()
def delete_depreciation_entries(self):
- for row in self.get("finance_books"):
- depr_schedule = get_depr_schedule(self.name, "Active", row.finance_book)
+ if self.calculate_depreciation:
+ for row in self.get("finance_books"):
+ depr_schedule = get_depr_schedule(self.name, "Active", row.finance_book)
- for d in depr_schedule or []:
- if d.journal_entry:
- frappe.get_doc("Journal Entry", d.journal_entry).cancel()
- d.db_set("journal_entry", None)
+ for d in depr_schedule or []:
+ if d.journal_entry:
+ frappe.get_doc("Journal Entry", d.journal_entry).cancel()
+ else:
+ depr_entries = self.get_manual_depreciation_entries()
- self.db_set(
- "value_after_depreciation",
- (flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)),
- )
+ for depr_entry in depr_entries or []:
+ frappe.get_doc("Journal Entry", depr_entry.name).cancel()
+
+ self.db_set(
+ "value_after_depreciation",
+ (flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)),
+ )
def set_status(self, status=None):
"""Get and update status"""
@@ -434,6 +427,28 @@
status = "Cancelled"
return status
+ def get_value_after_depreciation(self, finance_book=None):
+ if not self.calculate_depreciation:
+ return self.value_after_depreciation
+
+ if not finance_book:
+ return self.get("finance_books")[0].value_after_depreciation
+
+ for row in self.get("finance_books"):
+ if finance_book == row.finance_book:
+ return row.value_after_depreciation
+
+ def _get_value_after_depreciation_for_making_schedule(self, fb_row):
+ # value_after_depreciation - current Asset value
+ if self.docstatus == 1 and fb_row.value_after_depreciation:
+ value_after_depreciation = flt(fb_row.value_after_depreciation)
+ else:
+ value_after_depreciation = flt(self.gross_purchase_amount) - flt(
+ self.opening_accumulated_depreciation
+ )
+
+ return value_after_depreciation
+
def get_default_finance_book_idx(self):
if not self.get("default_finance_book") and self.company:
self.default_finance_book = erpnext.get_default_finance_book(self.company)
@@ -443,6 +458,43 @@
if d.finance_book == self.default_finance_book:
return cint(d.idx) - 1
+ @frappe.whitelist()
+ def get_manual_depreciation_entries(self):
+ (_, _, depreciation_expense_account) = get_depreciation_accounts(self)
+
+ gle = frappe.qb.DocType("GL Entry")
+
+ records = (
+ frappe.qb.from_(gle)
+ .select(gle.voucher_no.as_("name"), gle.debit.as_("value"), gle.posting_date)
+ .where(gle.against_voucher == self.name)
+ .where(gle.account == depreciation_expense_account)
+ .where(gle.debit != 0)
+ .where(gle.is_cancelled == 0)
+ .orderby(gle.posting_date)
+ ).run(as_dict=True)
+
+ return records
+
+ @erpnext.allow_regional
+ def get_depreciation_amount(self, depreciable_value, fb_row):
+ if fb_row.depreciation_method in ("Straight Line", "Manual"):
+ # if the Depreciation Schedule is being prepared for the first time
+ if not self.flags.increase_in_asset_life:
+ depreciation_amount = (
+ flt(self.gross_purchase_amount) - flt(fb_row.expected_value_after_useful_life)
+ ) / flt(fb_row.total_number_of_depreciations)
+
+ # if the Depreciation Schedule is being modified after Asset Repair
+ else:
+ depreciation_amount = (
+ flt(fb_row.value_after_depreciation) - flt(fb_row.expected_value_after_useful_life)
+ ) / (date_diff(self.to_date, self.available_for_use_date) / 365)
+ else:
+ depreciation_amount = flt(depreciable_value * (flt(fb_row.rate_of_depreciation) / 100))
+
+ return depreciation_amount
+
def validate_make_gl_entry(self):
purchase_document = self.get_purchase_document()
if not purchase_document:
@@ -603,7 +655,6 @@
def make_post_gl_entry():
-
asset_categories = frappe.db.get_all("Asset Category", fields=["name", "enable_cwip_accounting"])
for asset_category in asset_categories:
@@ -756,7 +807,7 @@
depreciation_expense_account,
) = get_depreciation_accounts(asset)
- depreciation_cost_center, depreciation_series = frappe.db.get_value(
+ depreciation_cost_center, depreciation_series = frappe.get_cached_value(
"Company", asset.company, ["depreciation_cost_center", "series_for_depreciation_entry"]
)
depreciation_cost_center = asset.cost_center or depreciation_cost_center
@@ -821,6 +872,13 @@
return cint(frappe.db.get_value("Asset Category", asset_category, "enable_cwip_accounting"))
+@frappe.whitelist()
+def get_asset_value_after_depreciation(asset_name, finance_book=None):
+ asset = frappe.get_doc("Asset", asset_name)
+
+ return asset.get_value_after_depreciation(finance_book)
+
+
def get_total_days(date, frequency):
period_start_date = add_months(date, cint(frequency) * -1)
@@ -886,7 +944,7 @@
)
new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc)
- set_draft_asset_depr_schedule_details(new_asset_depr_schedule_doc, asset, row)
+ new_asset_depr_schedule_doc.set_draft_asset_depr_schedule_details(asset, row)
accumulated_depreciation = 0
@@ -938,7 +996,7 @@
)
new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc)
- set_draft_asset_depr_schedule_details(new_asset_depr_schedule_doc, new_asset, row)
+ new_asset_depr_schedule_doc.set_draft_asset_depr_schedule_details(new_asset, row)
accumulated_depreciation = 0
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 17d4078..e7a2532 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -533,18 +533,8 @@
disposal_account, depreciation_cost_center = get_disposal_account_and_cost_center(asset.company)
depreciation_cost_center = asset.cost_center or depreciation_cost_center
- idx = 1
- if finance_book:
- for d in asset.finance_books:
- if d.finance_book == finance_book:
- idx = d.idx
- break
+ value_after_depreciation = asset.get_value_after_depreciation(finance_book)
- value_after_depreciation = (
- asset.finance_books[idx - 1].value_after_depreciation
- if asset.calculate_depreciation
- else asset.value_after_depreciation
- )
accumulated_depr_amount = flt(asset.gross_purchase_amount) - flt(value_after_depreciation)
return (
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 51a2b52..9a15263 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -16,6 +16,7 @@
nowdate,
)
+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.assets.doctype.asset.asset import (
make_sales_invoice,
@@ -28,7 +29,6 @@
scrap_asset,
)
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
- clear_depr_schedule,
get_asset_depr_schedule_doc,
get_depr_schedule,
)
@@ -924,11 +924,6 @@
def test_get_depreciation_amount(self):
"""Tests if get_depreciation_amount() returns the right value."""
-
- from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
- get_depreciation_amount,
- )
-
asset = create_asset(item_code="Macbook Pro", available_for_use_date="2019-12-31")
asset.calculate_depreciation = 1
@@ -943,7 +938,7 @@
},
)
- depreciation_amount = get_depreciation_amount(asset, 100000, asset.finance_books[0])
+ depreciation_amount = asset.get_depreciation_amount(100000, asset.finance_books[0])
self.assertEqual(depreciation_amount, 30000)
def test_make_depr_schedule(self):
@@ -1259,7 +1254,7 @@
asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset.name, "Active")
- clear_depr_schedule(asset_depr_schedule_doc)
+ asset_depr_schedule_doc.clear_depr_schedule()
self.assertEqual(len(asset_depr_schedule_doc.get("depreciation_schedule")), 1)
@@ -1308,19 +1303,19 @@
asset_depr_schedule_doc_1 = get_asset_depr_schedule_doc(
asset.name, "Active", "Test Finance Book 1"
)
- clear_depr_schedule(asset_depr_schedule_doc_1)
+ asset_depr_schedule_doc_1.clear_depr_schedule()
self.assertEqual(len(asset_depr_schedule_doc_1.get("depreciation_schedule")), 3)
asset_depr_schedule_doc_2 = get_asset_depr_schedule_doc(
asset.name, "Active", "Test Finance Book 2"
)
- clear_depr_schedule(asset_depr_schedule_doc_2)
+ asset_depr_schedule_doc_2.clear_depr_schedule()
self.assertEqual(len(asset_depr_schedule_doc_2.get("depreciation_schedule")), 3)
asset_depr_schedule_doc_3 = get_asset_depr_schedule_doc(
asset.name, "Active", "Test Finance Book 3"
)
- clear_depr_schedule(asset_depr_schedule_doc_3)
+ asset_depr_schedule_doc_3.clear_depr_schedule()
self.assertEqual(len(asset_depr_schedule_doc_3.get("depreciation_schedule")), 0)
def test_depreciation_schedules_are_set_up_for_multiple_finance_books(self):
@@ -1503,6 +1498,36 @@
for i, schedule in enumerate(get_depr_schedule(asset.name, "Active")):
self.assertEqual(getdate(expected_dates[i]), getdate(schedule.schedule_date))
+ def test_manual_depreciation_for_existing_asset(self):
+ asset = create_asset(
+ item_code="Macbook Pro",
+ is_existing_asset=1,
+ purchase_date="2020-01-30",
+ available_for_use_date="2020-01-30",
+ submit=1,
+ )
+
+ self.assertEqual(asset.status, "Submitted")
+ self.assertEqual(asset.get("value_after_depreciation"), 100000)
+
+ jv = make_journal_entry(
+ "_Test Depreciations - _TC", "_Test Accumulated Depreciations - _TC", 100, save=False
+ )
+ for d in jv.accounts:
+ d.reference_type = "Asset"
+ d.reference_name = asset.name
+ jv.voucher_type = "Depreciation Entry"
+ jv.insert()
+ jv.submit()
+
+ asset.reload()
+ self.assertEqual(asset.get("value_after_depreciation"), 99900)
+
+ jv.cancel()
+
+ asset.reload()
+ self.assertEqual(asset.get("value_after_depreciation"), 100000)
+
def create_asset_data():
if not frappe.db.exists("Asset Category", "Computers"):
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index 821accf..5b910db 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -10,6 +10,7 @@
from frappe.utils import cint, flt, get_link_to_form
import erpnext
+from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
from erpnext.assets.doctype.asset.depreciation import (
depreciate_asset,
get_gl_entries_on_asset_disposal,
@@ -21,9 +22,6 @@
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
make_new_active_asset_depr_schedules_and_cancel_current_ones,
)
-from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import (
- get_current_asset_value,
-)
from erpnext.controllers.stock_controller import StockController
from erpnext.setup.doctype.brand.brand import get_brand_defaults
from erpnext.setup.doctype.item_group.item_group import get_item_group_defaults
@@ -261,7 +259,9 @@
for d in self.get("asset_items"):
if d.asset:
finance_book = d.get("finance_book") or self.get("finance_book")
- d.current_asset_value = flt(get_current_asset_value(d.asset, finance_book=finance_book))
+ d.current_asset_value = flt(
+ get_asset_value_after_depreciation(d.asset, finance_book=finance_book)
+ )
d.asset_value = get_value_after_depreciation_on_disposal_date(
d.asset, self.posting_date, finance_book=finance_book
)
@@ -713,7 +713,7 @@
if args.asset:
out.current_asset_value = flt(
- get_current_asset_value(args.asset, finance_book=args.finance_book)
+ get_asset_value_after_depreciation(args.asset, finance_book=args.finance_book)
)
out.asset_value = get_value_after_depreciation_on_disposal_date(
args.asset, args.posting_date, finance_book=args.finance_book
diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
index 1446a6e..7615fbc 100644
--- a/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
+++ b/erpnext/assets/doctype/asset_depreciation_schedule/asset_depreciation_schedule.py
@@ -4,17 +4,7 @@
import frappe
from frappe import _
from frappe.model.document import Document
-from frappe.utils import (
- add_days,
- add_months,
- cint,
- date_diff,
- flt,
- get_last_day,
- is_last_day_of_the_month,
-)
-
-import erpnext
+from frappe.utils import add_days, add_months, cint, flt, get_last_day, is_last_day_of_the_month
class AssetDepreciationSchedule(Document):
@@ -83,7 +73,256 @@
)
asset_finance_book_doc = frappe.get_doc("Asset Finance Book", asset_finance_book_name)
- prepare_draft_asset_depr_schedule_data(self, asset_doc, asset_finance_book_doc)
+ self.prepare_draft_asset_depr_schedule_data(asset_doc, asset_finance_book_doc)
+
+ def prepare_draft_asset_depr_schedule_data(
+ self,
+ asset_doc,
+ row,
+ date_of_disposal=None,
+ date_of_return=None,
+ update_asset_finance_book_row=True,
+ ):
+ self.set_draft_asset_depr_schedule_details(asset_doc, 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)
+
+ def set_draft_asset_depr_schedule_details(self, asset_doc, row):
+ self.asset = asset_doc.name
+ self.finance_book = row.finance_book
+ self.finance_book_id = row.idx
+ self.opening_accumulated_depreciation = asset_doc.opening_accumulated_depreciation
+ self.depreciation_method = row.depreciation_method
+ self.total_number_of_depreciations = row.total_number_of_depreciations
+ self.frequency_of_depreciation = row.frequency_of_depreciation
+ self.rate_of_depreciation = row.rate_of_depreciation
+ self.expected_value_after_useful_life = row.expected_value_after_useful_life
+ self.status = "Draft"
+
+ def make_depr_schedule(
+ self, asset_doc, row, date_of_disposal, update_asset_finance_book_row=True
+ ):
+ if row.depreciation_method != "Manual" and 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(asset_doc, row, start, date_of_disposal, update_asset_finance_book_row)
+
+ def clear_depr_schedule(self):
+ start = 0
+ num_of_depreciations_completed = 0
+ depr_schedule = []
+
+ for schedule in self.get("depreciation_schedule"):
+ if schedule.journal_entry:
+ num_of_depreciations_completed += 1
+ depr_schedule.append(schedule)
+ else:
+ start = num_of_depreciations_completed
+ break
+
+ self.depreciation_schedule = depr_schedule
+
+ return start
+
+ def _make_depr_schedule(
+ self, asset_doc, row, start, date_of_disposal, update_asset_finance_book_row
+ ):
+ asset_doc.validate_asset_finance_books(row)
+
+ value_after_depreciation = asset_doc._get_value_after_depreciation_for_making_schedule(row)
+ row.value_after_depreciation = value_after_depreciation
+
+ if update_asset_finance_book_row:
+ row.db_update()
+
+ number_of_pending_depreciations = cint(row.total_number_of_depreciations) - cint(
+ asset_doc.number_of_depreciations_booked
+ )
+
+ has_pro_rata = asset_doc.check_is_pro_rata(row)
+ if has_pro_rata:
+ number_of_pending_depreciations += 1
+
+ skip_row = False
+ should_get_last_day = is_last_day_of_the_month(row.depreciation_start_date)
+
+ for n in range(start, number_of_pending_depreciations):
+ # If depreciation is already completed (for double declining balance)
+ if skip_row:
+ continue
+
+ depreciation_amount = asset_doc.get_depreciation_amount(value_after_depreciation, row)
+
+ if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
+ 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 will be a year later from start date
+ # so monthly schedule date is calculated by removing 11 months from it
+ monthly_schedule_date = add_months(schedule_date, -row.frequency_of_depreciation + 1)
+
+ # if asset is being sold or scrapped
+ if date_of_disposal:
+ from_date = asset_doc.available_for_use_date
+ if self.depreciation_schedule:
+ from_date = self.depreciation_schedule[-1].schedule_date
+
+ depreciation_amount, days, months = asset_doc.get_pro_rata_amt(
+ row, depreciation_amount, from_date, date_of_disposal
+ )
+
+ if depreciation_amount > 0:
+ self.add_depr_schedule_row(
+ date_of_disposal,
+ depreciation_amount,
+ row.depreciation_method,
+ )
+
+ break
+
+ # For first row
+ if has_pro_rata and not asset_doc.opening_accumulated_depreciation and n == 0:
+ from_date = add_days(
+ asset_doc.available_for_use_date, -1
+ ) # needed to calc depr amount for available_for_use_date too
+ depreciation_amount, days, months = asset_doc.get_pro_rata_amt(
+ row, depreciation_amount, from_date, row.depreciation_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
+ monthly_schedule_date = add_months(row.depreciation_start_date, -months + 1)
+
+ # For last row
+ elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
+ 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
+ asset_doc.to_date = add_months(
+ asset_doc.available_for_use_date,
+ (n + asset_doc.number_of_depreciations_booked) * cint(row.frequency_of_depreciation),
+ )
+
+ depreciation_amount_without_pro_rata = depreciation_amount
+
+ depreciation_amount, days, months = asset_doc.get_pro_rata_amt(
+ row, depreciation_amount, schedule_date, asset_doc.to_date
+ )
+
+ depreciation_amount = self.get_adjusted_depreciation_amount(
+ depreciation_amount_without_pro_rata, depreciation_amount
+ )
+
+ monthly_schedule_date = add_months(schedule_date, 1)
+ schedule_date = add_days(schedule_date, days)
+ last_schedule_date = schedule_date
+
+ if not depreciation_amount:
+ continue
+ value_after_depreciation -= flt(
+ depreciation_amount, asset_doc.precision("gross_purchase_amount")
+ )
+
+ # Adjust depreciation amount in the last period based on the expected value after useful life
+ if row.expected_value_after_useful_life and (
+ (
+ n == cint(number_of_pending_depreciations) - 1
+ and value_after_depreciation != row.expected_value_after_useful_life
+ )
+ or value_after_depreciation < row.expected_value_after_useful_life
+ ):
+ depreciation_amount += value_after_depreciation - row.expected_value_after_useful_life
+ skip_row = True
+
+ if depreciation_amount > 0:
+ self.add_depr_schedule_row(
+ schedule_date,
+ depreciation_amount,
+ row.depreciation_method,
+ )
+
+ # to ensure that final accumulated depreciation amount is accurate
+ def get_adjusted_depreciation_amount(
+ self, depreciation_amount_without_pro_rata, depreciation_amount_for_last_row
+ ):
+ if not self.opening_accumulated_depreciation:
+ depreciation_amount_for_first_row = self.get_depreciation_amount_for_first_row()
+
+ if (
+ depreciation_amount_for_first_row + depreciation_amount_for_last_row
+ != depreciation_amount_without_pro_rata
+ ):
+ depreciation_amount_for_last_row = (
+ depreciation_amount_without_pro_rata - depreciation_amount_for_first_row
+ )
+
+ return depreciation_amount_for_last_row
+
+ def get_depreciation_amount_for_first_row(self):
+ return self.get("depreciation_schedule")[0].depreciation_amount
+
+ def add_depr_schedule_row(
+ self,
+ schedule_date,
+ depreciation_amount,
+ depreciation_method,
+ ):
+ self.append(
+ "depreciation_schedule",
+ {
+ "schedule_date": schedule_date,
+ "depreciation_amount": depreciation_amount,
+ "depreciation_method": depreciation_method,
+ },
+ )
+
+ def set_accumulated_depreciation(
+ self,
+ 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 d.depreciation_method == "Straight Line"
+ ]
+
+ 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:
+ continue
+
+ depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
+ value_after_depreciation -= flt(depreciation_amount)
+
+ # for the last row, if depreciation method = Straight Line
+ if (
+ straight_line_idx
+ and i == max(straight_line_idx) - 1
+ and not date_of_disposal
+ and not date_of_return
+ ):
+ depreciation_amount += flt(
+ value_after_depreciation - flt(row.expected_value_after_useful_life),
+ d.precision("depreciation_amount"),
+ )
+
+ d.depreciation_amount = depreciation_amount
+ accumulated_depreciation += d.depreciation_amount
+ d.accumulated_depreciation_amount = flt(
+ accumulated_depreciation, d.precision("accumulated_depreciation_amount")
+ )
def make_draft_asset_depr_schedules_if_not_present(asset_doc):
@@ -108,7 +347,7 @@
def make_draft_asset_depr_schedule(asset_doc, row):
asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule")
- prepare_draft_asset_depr_schedule_data(asset_depr_schedule_doc, asset_doc, row)
+ asset_depr_schedule_doc.prepare_draft_asset_depr_schedule_data(asset_doc, row)
asset_depr_schedule_doc.insert()
@@ -120,41 +359,11 @@
if not asset_depr_schedule_doc:
continue
- prepare_draft_asset_depr_schedule_data(asset_depr_schedule_doc, asset_doc, row)
+ asset_depr_schedule_doc.prepare_draft_asset_depr_schedule_data(asset_doc, row)
asset_depr_schedule_doc.save()
-def prepare_draft_asset_depr_schedule_data(
- asset_depr_schedule_doc,
- asset_doc,
- row,
- date_of_disposal=None,
- date_of_return=None,
- update_asset_finance_book_row=True,
-):
- set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, row)
- make_depr_schedule(
- asset_depr_schedule_doc, asset_doc, row, date_of_disposal, update_asset_finance_book_row
- )
- set_accumulated_depreciation(asset_depr_schedule_doc, row, date_of_disposal, date_of_return)
-
-
-def set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset_doc, row):
- asset_depr_schedule_doc.asset = asset_doc.name
- asset_depr_schedule_doc.finance_book = row.finance_book
- asset_depr_schedule_doc.finance_book_id = row.idx
- asset_depr_schedule_doc.opening_accumulated_depreciation = (
- asset_doc.opening_accumulated_depreciation
- )
- asset_depr_schedule_doc.depreciation_method = row.depreciation_method
- asset_depr_schedule_doc.total_number_of_depreciations = row.total_number_of_depreciations
- asset_depr_schedule_doc.frequency_of_depreciation = row.frequency_of_depreciation
- asset_depr_schedule_doc.rate_of_depreciation = row.rate_of_depreciation
- asset_depr_schedule_doc.expected_value_after_useful_life = row.expected_value_after_useful_life
- asset_depr_schedule_doc.status = "Draft"
-
-
def convert_draft_asset_depr_schedules_into_active(asset_doc):
for row in asset_doc.get("finance_books"):
asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_doc.name, "Draft", row.finance_book)
@@ -192,8 +401,8 @@
new_asset_depr_schedule_doc = frappe.copy_doc(current_asset_depr_schedule_doc)
- make_depr_schedule(new_asset_depr_schedule_doc, asset_doc, row, date_of_disposal)
- set_accumulated_depreciation(new_asset_depr_schedule_doc, row, date_of_disposal, date_of_return)
+ new_asset_depr_schedule_doc.make_depr_schedule(asset_doc, row, date_of_disposal)
+ new_asset_depr_schedule_doc.set_accumulated_depreciation(row, date_of_disposal, date_of_return)
new_asset_depr_schedule_doc.notes = notes
@@ -208,8 +417,7 @@
):
asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule")
- prepare_draft_asset_depr_schedule_data(
- asset_depr_schedule_doc,
+ asset_depr_schedule_doc.prepare_draft_asset_depr_schedule_data(
asset_doc,
row,
date_of_disposal,
@@ -220,21 +428,6 @@
return asset_depr_schedule_doc
-def get_asset_depr_schedule_name(asset_name, status, finance_book=None):
- finance_book_filter = ["finance_book", "is", "not set"]
- if finance_book:
- finance_book_filter = ["finance_book", "=", finance_book]
-
- return frappe.db.get_value(
- doctype="Asset Depreciation Schedule",
- filters=[
- ["asset", "=", asset_name],
- finance_book_filter,
- ["status", "=", status],
- ],
- )
-
-
@frappe.whitelist()
def get_depr_schedule(asset_name, status, finance_book=None):
asset_depr_schedule_doc = get_asset_depr_schedule_doc(asset_name, status, finance_book)
@@ -256,261 +449,16 @@
return asset_depr_schedule_doc
-def make_depr_schedule(
- asset_depr_schedule_doc, asset_doc, row, date_of_disposal, update_asset_finance_book_row=True
-):
- if row.depreciation_method != "Manual" and not asset_depr_schedule_doc.get(
- "depreciation_schedule"
- ):
- asset_depr_schedule_doc.depreciation_schedule = []
+def get_asset_depr_schedule_name(asset_name, status, finance_book=None):
+ finance_book_filter = ["finance_book", "is", "not set"]
+ if finance_book:
+ finance_book_filter = ["finance_book", "=", finance_book]
- if not asset_doc.available_for_use_date:
- return
-
- start = clear_depr_schedule(asset_depr_schedule_doc)
-
- _make_depr_schedule(
- asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal, update_asset_finance_book_row
+ return frappe.db.get_value(
+ doctype="Asset Depreciation Schedule",
+ filters=[
+ ["asset", "=", asset_name],
+ finance_book_filter,
+ ["status", "=", status],
+ ],
)
-
-
-def clear_depr_schedule(asset_depr_schedule_doc):
- start = 0
- num_of_depreciations_completed = 0
- depr_schedule = []
-
- for schedule in asset_depr_schedule_doc.get("depreciation_schedule"):
- if schedule.journal_entry:
- num_of_depreciations_completed += 1
- depr_schedule.append(schedule)
- else:
- start = num_of_depreciations_completed
- break
-
- asset_depr_schedule_doc.depreciation_schedule = depr_schedule
-
- return start
-
-
-def _make_depr_schedule(
- asset_depr_schedule_doc, asset_doc, row, start, date_of_disposal, update_asset_finance_book_row
-):
- asset_doc.validate_asset_finance_books(row)
-
- value_after_depreciation = asset_doc._get_value_after_depreciation(row)
- row.value_after_depreciation = value_after_depreciation
-
- if update_asset_finance_book_row:
- row.db_update()
-
- number_of_pending_depreciations = cint(row.total_number_of_depreciations) - cint(
- asset_doc.number_of_depreciations_booked
- )
-
- has_pro_rata = asset_doc.check_is_pro_rata(row)
- if has_pro_rata:
- number_of_pending_depreciations += 1
-
- skip_row = False
- should_get_last_day = is_last_day_of_the_month(row.depreciation_start_date)
-
- for n in range(start, number_of_pending_depreciations):
- # If depreciation is already completed (for double declining balance)
- if skip_row:
- continue
-
- depreciation_amount = get_depreciation_amount(asset_doc, value_after_depreciation, row)
-
- if not has_pro_rata or n < cint(number_of_pending_depreciations) - 1:
- 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 will be a year later from start date
- # so monthly schedule date is calculated by removing 11 months from it
- monthly_schedule_date = add_months(schedule_date, -row.frequency_of_depreciation + 1)
-
- # if asset is being sold or scrapped
- if date_of_disposal:
- from_date = asset_doc.available_for_use_date
- if asset_depr_schedule_doc.depreciation_schedule:
- from_date = asset_depr_schedule_doc.depreciation_schedule[-1].schedule_date
-
- depreciation_amount, days, months = asset_doc.get_pro_rata_amt(
- row, depreciation_amount, from_date, date_of_disposal
- )
-
- if depreciation_amount > 0:
- add_depr_schedule_row(
- asset_depr_schedule_doc,
- date_of_disposal,
- depreciation_amount,
- row.depreciation_method,
- )
-
- break
-
- # For first row
- if has_pro_rata and not asset_doc.opening_accumulated_depreciation and n == 0:
- from_date = add_days(
- asset_doc.available_for_use_date, -1
- ) # needed to calc depr amount for available_for_use_date too
- depreciation_amount, days, months = asset_doc.get_pro_rata_amt(
- row, depreciation_amount, from_date, row.depreciation_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
- monthly_schedule_date = add_months(row.depreciation_start_date, -months + 1)
-
- # For last row
- elif has_pro_rata and n == cint(number_of_pending_depreciations) - 1:
- 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
- asset_doc.to_date = add_months(
- asset_doc.available_for_use_date,
- (n + asset_doc.number_of_depreciations_booked) * cint(row.frequency_of_depreciation),
- )
-
- depreciation_amount_without_pro_rata = depreciation_amount
-
- depreciation_amount, days, months = asset_doc.get_pro_rata_amt(
- row, depreciation_amount, schedule_date, asset_doc.to_date
- )
-
- depreciation_amount = get_adjusted_depreciation_amount(
- asset_depr_schedule_doc, depreciation_amount_without_pro_rata, depreciation_amount
- )
-
- monthly_schedule_date = add_months(schedule_date, 1)
- schedule_date = add_days(schedule_date, days)
- last_schedule_date = schedule_date
-
- if not depreciation_amount:
- continue
- value_after_depreciation -= flt(
- depreciation_amount, asset_doc.precision("gross_purchase_amount")
- )
-
- # Adjust depreciation amount in the last period based on the expected value after useful life
- if row.expected_value_after_useful_life and (
- (
- n == cint(number_of_pending_depreciations) - 1
- and value_after_depreciation != row.expected_value_after_useful_life
- )
- or value_after_depreciation < row.expected_value_after_useful_life
- ):
- depreciation_amount += value_after_depreciation - row.expected_value_after_useful_life
- skip_row = True
-
- if depreciation_amount > 0:
- add_depr_schedule_row(
- asset_depr_schedule_doc,
- schedule_date,
- depreciation_amount,
- row.depreciation_method,
- )
-
-
-# to ensure that final accumulated depreciation amount is accurate
-def get_adjusted_depreciation_amount(
- asset_depr_schedule_doc, depreciation_amount_without_pro_rata, depreciation_amount_for_last_row
-):
- if not asset_depr_schedule_doc.opening_accumulated_depreciation:
- depreciation_amount_for_first_row = get_depreciation_amount_for_first_row(
- asset_depr_schedule_doc
- )
-
- if (
- depreciation_amount_for_first_row + depreciation_amount_for_last_row
- != depreciation_amount_without_pro_rata
- ):
- depreciation_amount_for_last_row = (
- depreciation_amount_without_pro_rata - depreciation_amount_for_first_row
- )
-
- return depreciation_amount_for_last_row
-
-
-def get_depreciation_amount_for_first_row(asset_depr_schedule_doc):
- return asset_depr_schedule_doc.get("depreciation_schedule")[0].depreciation_amount
-
-
-@erpnext.allow_regional
-def get_depreciation_amount(asset_doc, depreciable_value, row):
- if row.depreciation_method in ("Straight Line", "Manual"):
- # if the Depreciation Schedule is being prepared for the first time
- if not asset_doc.flags.increase_in_asset_life:
- depreciation_amount = (
- flt(asset_doc.gross_purchase_amount) - flt(row.expected_value_after_useful_life)
- ) / flt(row.total_number_of_depreciations)
-
- # if the Depreciation Schedule is being modified after Asset Repair
- else:
- depreciation_amount = (
- flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)
- ) / (date_diff(asset_doc.to_date, asset_doc.available_for_use_date) / 365)
- else:
- depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100))
-
- return depreciation_amount
-
-
-def add_depr_schedule_row(
- asset_depr_schedule_doc,
- schedule_date,
- depreciation_amount,
- depreciation_method,
-):
- asset_depr_schedule_doc.append(
- "depreciation_schedule",
- {
- "schedule_date": schedule_date,
- "depreciation_amount": depreciation_amount,
- "depreciation_method": depreciation_method,
- },
- )
-
-
-def set_accumulated_depreciation(
- asset_depr_schedule_doc,
- row,
- date_of_disposal=None,
- date_of_return=None,
- ignore_booked_entry=False,
-):
- straight_line_idx = [
- d.idx
- for d in asset_depr_schedule_doc.get("depreciation_schedule")
- if d.depreciation_method == "Straight Line"
- ]
-
- accumulated_depreciation = flt(asset_depr_schedule_doc.opening_accumulated_depreciation)
- value_after_depreciation = flt(row.value_after_depreciation)
-
- for i, d in enumerate(asset_depr_schedule_doc.get("depreciation_schedule")):
- if ignore_booked_entry and d.journal_entry:
- continue
-
- depreciation_amount = flt(d.depreciation_amount, d.precision("depreciation_amount"))
- value_after_depreciation -= flt(depreciation_amount)
-
- # for the last row, if depreciation method = Straight Line
- if (
- straight_line_idx
- and i == max(straight_line_idx) - 1
- and not date_of_disposal
- and not date_of_return
- ):
- depreciation_amount += flt(
- value_after_depreciation - flt(row.expected_value_after_useful_life),
- d.precision("depreciation_amount"),
- )
-
- d.depreciation_amount = depreciation_amount
- accumulated_depreciation += d.depreciation_amount
- d.accumulated_depreciation_amount = flt(
- accumulated_depreciation, d.precision("accumulated_depreciation_amount")
- )
diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py
index ff72aa9..a9d0b25 100644
--- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py
+++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py
@@ -6,7 +6,10 @@
import frappe
from frappe.utils import flt, nowdate
-from erpnext.assets.doctype.asset.asset import get_asset_account
+from erpnext.assets.doctype.asset.asset import (
+ get_asset_account,
+ get_asset_value_after_depreciation,
+)
from erpnext.assets.doctype.asset.test_asset import (
create_asset,
create_asset_data,
@@ -109,20 +112,20 @@
def test_increase_in_asset_value_due_to_stock_consumption(self):
asset = create_asset(calculate_depreciation=1, submit=1)
- initial_asset_value = get_asset_value(asset)
+ initial_asset_value = get_asset_value_after_depreciation(asset.name)
asset_repair = create_asset_repair(asset=asset, stock_consumption=1, submit=1)
asset.reload()
- increase_in_asset_value = get_asset_value(asset) - initial_asset_value
+ increase_in_asset_value = get_asset_value_after_depreciation(asset.name) - initial_asset_value
self.assertEqual(asset_repair.stock_items[0].total_value, increase_in_asset_value)
def test_increase_in_asset_value_due_to_repair_cost_capitalisation(self):
asset = create_asset(calculate_depreciation=1, submit=1)
- initial_asset_value = get_asset_value(asset)
+ initial_asset_value = get_asset_value_after_depreciation(asset.name)
asset_repair = create_asset_repair(asset=asset, capitalize_repair_cost=1, submit=1)
asset.reload()
- increase_in_asset_value = get_asset_value(asset) - initial_asset_value
+ increase_in_asset_value = get_asset_value_after_depreciation(asset.name) - initial_asset_value
self.assertEqual(asset_repair.repair_cost, increase_in_asset_value)
def test_purchase_invoice(self):
@@ -256,10 +259,6 @@
)
-def get_asset_value(asset):
- return asset.finance_books[0].value_after_depreciation
-
-
def num_of_depreciations(asset):
return asset.finance_books[0].total_number_of_depreciations
diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js
index 36f510b..ae0e1bd 100644
--- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js
+++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.js
@@ -47,7 +47,7 @@
set_current_asset_value: function(frm) {
if (frm.doc.asset) {
frm.call({
- method: "erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment.get_current_asset_value",
+ method: "erpnext.assets.doctype.asset.asset.get_asset_value_after_depreciation",
args: {
asset: frm.doc.asset,
finance_book: frm.doc.finance_book
diff --git a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
index 6cfbe53..31d6ffa 100644
--- a/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
+++ b/erpnext/assets/doctype/asset_value_adjustment/asset_value_adjustment.py
@@ -10,11 +10,10 @@
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_checks_for_pl_and_bs_accounts,
)
+from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
get_asset_depr_schedule_doc,
- get_depreciation_amount,
- set_accumulated_depreciation,
)
@@ -46,7 +45,7 @@
def set_current_asset_value(self):
if not self.current_asset_value and self.asset:
- self.current_asset_value = get_current_asset_value(self.asset, self.finance_book)
+ 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)
@@ -163,7 +162,7 @@
depreciation_amount = days * rate_per_day
from_date = data.schedule_date
else:
- depreciation_amount = get_depreciation_amount(asset, value_after_depreciation, d)
+ depreciation_amount = asset.get_depreciation_amount(value_after_depreciation, d)
if depreciation_amount:
value_after_depreciation -= flt(depreciation_amount)
@@ -171,18 +170,9 @@
d.db_update()
- set_accumulated_depreciation(new_asset_depr_schedule_doc, d, ignore_booked_entry=True)
+ 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()
-
-
-@frappe.whitelist()
-def get_current_asset_value(asset, finance_book=None):
- cond = {"parent": asset, "parenttype": "Asset"}
- if finance_book:
- cond.update({"finance_book": finance_book})
-
- return frappe.db.get_value("Asset Finance Book", cond, "value_after_depreciation")
diff --git a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py
index 03dcea9..0b3dcba 100644
--- a/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py
+++ b/erpnext/assets/doctype/asset_value_adjustment/test_asset_value_adjustment.py
@@ -6,13 +6,11 @@
import frappe
from frappe.utils import add_days, get_last_day, nowdate
+from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
from erpnext.assets.doctype.asset.test_asset import create_asset_data
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
get_asset_depr_schedule_doc,
)
-from erpnext.assets.doctype.asset_value_adjustment.asset_value_adjustment import (
- get_current_asset_value,
-)
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
@@ -46,7 +44,7 @@
)
asset_doc.submit()
- current_value = get_current_asset_value(asset_doc.name)
+ current_value = get_asset_value_after_depreciation(asset_doc.name)
self.assertEqual(current_value, 100000.0)
def test_asset_depreciation_value_adjustment(self):
@@ -79,7 +77,7 @@
first_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active")
self.assertEquals(first_asset_depr_schedule.status, "Active")
- current_value = get_current_asset_value(asset_doc.name)
+ current_value = get_asset_value_after_depreciation(asset_doc.name)
adj_doc = make_asset_value_adjustment(
asset=asset_doc.name, current_asset_value=current_value, new_asset_value=50000.0
)
diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
index d41069c..cead72e 100644
--- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
+++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
@@ -4,13 +4,16 @@
import frappe
from frappe import _
-from frappe.utils import cstr, flt, formatdate, getdate
+from frappe.query_builder.functions import Sum
+from frappe.utils import cstr, formatdate, getdate
from erpnext.accounts.report.financial_statements import (
get_fiscal_year_data,
get_period_list,
validate_fiscal_year,
)
+from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
+from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
def execute(filters=None):
@@ -85,6 +88,7 @@
"asset_name",
"status",
"department",
+ "company",
"cost_center",
"calculate_depreciation",
"purchase_receipt",
@@ -98,8 +102,25 @@
]
assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields)
+ finance_book_filter = ("is", "not set")
+ if filters.finance_book:
+ finance_book_filter = ("=", filters.finance_book)
+
+ assets_linked_to_fb = frappe.db.get_all(
+ doctype="Asset Finance Book",
+ filters={"finance_book": finance_book_filter},
+ pluck="parent",
+ )
+
for asset in assets_record:
- asset_value = get_asset_value(asset, filters.finance_book)
+ if filters.finance_book:
+ if asset.asset_id not in assets_linked_to_fb:
+ continue
+ else:
+ if asset.calculate_depreciation and asset.asset_id not in assets_linked_to_fb:
+ continue
+
+ asset_value = get_asset_value_after_depreciation(asset.asset_id, filters.finance_book)
row = {
"asset_id": asset.asset_id,
"asset_name": asset.asset_name,
@@ -110,7 +131,7 @@
or pi_supplier_map.get(asset.purchase_invoice),
"gross_purchase_amount": asset.gross_purchase_amount,
"opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
- "depreciated_amount": depreciation_amount_map.get(asset.asset_id) or 0.0,
+ "depreciated_amount": get_depreciation_amount_of_asset(asset, depreciation_amount_map, filters),
"available_for_use_date": asset.available_for_use_date,
"location": asset.location,
"asset_category": asset.asset_category,
@@ -122,23 +143,6 @@
return data
-def get_asset_value(asset, finance_book=None):
- if not asset.calculate_depreciation:
- return flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation)
-
- result = frappe.get_all(
- doctype="Asset Finance Book",
- filters={
- "parent": asset.asset_id,
- "finance_book": finance_book or ("is", "not set"),
- },
- pluck="value_after_depreciation",
- limit=1,
- )
-
- return result[0] if result else 0.0
-
-
def prepare_chart_data(data, filters):
labels_values_map = {}
date_field = frappe.scrub(filters.date_based_on)
@@ -184,6 +188,15 @@
}
+def get_depreciation_amount_of_asset(asset, depreciation_amount_map, filters):
+ if asset.calculate_depreciation:
+ depr_amount = depreciation_amount_map.get(asset.asset_id) or 0.0
+ else:
+ depr_amount = get_manual_depreciation_amount_of_asset(asset, filters)
+
+ return depr_amount
+
+
def get_finance_book_value_map(filters):
date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date
@@ -205,6 +218,31 @@
)
+def get_manual_depreciation_amount_of_asset(asset, filters):
+ date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date
+
+ (_, _, depreciation_expense_account) = get_depreciation_accounts(asset)
+
+ gle = frappe.qb.DocType("GL Entry")
+
+ result = (
+ frappe.qb.from_(gle)
+ .select(Sum(gle.debit))
+ .where(gle.against_voucher == asset.asset_id)
+ .where(gle.account == depreciation_expense_account)
+ .where(gle.debit != 0)
+ .where(gle.is_cancelled == 0)
+ .where(gle.posting_date <= date)
+ ).run()
+
+ if result and result[0] and result[0][0]:
+ depr_amount = result[0][0]
+ else:
+ depr_amount = 0
+
+ return depr_amount
+
+
def get_purchase_receipt_supplier_map():
return frappe._dict(
frappe.db.sql(
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index 698ffac..211f074 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -326,3 +326,4 @@
erpnext.patches.v14_0.update_entry_type_for_journal_entry
erpnext.patches.v14_0.change_autoname_for_tax_withheld_vouchers
erpnext.patches.v14_0.set_pick_list_status
+erpnext.patches.v15_0.update_asset_value_for_manual_depr_entries
diff --git a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py
index 5dc3cdd..371ecbc 100644
--- a/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py
+++ b/erpnext/patches/v15_0/create_asset_depreciation_schedules_from_assets.py
@@ -1,9 +1,5 @@
import frappe
-from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
- set_draft_asset_depr_schedule_details,
-)
-
def execute():
frappe.reload_doc("assets", "doctype", "Asset Depreciation Schedule")
@@ -16,7 +12,7 @@
for fb_row in finance_book_rows:
asset_depr_schedule_doc = frappe.new_doc("Asset Depreciation Schedule")
- set_draft_asset_depr_schedule_details(asset_depr_schedule_doc, asset, fb_row)
+ asset_depr_schedule_doc.set_draft_asset_depr_schedule_details(asset, fb_row)
asset_depr_schedule_doc.insert()
diff --git a/erpnext/patches/v15_0/update_asset_value_for_manual_depr_entries.py b/erpnext/patches/v15_0/update_asset_value_for_manual_depr_entries.py
new file mode 100644
index 0000000..5d7b5cf
--- /dev/null
+++ b/erpnext/patches/v15_0/update_asset_value_for_manual_depr_entries.py
@@ -0,0 +1,38 @@
+import frappe
+from frappe.query_builder.functions import IfNull, Sum
+
+
+def execute():
+ asset = frappe.qb.DocType("Asset")
+ gle = frappe.qb.DocType("GL Entry")
+ aca = frappe.qb.DocType("Asset Category Account")
+ company = frappe.qb.DocType("Company")
+
+ asset_total_depr_value_map = (
+ frappe.qb.from_(gle)
+ .join(asset)
+ .on(gle.against_voucher == asset.name)
+ .join(aca)
+ .on((aca.parent == asset.asset_category) & (aca.company_name == asset.company))
+ .join(company)
+ .on(company.name == asset.company)
+ .select(Sum(gle.debit).as_("value"), asset.name.as_("asset_name"))
+ .where(
+ gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account)
+ )
+ .where(gle.debit != 0)
+ .where(gle.is_cancelled == 0)
+ .where(asset.docstatus == 1)
+ .where(asset.calculate_depreciation == 0)
+ .groupby(asset.name)
+ )
+
+ frappe.qb.update(asset).join(asset_total_depr_value_map).on(
+ asset_total_depr_value_map.asset_name == asset.name
+ ).set(
+ asset.value_after_depreciation, asset.value_after_depreciation - asset_total_depr_value_map.value
+ ).where(
+ asset.docstatus == 1
+ ).where(
+ asset.calculate_depreciation == 0
+ ).run()