fix: asset capitalization (#35832)

* fix: misc asset capitalisation fixes

* chore: add location in tests and remove unnecessary code

* chore: more fixes and removals

* chore: show company and fix tests

* chore: make target qty read only on capitalization
This commit is contained in:
Anand Baburajan
2023-06-22 17:14:24 +05:30
committed by GitHub
parent 0138595000
commit fb823b53d1
4 changed files with 69 additions and 130 deletions

View File

@@ -14,7 +14,6 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
} }
refresh() { refresh() {
erpnext.hide_company();
this.show_general_ledger(); this.show_general_ledger();
if ((this.frm.doc.stock_items && this.frm.doc.stock_items.length) || !this.frm.doc.target_is_fixed_asset) { if ((this.frm.doc.stock_items && this.frm.doc.stock_items.length) || !this.frm.doc.target_is_fixed_asset) {
this.show_stock_ledger(); this.show_stock_ledger();
@@ -105,10 +104,6 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
return this.get_target_item_details(); return this.get_target_item_details();
} }
target_asset() {
return this.get_target_asset_details();
}
item_code(doc, cdt, cdn) { item_code(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn); var row = frappe.get_doc(cdt, cdn);
if (cdt === "Asset Capitalization Stock Item") { if (cdt === "Asset Capitalization Stock Item") {
@@ -223,26 +218,6 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
} }
} }
get_target_asset_details() {
var me = this;
if (me.frm.doc.target_asset) {
return me.frm.call({
method: "erpnext.assets.doctype.asset_capitalization.asset_capitalization.get_target_asset_details",
child: me.frm.doc,
args: {
asset: me.frm.doc.target_asset,
company: me.frm.doc.company,
},
callback: function (r) {
if (!r.exc) {
me.frm.refresh_fields();
}
}
});
}
}
get_consumed_stock_item_details(row) { get_consumed_stock_item_details(row) {
var me = this; var me = this;

View File

@@ -11,13 +11,14 @@
"naming_series", "naming_series",
"entry_type", "entry_type",
"target_item_code", "target_item_code",
"target_asset",
"target_item_name", "target_item_name",
"target_is_fixed_asset", "target_is_fixed_asset",
"target_has_batch_no", "target_has_batch_no",
"target_has_serial_no", "target_has_serial_no",
"column_break_9", "column_break_9",
"target_asset",
"target_asset_name", "target_asset_name",
"target_asset_location",
"target_warehouse", "target_warehouse",
"target_qty", "target_qty",
"target_stock_uom", "target_stock_uom",
@@ -85,14 +86,13 @@
"fieldtype": "Column Break" "fieldtype": "Column Break"
}, },
{ {
"depends_on": "eval:doc.entry_type=='Capitalization'",
"fieldname": "target_asset", "fieldname": "target_asset",
"fieldtype": "Link", "fieldtype": "Link",
"in_standard_filter": 1, "in_standard_filter": 1,
"label": "Target Asset", "label": "Target Asset",
"mandatory_depends_on": "eval:doc.entry_type=='Capitalization'",
"no_copy": 1, "no_copy": 1,
"options": "Asset" "options": "Asset",
"read_only": 1
}, },
{ {
"depends_on": "eval:doc.entry_type=='Capitalization'", "depends_on": "eval:doc.entry_type=='Capitalization'",
@@ -108,11 +108,11 @@
"fieldtype": "Column Break" "fieldtype": "Column Break"
}, },
{ {
"fetch_from": "asset.company",
"fieldname": "company", "fieldname": "company",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Company", "label": "Company",
"options": "Company", "options": "Company",
"remember_last_selected_value": 1,
"reqd": 1 "reqd": 1
}, },
{ {
@@ -158,7 +158,7 @@
"read_only": 1 "read_only": 1
}, },
{ {
"depends_on": "eval:doc.docstatus == 0 || (doc.stock_items && doc.stock_items.length)", "depends_on": "eval:doc.entry_type=='Capitalization' && (doc.docstatus == 0 || (doc.stock_items && doc.stock_items.length))",
"fieldname": "section_break_16", "fieldname": "section_break_16",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Consumed Stock Items" "label": "Consumed Stock Items"
@@ -189,7 +189,7 @@
"fieldname": "target_qty", "fieldname": "target_qty",
"fieldtype": "Float", "fieldtype": "Float",
"label": "Target Qty", "label": "Target Qty",
"read_only_depends_on": "target_is_fixed_asset" "read_only_depends_on": "eval:doc.entry_type=='Capitalization'"
}, },
{ {
"fetch_from": "target_item_code.stock_uom", "fetch_from": "target_item_code.stock_uom",
@@ -227,7 +227,7 @@
"depends_on": "eval:doc.docstatus == 0 || (doc.asset_items && doc.asset_items.length)", "depends_on": "eval:doc.docstatus == 0 || (doc.asset_items && doc.asset_items.length)",
"fieldname": "section_break_26", "fieldname": "section_break_26",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Consumed Asset Items" "label": "Consumed Assets"
}, },
{ {
"fieldname": "asset_items", "fieldname": "asset_items",
@@ -266,7 +266,7 @@
"options": "Finance Book" "options": "Finance Book"
}, },
{ {
"depends_on": "eval:doc.docstatus == 0 || (doc.service_items && doc.service_items.length)", "depends_on": "eval:doc.entry_type=='Capitalization' && (doc.docstatus == 0 || (doc.service_items && doc.service_items.length))",
"fieldname": "service_expenses_section", "fieldname": "service_expenses_section",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Service Expenses" "label": "Service Expenses"
@@ -329,12 +329,20 @@
"label": "Target Fixed Asset Account", "label": "Target Fixed Asset Account",
"options": "Account", "options": "Account",
"read_only": 1 "read_only": 1
},
{
"depends_on": "eval:doc.entry_type=='Capitalization'",
"fieldname": "target_asset_location",
"fieldtype": "Link",
"label": "Target Asset Location",
"mandatory_depends_on": "eval:doc.entry_type=='Capitalization'",
"options": "Location"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-09-12 15:09:40.771332", "modified": "2023-06-22 14:17:07.995120",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Assets", "module": "Assets",
"name": "Asset Capitalization", "name": "Asset Capitalization",

View File

@@ -7,7 +7,7 @@ import frappe
# import erpnext # import erpnext
from frappe import _ from frappe import _
from frappe.utils import cint, flt from frappe.utils import cint, flt, get_link_to_form
from six import string_types from six import string_types
import erpnext import erpnext
@@ -43,7 +43,6 @@ force_fields = [
"target_has_batch_no", "target_has_batch_no",
"target_stock_uom", "target_stock_uom",
"stock_uom", "stock_uom",
"target_fixed_asset_account",
"fixed_asset_account", "fixed_asset_account",
"valuation_rate", "valuation_rate",
] ]
@@ -54,7 +53,6 @@ class AssetCapitalization(StockController):
self.validate_posting_time() self.validate_posting_time()
self.set_missing_values(for_validate=True) self.set_missing_values(for_validate=True)
self.validate_target_item() self.validate_target_item()
self.validate_target_asset()
self.validate_consumed_stock_item() self.validate_consumed_stock_item()
self.validate_consumed_asset_item() self.validate_consumed_asset_item()
self.validate_service_item() self.validate_service_item()
@@ -65,17 +63,18 @@ class AssetCapitalization(StockController):
def before_submit(self): def before_submit(self):
self.validate_source_mandatory() self.validate_source_mandatory()
if self.entry_type == "Capitalization":
self.create_target_asset()
def on_submit(self): def on_submit(self):
self.update_stock_ledger() self.update_stock_ledger()
self.make_gl_entries() self.make_gl_entries()
self.update_target_asset()
def on_cancel(self): def on_cancel(self):
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Repost Item Valuation") self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Repost Item Valuation")
self.update_stock_ledger() self.update_stock_ledger()
self.make_gl_entries() self.make_gl_entries()
self.update_target_asset() self.restore_consumed_asset_items()
def set_title(self): def set_title(self):
self.title = self.target_asset_name or self.target_item_name or self.target_item_code self.title = self.target_asset_name or self.target_item_name or self.target_item_code
@@ -86,15 +85,6 @@ class AssetCapitalization(StockController):
if self.meta.has_field(k) and (not self.get(k) or k in force_fields): if self.meta.has_field(k) and (not self.get(k) or k in force_fields):
self.set(k, v) self.set(k, v)
# Remove asset if item not a fixed asset
if not self.target_is_fixed_asset:
self.target_asset = None
target_asset_details = get_target_asset_details(self.target_asset, self.company)
for k, v in target_asset_details.items():
if self.meta.has_field(k) and (not self.get(k) or k in force_fields):
self.set(k, v)
for d in self.stock_items: for d in self.stock_items:
args = self.as_dict() args = self.as_dict()
args.update(d.as_dict()) args.update(d.as_dict())
@@ -146,9 +136,6 @@ class AssetCapitalization(StockController):
if not target_item.is_stock_item: if not target_item.is_stock_item:
self.target_warehouse = None self.target_warehouse = None
if not target_item.is_fixed_asset:
self.target_asset = None
self.target_fixed_asset_account = None
if not target_item.has_batch_no: if not target_item.has_batch_no:
self.target_batch_no = None self.target_batch_no = None
if not target_item.has_serial_no: if not target_item.has_serial_no:
@@ -159,17 +146,6 @@ class AssetCapitalization(StockController):
self.validate_item(target_item) self.validate_item(target_item)
def validate_target_asset(self):
if self.target_asset:
target_asset = self.get_asset_for_validation(self.target_asset)
if target_asset.item_code != self.target_item_code:
frappe.throw(
_("Asset {0} does not belong to Item {1}").format(self.target_asset, self.target_item_code)
)
self.validate_asset(target_asset)
def validate_consumed_stock_item(self): def validate_consumed_stock_item(self):
for d in self.stock_items: for d in self.stock_items:
if d.item_code: if d.item_code:
@@ -379,7 +355,11 @@ class AssetCapitalization(StockController):
gl_entries, target_account, target_against, precision gl_entries, target_account, target_against, precision
) )
if not self.stock_items and not self.service_items and self.are_all_asset_items_non_depreciable:
return []
self.get_gl_entries_for_target_item(gl_entries, target_against, precision) self.get_gl_entries_for_target_item(gl_entries, target_against, precision)
return gl_entries return gl_entries
def get_target_account(self): def get_target_account(self):
@@ -422,11 +402,14 @@ class AssetCapitalization(StockController):
def get_gl_entries_for_consumed_asset_items( def get_gl_entries_for_consumed_asset_items(
self, gl_entries, target_account, target_against, precision self, gl_entries, target_account, target_against, precision
): ):
self.are_all_asset_items_non_depreciable = True
# Consumed Assets # Consumed Assets
for item in self.asset_items: for item in self.asset_items:
asset = self.get_asset(item) asset = frappe.get_doc("Asset", item.asset)
if asset.calculate_depreciation: if asset.calculate_depreciation:
self.are_all_asset_items_non_depreciable = False
depreciate_asset(asset, self.posting_date) depreciate_asset(asset, self.posting_date)
asset.reload() asset.reload()
@@ -507,30 +490,41 @@ class AssetCapitalization(StockController):
) )
) )
def update_target_asset(self): def create_target_asset(self):
total_target_asset_value = flt(self.total_value, self.precision("total_value")) total_target_asset_value = flt(self.total_value, self.precision("total_value"))
if self.docstatus == 1 and self.entry_type == "Capitalization": asset_doc = frappe.new_doc("Asset")
asset_doc = frappe.get_doc("Asset", self.target_asset) asset_doc.company = self.company
asset_doc.purchase_date = self.posting_date asset_doc.item_code = self.target_item_code
asset_doc.gross_purchase_amount = total_target_asset_value asset_doc.is_existing_asset = 1
asset_doc.purchase_receipt_amount = total_target_asset_value asset_doc.location = self.target_asset_location
asset_doc.prepare_depreciation_data() asset_doc.available_for_use_date = self.posting_date
asset_doc.flags.ignore_validate_update_after_submit = True asset_doc.purchase_date = self.posting_date
asset_doc.save() asset_doc.gross_purchase_amount = total_target_asset_value
elif self.docstatus == 2: asset_doc.purchase_receipt_amount = total_target_asset_value
for item in self.asset_items: asset_doc.flags.ignore_validate = True
asset = self.get_asset(item) asset_doc.insert()
asset.db_set("disposal_date", None)
self.set_consumed_asset_status(asset)
if asset.calculate_depreciation: self.target_asset = asset_doc.name
reverse_depreciation_entry_made_after_disposal(asset, self.posting_date)
reset_depreciation_schedule(asset, self.posting_date)
def get_asset(self, item): self.target_fixed_asset_account = get_asset_category_account(
asset = frappe.get_doc("Asset", item.asset) "fixed_asset_account", item=self.target_item_code, company=asset_doc.company
self.check_finance_books(item, asset) )
return asset
frappe.msgprint(
_(
"Asset {0} has been created. Please set the depreciation details if any and submit it."
).format(get_link_to_form("Asset", asset_doc.name))
)
def restore_consumed_asset_items(self):
for item in self.asset_items:
asset = frappe.get_doc("Asset", item.asset)
asset.db_set("disposal_date", None)
self.set_consumed_asset_status(asset)
if asset.calculate_depreciation:
reverse_depreciation_entry_made_after_disposal(asset, self.posting_date)
reset_depreciation_schedule(asset, self.posting_date)
def set_consumed_asset_status(self, asset): def set_consumed_asset_status(self, asset):
if self.docstatus == 1: if self.docstatus == 1:
@@ -580,33 +574,6 @@ def get_target_item_details(item_code=None, company=None):
return out return out
@frappe.whitelist()
def get_target_asset_details(asset=None, company=None):
out = frappe._dict()
# Get Asset Details
asset_details = frappe._dict()
if asset:
asset_details = frappe.db.get_value("Asset", asset, ["asset_name", "item_code"], as_dict=1)
if not asset_details:
frappe.throw(_("Asset {0} does not exist").format(asset))
# Re-set item code from Asset
out.target_item_code = asset_details.item_code
# Set Asset Details
out.asset_name = asset_details.asset_name
if asset_details.item_code:
out.target_fixed_asset_account = get_asset_category_account(
"fixed_asset_account", item=asset_details.item_code, company=company
)
else:
out.target_fixed_asset_account = None
return out
@frappe.whitelist() @frappe.whitelist()
def get_consumed_stock_item_details(args): def get_consumed_stock_item_details(args):
if isinstance(args, string_types): if isinstance(args, string_types):

