mirror of
https://github.com/frappe/erpnext.git
synced 2026-03-18 22:42:12 +00:00
fix(capitalization): debit cwip account instead of fixed asset account (#42857)
* fix(capitalization): debit cwip account instead of fixed asset account
* fix: post entries for capitalized asset through background jobs
* chore: run pre-commit
* fix: correct GL entries posting for composite assets
* fix(minor): resolve failing check
* chore: update gl entry check logic
* chore: handle none values
(cherry picked from commit 5d99f17583)
This commit is contained in:
@@ -691,12 +691,17 @@ class Asset(AccountsController):
|
|||||||
return cwip_account
|
return cwip_account
|
||||||
|
|
||||||
def make_gl_entries(self):
|
def make_gl_entries(self):
|
||||||
|
if self.check_asset_capitalization_gl_entries():
|
||||||
|
return
|
||||||
|
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
|
|
||||||
purchase_document = self.get_purchase_document()
|
purchase_document = self.get_purchase_document()
|
||||||
fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
|
fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
|
||||||
|
|
||||||
if purchase_document and self.purchase_amount and getdate(self.available_for_use_date) <= getdate():
|
if (self.is_composite_asset or (purchase_document and self.purchase_amount)) and getdate(
|
||||||
|
self.available_for_use_date
|
||||||
|
) <= getdate():
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
@@ -733,6 +738,24 @@ class Asset(AccountsController):
|
|||||||
make_gl_entries(gl_entries)
|
make_gl_entries(gl_entries)
|
||||||
self.db_set("booked_fixed_asset", 1)
|
self.db_set("booked_fixed_asset", 1)
|
||||||
|
|
||||||
|
def check_asset_capitalization_gl_entries(self):
|
||||||
|
if self.is_composite_asset:
|
||||||
|
result = frappe.db.get_value(
|
||||||
|
"Asset Capitalization",
|
||||||
|
{"target_asset": self.name, "docstatus": 1},
|
||||||
|
["name", "target_fixed_asset_account"],
|
||||||
|
)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
asset_capitalization, target_fixed_asset_account = result
|
||||||
|
# Check GL entries for the retrieved Asset Capitalization and target fixed asset account
|
||||||
|
return has_gl_entries(
|
||||||
|
"Asset Capitalization", asset_capitalization, target_fixed_asset_account
|
||||||
|
)
|
||||||
|
# return if there are no submitted capitalization for given asset
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_depreciation_rate(self, args, on_validate=False):
|
def get_depreciation_rate(self, args, on_validate=False):
|
||||||
if isinstance(args, str):
|
if isinstance(args, str):
|
||||||
@@ -779,6 +802,22 @@ class Asset(AccountsController):
|
|||||||
return flt((100 * (1 - depreciation_rate)), float_precision)
|
return flt((100 * (1 - depreciation_rate)), float_precision)
|
||||||
|
|
||||||
|
|
||||||
|
def has_gl_entries(doctype, docname, target_account):
|
||||||
|
gl_entry = frappe.qb.DocType("GL Entry")
|
||||||
|
gl_entries = (
|
||||||
|
frappe.qb.from_(gl_entry)
|
||||||
|
.select(gl_entry.account)
|
||||||
|
.where(
|
||||||
|
(gl_entry.voucher_type == doctype)
|
||||||
|
& (gl_entry.voucher_no == docname)
|
||||||
|
& (gl_entry.debit != 0)
|
||||||
|
& (gl_entry.account == target_account)
|
||||||
|
)
|
||||||
|
.run(as_dict=True)
|
||||||
|
)
|
||||||
|
return len(gl_entries) > 0
|
||||||
|
|
||||||
|
|
||||||
def update_maintenance_status():
|
def update_maintenance_status():
|
||||||
assets = frappe.get_all(
|
assets = frappe.get_all(
|
||||||
"Asset", filters={"docstatus": 1, "maintenance_required": 1, "disposal_date": ("is", "not set")}
|
"Asset", filters={"docstatus": 1, "maintenance_required": 1, "disposal_date": ("is", "not set")}
|
||||||
|
|||||||
@@ -469,13 +469,24 @@ class AssetCapitalization(StockController):
|
|||||||
self.get_gl_entries_for_consumed_asset_items(gl_entries, target_account, target_against, precision)
|
self.get_gl_entries_for_consumed_asset_items(gl_entries, target_account, target_against, precision)
|
||||||
self.get_gl_entries_for_consumed_service_items(gl_entries, target_account, target_against, precision)
|
self.get_gl_entries_for_consumed_service_items(gl_entries, target_account, target_against, precision)
|
||||||
|
|
||||||
self.get_gl_entries_for_target_item(gl_entries, target_against, precision)
|
self.get_gl_entries_for_target_item(gl_entries, target_account, target_against, precision)
|
||||||
|
|
||||||
return gl_entries
|
return gl_entries
|
||||||
|
|
||||||
def get_target_account(self):
|
def get_target_account(self):
|
||||||
if self.target_is_fixed_asset:
|
if self.target_is_fixed_asset:
|
||||||
return self.target_fixed_asset_account
|
from erpnext.assets.doctype.asset.asset import is_cwip_accounting_enabled
|
||||||
|
|
||||||
|
asset_category = frappe.get_cached_value("Asset", self.target_asset, "asset_category")
|
||||||
|
if is_cwip_accounting_enabled(asset_category):
|
||||||
|
target_account = get_asset_category_account(
|
||||||
|
"capital_work_in_progress_account",
|
||||||
|
asset_category=asset_category,
|
||||||
|
company=self.company,
|
||||||
|
)
|
||||||
|
return target_account if target_account else self.target_fixed_asset_account
|
||||||
|
else:
|
||||||
|
return self.target_fixed_asset_account
|
||||||
else:
|
else:
|
||||||
return self.warehouse_account[self.target_warehouse]["account"]
|
return self.warehouse_account[self.target_warehouse]["account"]
|
||||||
|
|
||||||
@@ -563,13 +574,13 @@ class AssetCapitalization(StockController):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_gl_entries_for_target_item(self, gl_entries, target_against, precision):
|
def get_gl_entries_for_target_item(self, gl_entries, target_account, target_against, precision):
|
||||||
if self.target_is_fixed_asset:
|
if self.target_is_fixed_asset:
|
||||||
# Capitalization
|
# Capitalization
|
||||||
gl_entries.append(
|
gl_entries.append(
|
||||||
self.get_gl_dict(
|
self.get_gl_dict(
|
||||||
{
|
{
|
||||||
"account": self.target_fixed_asset_account,
|
"account": target_account,
|
||||||
"against": ", ".join(target_against),
|
"against": ", ".join(target_against),
|
||||||
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
"remarks": self.get("remarks") or _("Accounting Entry for Asset"),
|
||||||
"debit": flt(self.total_value, precision),
|
"debit": flt(self.total_value, precision),
|
||||||
|
|||||||
@@ -187,9 +187,10 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
# Test General Ledger Entries
|
# Test General Ledger Entries
|
||||||
default_expense_account = frappe.db.get_value("Company", company, "default_expense_account")
|
default_expense_account = frappe.db.get_value("Company", company, "default_expense_account")
|
||||||
expected_gle = {
|
expected_gle = {
|
||||||
"_Test Fixed Asset - _TC": 3000,
|
"_Test Fixed Asset - _TC": -100000.0,
|
||||||
"Expenses Included In Asset Valuation - _TC": -1000,
|
default_expense_account: -2000.0,
|
||||||
default_expense_account: -2000,
|
"CWIP Account - _TC": 103000.0,
|
||||||
|
"Expenses Included In Asset Valuation - _TC": -1000.0,
|
||||||
}
|
}
|
||||||
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
actual_gle = get_actual_gle_dict(asset_capitalization.name)
|
||||||
|
|
||||||
@@ -424,7 +425,7 @@ class TestAssetCapitalization(unittest.TestCase):
|
|||||||
self.assertEqual(target_asset.purchase_amount, total_amount)
|
self.assertEqual(target_asset.purchase_amount, total_amount)
|
||||||
|
|
||||||
expected_gle = {
|
expected_gle = {
|
||||||
"_Test Fixed Asset - _TC": 1000.0,
|
"CWIP Account - _TC": 1000.0,
|
||||||
"Expenses Included In Asset Valuation - _TC": -1000.0,
|
"Expenses Included In Asset Valuation - _TC": -1000.0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user