mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-19 04:59:18 +00:00
Merge pull request #42759 from frappe/mergify/bp/version-15-hotfix/pr-42719
fix: linkage between asset repair and asset value adjustment (backport #42719)
This commit is contained in:
@@ -509,7 +509,10 @@ class AssetDepreciationSchedule(Document):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if not accumulated_depreciation:
|
if not accumulated_depreciation:
|
||||||
if i > 0 and asset_doc.flags.decrease_in_asset_value_due_to_value_adjustment:
|
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")[
|
accumulated_depreciation = self.get("depreciation_schedule")[
|
||||||
i - 1
|
i - 1
|
||||||
].accumulated_depreciation_amount
|
].accumulated_depreciation_amount
|
||||||
@@ -677,7 +680,7 @@ def get_straight_line_or_manual_depr_amount(
|
|||||||
# if the Depreciation Schedule is being modified after Asset Repair due to increase in asset value
|
# if the Depreciation Schedule is being modified after Asset Repair due to increase in asset value
|
||||||
elif asset.flags.increase_in_asset_value_due_to_repair:
|
elif asset.flags.increase_in_asset_value_due_to_repair:
|
||||||
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / flt(
|
return (flt(row.value_after_depreciation) - flt(row.expected_value_after_useful_life)) / flt(
|
||||||
row.total_number_of_depreciations
|
number_of_pending_depreciations
|
||||||
)
|
)
|
||||||
# if the Depreciation Schedule is being modified after Asset Value Adjustment due to decrease in asset value
|
# if the Depreciation Schedule is being modified after Asset Value Adjustment due to decrease in asset value
|
||||||
elif asset.flags.decrease_in_asset_value_due_to_value_adjustment:
|
elif asset.flags.decrease_in_asset_value_due_to_value_adjustment:
|
||||||
@@ -1041,6 +1044,7 @@ def make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
|||||||
date_of_return=None,
|
date_of_return=None,
|
||||||
value_after_depreciation=None,
|
value_after_depreciation=None,
|
||||||
ignore_booked_entry=False,
|
ignore_booked_entry=False,
|
||||||
|
difference_amount=None,
|
||||||
):
|
):
|
||||||
for row in asset_doc.get("finance_books"):
|
for row in asset_doc.get("finance_books"):
|
||||||
current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(
|
current_asset_depr_schedule_doc = get_asset_depr_schedule_doc(
|
||||||
@@ -1055,6 +1059,8 @@ 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:
|
||||||
|
value_after_depreciation = row.value_after_depreciation + difference_amount
|
||||||
|
|
||||||
if asset_doc.flags.increase_in_asset_value_due_to_repair and row.depreciation_method in (
|
if asset_doc.flags.increase_in_asset_value_due_to_repair and row.depreciation_method in (
|
||||||
"Written Down Value",
|
"Written Down Value",
|
||||||
|
|||||||
@@ -29,6 +29,15 @@ frappe.ui.form.on("Asset Repair", {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frm.set_query("purchase_invoice", function () {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: frm.doc.company,
|
||||||
|
docstatus: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
frm.set_query("warehouse", "stock_items", function () {
|
frm.set_query("warehouse", "stock_items", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
@@ -117,7 +117,9 @@ class AssetRepair(AccountsController):
|
|||||||
get_link_to_form(self.doctype, self.name),
|
get_link_to_form(self.doctype, self.name),
|
||||||
)
|
)
|
||||||
self.asset_doc.flags.ignore_validate_update_after_submit = True
|
self.asset_doc.flags.ignore_validate_update_after_submit = True
|
||||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes)
|
make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
||||||
|
self.asset_doc, notes, ignore_booked_entry=True
|
||||||
|
)
|
||||||
self.asset_doc.save()
|
self.asset_doc.save()
|
||||||
|
|
||||||
add_asset_activity(
|
add_asset_activity(
|
||||||
@@ -154,7 +156,9 @@ class AssetRepair(AccountsController):
|
|||||||
get_link_to_form(self.doctype, self.name),
|
get_link_to_form(self.doctype, self.name),
|
||||||
)
|
)
|
||||||
self.asset_doc.flags.ignore_validate_update_after_submit = True
|
self.asset_doc.flags.ignore_validate_update_after_submit = True
|
||||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes)
|
make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
||||||
|
self.asset_doc, notes, ignore_booked_entry=True
|
||||||
|
)
|
||||||
self.asset_doc.save()
|
self.asset_doc.save()
|
||||||
|
|
||||||
add_asset_activity(
|
add_asset_activity(
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class AssetValueAdjustment(Document):
|
|||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
frappe.get_doc("Journal Entry", self.journal_entry).cancel()
|
frappe.get_doc("Journal Entry", self.journal_entry).cancel()
|
||||||
self.update_asset(self.current_asset_value)
|
self.update_asset()
|
||||||
add_asset_activity(
|
add_asset_activity(
|
||||||
self.asset,
|
self.asset,
|
||||||
_("Asset's value adjusted after cancellation of Asset Value Adjustment {0}").format(
|
_("Asset's value adjusted after cancellation of Asset Value Adjustment {0}").format(
|
||||||
@@ -145,7 +145,7 @@ class AssetValueAdjustment(Document):
|
|||||||
|
|
||||||
self.db_set("journal_entry", je.name)
|
self.db_set("journal_entry", je.name)
|
||||||
|
|
||||||
def update_asset(self, asset_value):
|
def update_asset(self, asset_value=None):
|
||||||
asset = frappe.get_doc("Asset", self.asset)
|
asset = frappe.get_doc("Asset", self.asset)
|
||||||
|
|
||||||
if not asset.calculate_depreciation:
|
if not asset.calculate_depreciation:
|
||||||
@@ -171,7 +171,11 @@ class AssetValueAdjustment(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
make_new_active_asset_depr_schedules_and_cancel_current_ones(
|
||||||
asset, notes, value_after_depreciation=asset_value, ignore_booked_entry=True
|
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.flags.ignore_validate_update_after_submit = True
|
||||||
asset.save()
|
asset.save()
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from erpnext.assets.doctype.asset.test_asset import create_asset_data
|
|||||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||||
get_asset_depr_schedule_doc,
|
get_asset_depr_schedule_doc,
|
||||||
)
|
)
|
||||||
|
from erpnext.assets.doctype.asset_repair.test_asset_repair import create_asset_repair
|
||||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||||
|
|
||||||
|
|
||||||
@@ -128,6 +129,136 @@ class TestAssetValueAdjustment(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(schedules, expected_schedules)
|
self.assertEqual(schedules, expected_schedules)
|
||||||
|
|
||||||
|
def test_depreciation_after_cancelling_asset_repair(self):
|
||||||
|
pr = make_purchase_receipt(item_code="Macbook Pro", qty=1, rate=120000.0, location="Test Location")
|
||||||
|
|
||||||
|
asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name")
|
||||||
|
asset_doc = frappe.get_doc("Asset", asset_name)
|
||||||
|
asset_doc.calculate_depreciation = 1
|
||||||
|
asset_doc.available_for_use_date = "2023-01-15"
|
||||||
|
asset_doc.purchase_date = "2023-01-15"
|
||||||
|
|
||||||
|
asset_doc.append(
|
||||||
|
"finance_books",
|
||||||
|
{
|
||||||
|
"expected_value_after_useful_life": 200,
|
||||||
|
"depreciation_method": "Straight Line",
|
||||||
|
"total_number_of_depreciations": 12,
|
||||||
|
"frequency_of_depreciation": 1,
|
||||||
|
"depreciation_start_date": "2023-01-31",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
asset_doc.submit()
|
||||||
|
|
||||||
|
post_depreciation_entries(getdate("2023-08-21"))
|
||||||
|
|
||||||
|
# create asset repair
|
||||||
|
asset_repair = create_asset_repair(asset=asset_doc, capitalize_repair_cost=1, submit=1)
|
||||||
|
|
||||||
|
first_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active")
|
||||||
|
self.assertEqual(first_asset_depr_schedule.status, "Active")
|
||||||
|
|
||||||
|
# create asset value adjustment
|
||||||
|
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,
|
||||||
|
date="2023-08-21",
|
||||||
|
)
|
||||||
|
adj_doc.submit()
|
||||||
|
|
||||||
|
first_asset_depr_schedule.load_from_db()
|
||||||
|
|
||||||
|
second_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active")
|
||||||
|
self.assertEqual(second_asset_depr_schedule.status, "Active")
|
||||||
|
self.assertEqual(first_asset_depr_schedule.status, "Cancelled")
|
||||||
|
|
||||||
|
# Test gl entry creted from asset value adjustemnet
|
||||||
|
expected_gle = (
|
||||||
|
("_Test Accumulated Depreciations - _TC", 0.0, 5625.29),
|
||||||
|
("_Test Depreciations - _TC", 5625.29, 0.0),
|
||||||
|
)
|
||||||
|
|
||||||
|
gle = frappe.db.sql(
|
||||||
|
"""select account, debit, credit from `tabGL Entry`
|
||||||
|
where voucher_type='Journal Entry' and voucher_no = %s
|
||||||
|
order by account""",
|
||||||
|
adj_doc.journal_entry,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertSequenceEqual(gle, expected_gle)
|
||||||
|
|
||||||
|
# test depreciation schedule after asset repair and asset value adjustemnet
|
||||||
|
expected_schedules = [
|
||||||
|
["2023-01-31", 5474.73, 5474.73],
|
||||||
|
["2023-02-28", 9983.33, 15458.06],
|
||||||
|
["2023-03-31", 9983.33, 25441.39],
|
||||||
|
["2023-04-30", 9983.33, 35424.72],
|
||||||
|
["2023-05-31", 9983.33, 45408.05],
|
||||||
|
["2023-06-30", 9983.33, 55391.38],
|
||||||
|
["2023-07-31", 9983.33, 65374.71],
|
||||||
|
["2023-08-31", 2766.67, 68141.38],
|
||||||
|
["2023-09-30", 2766.67, 70908.05],
|
||||||
|
["2023-10-31", 2766.67, 73674.72],
|
||||||
|
["2023-11-30", 2766.67, 76441.39],
|
||||||
|
["2023-12-31", 2766.67, 79208.06],
|
||||||
|
["2024-01-31", 2766.67, 81974.73],
|
||||||
|
["2024-02-29", 2766.67, 84741.4],
|
||||||
|
["2024-03-31", 2766.67, 87508.07],
|
||||||
|
["2024-04-30", 2766.67, 90274.74],
|
||||||
|
["2024-05-31", 2766.67, 93041.41],
|
||||||
|
["2024-06-30", 2766.67, 95808.08],
|
||||||
|
["2024-07-31", 2766.67, 98574.75],
|
||||||
|
["2024-08-31", 2766.67, 101341.42],
|
||||||
|
["2024-09-30", 2766.67, 104108.09],
|
||||||
|
["2024-10-31", 2766.67, 106874.76],
|
||||||
|
["2024-11-30", 2766.67, 109641.43],
|
||||||
|
["2024-12-31", 2766.67, 112408.1],
|
||||||
|
["2025-01-15", 2766.61, 115174.71],
|
||||||
|
]
|
||||||
|
|
||||||
|
schedules = [
|
||||||
|
[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
||||||
|
for d in second_asset_depr_schedule.get("depreciation_schedule")
|
||||||
|
]
|
||||||
|
|
||||||
|
self.assertEqual(schedules, expected_schedules)
|
||||||
|
|
||||||
|
# Cancel asset repair
|
||||||
|
asset_repair.cancel()
|
||||||
|
asset_repair.load_from_db()
|
||||||
|
second_asset_depr_schedule.load_from_db()
|
||||||
|
|
||||||
|
third_asset_depr_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active")
|
||||||
|
self.assertEqual(third_asset_depr_schedule.status, "Active")
|
||||||
|
self.assertEqual(second_asset_depr_schedule.status, "Cancelled")
|
||||||
|
|
||||||
|
# After cancelling asset repair asset life will be decreased and new depreciation schedule should be calculated
|
||||||
|
expected_schedules = [
|
||||||
|
["2023-01-31", 5474.73, 5474.73],
|
||||||
|
["2023-02-28", 9983.33, 15458.06],
|
||||||
|
["2023-03-31", 9983.33, 25441.39],
|
||||||
|
["2023-04-30", 9983.33, 35424.72],
|
||||||
|
["2023-05-31", 9983.33, 45408.05],
|
||||||
|
["2023-06-30", 9983.33, 55391.38],
|
||||||
|
["2023-07-31", 9983.33, 65374.71],
|
||||||
|
["2023-08-31", 8133.33, 73508.04],
|
||||||
|
["2023-09-30", 8133.33, 81641.37],
|
||||||
|
["2023-10-31", 8133.33, 89774.7],
|
||||||
|
["2023-11-30", 8133.33, 97908.03],
|
||||||
|
["2023-12-31", 8133.33, 106041.36],
|
||||||
|
["2024-01-15", 8133.35, 114174.71],
|
||||||
|
]
|
||||||
|
|
||||||
|
schedules = [
|
||||||
|
[cstr(d.schedule_date), d.depreciation_amount, d.accumulated_depreciation_amount]
|
||||||
|
for d in third_asset_depr_schedule.get("depreciation_schedule")
|
||||||
|
]
|
||||||
|
|
||||||
|
self.assertEqual(schedules, expected_schedules)
|
||||||
|
|
||||||
|
|
||||||
def make_asset_value_adjustment(**args):
|
def make_asset_value_adjustment(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
Reference in New Issue
Block a user