View File

@@ -39,13 +39,6 @@ class TestAssetCapitalization(unittest.TestCase):
total_amount = 103000 total_amount = 103000
# Create assets
target_asset = create_asset(
asset_name="Asset Capitalization Target Asset",
submit=1,
warehouse="Stores - TCP1",
company=company,
)
consumed_asset = create_asset( consumed_asset = create_asset(
asset_name="Asset Capitalization Consumable Asset", asset_name="Asset Capitalization Consumable Asset",
asset_value=consumed_asset_value, asset_value=consumed_asset_value,
@@ -57,7 +50,8 @@ class TestAssetCapitalization(unittest.TestCase):
# Create and submit Asset Captitalization # Create and submit Asset Captitalization
asset_capitalization = create_asset_capitalization( asset_capitalization = create_asset_capitalization(
entry_type="Capitalization", entry_type="Capitalization",
target_asset=target_asset.name, target_item_code="Macbook Pro",
target_asset_location="Test Location",
stock_qty=stock_qty, stock_qty=stock_qty,
stock_rate=stock_rate, stock_rate=stock_rate,
consumed_asset=consumed_asset.name, consumed_asset=consumed_asset.name,
@@ -86,7 +80,7 @@ class TestAssetCapitalization(unittest.TestCase):
self.assertEqual(asset_capitalization.target_incoming_rate, total_amount) self.assertEqual(asset_capitalization.target_incoming_rate, total_amount)
# Test Target Asset values # Test Target Asset values
target_asset.reload() target_asset = frappe.get_doc("Asset", asset_capitalization.target_asset)
self.assertEqual(target_asset.gross_purchase_amount, total_amount) self.assertEqual(target_asset.gross_purchase_amount, total_amount)
self.assertEqual(target_asset.purchase_receipt_amount, total_amount) self.assertEqual(target_asset.purchase_receipt_amount, total_amount)
@@ -134,13 +128,6 @@ class TestAssetCapitalization(unittest.TestCase):
total_amount = 103000 total_amount = 103000
# Create assets
target_asset = create_asset(
asset_name="Asset Capitalization Target Asset",
submit=1,
warehouse="Stores - _TC",
company=company,
)
consumed_asset = create_asset( consumed_asset = create_asset(
asset_name="Asset Capitalization Consumable Asset", asset_name="Asset Capitalization Consumable Asset",
asset_value=consumed_asset_value, asset_value=consumed_asset_value,
@@ -152,7 +139,8 @@ class TestAssetCapitalization(unittest.TestCase):
# Create and submit Asset Captitalization # Create and submit Asset Captitalization
asset_capitalization = create_asset_capitalization( asset_capitalization = create_asset_capitalization(
entry_type="Capitalization", entry_type="Capitalization",
target_asset=target_asset.name, target_item_code="Macbook Pro",
target_asset_location="Test Location",
stock_qty=stock_qty, stock_qty=stock_qty,
stock_rate=stock_rate, stock_rate=stock_rate,
consumed_asset=consumed_asset.name, consumed_asset=consumed_asset.name,
@@ -181,7 +169,7 @@ class TestAssetCapitalization(unittest.TestCase):
self.assertEqual(asset_capitalization.target_incoming_rate, total_amount) self.assertEqual(asset_capitalization.target_incoming_rate, total_amount)
# Test Target Asset values # Test Target Asset values
target_asset.reload() target_asset = frappe.get_doc("Asset", asset_capitalization.target_asset)
self.assertEqual(target_asset.gross_purchase_amount, total_amount) self.assertEqual(target_asset.gross_purchase_amount, total_amount)
self.assertEqual(target_asset.purchase_receipt_amount, total_amount) self.assertEqual(target_asset.purchase_receipt_amount, total_amount)
@@ -343,6 +331,7 @@ def create_asset_capitalization(**args):
"posting_time": args.posting_time or now.strftime("%H:%M:%S.%f"), "posting_time": args.posting_time or now.strftime("%H:%M:%S.%f"),
"target_item_code": target_item_code, "target_item_code": target_item_code,
"target_asset": target_asset.name, "target_asset": target_asset.name,
"target_asset_location": "Test Location",
"target_warehouse": target_warehouse, "target_warehouse": target_warehouse,
"target_qty": flt(args.target_qty) or 1, "target_qty": flt(args.target_qty) or 1,
"target_batch_no": args.target_batch_no, "target_batch_no": args.target_batch_no,