diff --git a/erpnext/accounts/doctype/accounting_period/accounting_period.py b/erpnext/accounts/doctype/accounting_period/accounting_period.py
index c4e51d813b2..16a29bf4591 100644
--- a/erpnext/accounts/doctype/accounting_period/accounting_period.py
+++ b/erpnext/accounts/doctype/accounting_period/accounting_period.py
@@ -97,7 +97,7 @@ def validate_accounting_period_on_doc_save(doc, method=None):
if doc.doctype == "Bank Clearance":
return
elif doc.doctype == "Asset":
- if doc.is_existing_asset:
+ if doc.asset_type == "Existing Asset":
return
else:
date = doc.available_for_use_date
diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
index ac214fdac43..e214d2f4416 100644
--- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
+++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.js
@@ -534,7 +534,7 @@ cur_frm.fields_dict["select_print_heading"].get_query = function (doc, cdt, cdn)
cur_frm.set_query("wip_composite_asset", "items", function () {
return {
- filters: { is_composite_asset: 1, docstatus: 0 },
+ filters: { asset_type: "Composite Asset", docstatus: 0 },
};
});
diff --git a/erpnext/assets/dashboard_chart/category_wise_asset_value/category_wise_asset_value.json b/erpnext/assets/dashboard_chart/category_wise_asset_value/category_wise_asset_value.json
index 78611da0036..60551560185 100644
--- a/erpnext/assets/dashboard_chart/category_wise_asset_value/category_wise_asset_value.json
+++ b/erpnext/assets/dashboard_chart/category_wise_asset_value/category_wise_asset_value.json
@@ -6,11 +6,11 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_date\":\"frappe.datetime.add_months(frappe.datetime.nowdate(), -12)\",\"to_date\":\"frappe.datetime.nowdate()\"}",
- "filters_json": "{\"status\":\"In Location\",\"group_by\":\"Asset Category\",\"is_existing_asset\":0}",
+ "filters_json": "{\"status\":\"In Location\",\"group_by\":\"Asset Category\",\"asset_type\":[\"!=\",\"Existing Asset\"]}",
"idx": 0,
"is_public": 1,
"is_standard": 1,
- "modified": "2020-10-28 23:16:16.939070",
+ "modified": "2026-02-03 15:48:13.407835",
"modified_by": "Administrator",
"module": "Assets",
"name": "Category-wise Asset Value",
diff --git a/erpnext/assets/dashboard_chart/location_wise_asset_value/location_wise_asset_value.json b/erpnext/assets/dashboard_chart/location_wise_asset_value/location_wise_asset_value.json
index 848184cc148..3f89d987ba0 100644
--- a/erpnext/assets/dashboard_chart/location_wise_asset_value/location_wise_asset_value.json
+++ b/erpnext/assets/dashboard_chart/location_wise_asset_value/location_wise_asset_value.json
@@ -6,11 +6,11 @@
"docstatus": 0,
"doctype": "Dashboard Chart",
"dynamic_filters_json": "{\"company\":\"frappe.defaults.get_user_default(\\\"Company\\\")\",\"from_date\":\"frappe.datetime.add_months(frappe.datetime.nowdate(), -12)\",\"to_date\":\"frappe.datetime.nowdate()\"}",
- "filters_json": "{\"status\":\"In Location\",\"group_by\":\"Location\",\"is_existing_asset\":0}",
+ "filters_json": "{\"status\":\"In Location\",\"group_by\":\"Location\",\"asset_type\":[\"!=\",\"Existing Asset\"]}",
"idx": 0,
"is_public": 1,
"is_standard": 1,
- "modified": "2020-10-28 23:16:07.883312",
+ "modified": "2026-02-03 15:48:13.407835",
"modified_by": "Administrator",
"module": "Assets",
"name": "Location-wise Asset Value",
diff --git a/erpnext/assets/dashboard_fixtures.py b/erpnext/assets/dashboard_fixtures.py
index 3b1d14440cf..0fd6c019f36 100644
--- a/erpnext/assets/dashboard_fixtures.py
+++ b/erpnext/assets/dashboard_fixtures.py
@@ -100,7 +100,7 @@ def get_charts(fiscal_year, year_start_date, year_end_date):
"company": company,
"status": "In Location",
"group_by": "Asset Category",
- "is_existing_asset": 0,
+ "asset_type": ["!=", "Existing Asset"],
}
),
"type": "Donut",
@@ -126,7 +126,12 @@ def get_charts(fiscal_year, year_start_date, year_end_date):
"x_field": "location",
"timeseries": 0,
"filters_json": json.dumps(
- {"company": company, "status": "In Location", "group_by": "Location", "is_existing_asset": 0}
+ {
+ "company": company,
+ "status": "In Location",
+ "group_by": "Location",
+ "asset_type": ["!=", "Existing Asset"],
+ }
),
"type": "Donut",
"doctype": "Dashboard Chart",
diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js
index 28add7cb35d..2a7703495bf 100644
--- a/erpnext/assets/doctype/asset/asset.js
+++ b/erpnext/assets/doctype/asset/asset.js
@@ -81,23 +81,79 @@ frappe.ui.form.on("Asset", {
},
before_submit: function (frm) {
- if (frm.doc.is_composite_asset && !frm.has_active_capitalization) {
+ if (frm.doc.asset_type == "Composite Asset" && !frm.has_active_capitalization) {
frappe.throw(__("Please capitalize this asset before submitting."));
}
},
- refresh: function (frm) {
- frappe.ui.form.trigger("Asset", "is_existing_asset");
+ refresh: async function (frm) {
+ frappe.ui.form.trigger("Asset", "asset_type");
frm.toggle_display("next_depreciation_date", frm.doc.docstatus < 1);
+ let has_create_buttons = false;
if (frm.doc.docstatus == 1) {
+ if (["Submitted", "Partially Depreciated"].includes(frm.doc.status)) {
+ frm.add_custom_button(
+ __("Asset Value Adjustment"),
+ function () {
+ frm.trigger("create_asset_value_adjustment");
+ },
+ __("Create")
+ );
+
+ frm.add_custom_button(
+ __("Asset Repair"),
+ function () {
+ frm.trigger("create_asset_repair");
+ },
+ __("Create")
+ );
+ has_create_buttons = true;
+ }
+
+ if (
+ !frm.doc.calculate_depreciation &&
+ ["Submitted", "Partially Depreciated", "Fully Depreciated"].includes(frm.doc.status)
+ ) {
+ frm.add_custom_button(
+ __("Depreciation Entry"),
+ function () {
+ frm.trigger("make_journal_entry");
+ },
+ __("Create")
+ );
+ has_create_buttons = true;
+ }
+
+ if (has_create_buttons) {
+ frm.page.set_inner_btn_group_as_primary(__("Create"));
+ }
+
if (["Submitted", "Partially Depreciated", "Fully Depreciated"].includes(frm.doc.status)) {
+ if (frm.doc.maintenance_required && !frm.doc.maintenance_schedule) {
+ frm.add_custom_button(
+ __("Maintain Asset"),
+ function () {
+ frm.trigger("create_asset_maintenance");
+ },
+ __("Actions")
+ );
+ }
+
+ frm.add_custom_button(
+ __("Split Asset"),
+ function () {
+ frm.trigger("split_asset");
+ },
+ __("Actions")
+ );
+
frm.add_custom_button(
__("Transfer Asset"),
function () {
erpnext.asset.transfer_asset(frm);
},
- __("Manage")
+ __("Actions")
);
frm.add_custom_button(
@@ -105,7 +161,7 @@ frappe.ui.form.on("Asset", {
function () {
erpnext.asset.scrap_asset(frm);
},
- __("Manage")
+ __("Actions")
);
frm.add_custom_button(
@@ -113,15 +169,7 @@ frappe.ui.form.on("Asset", {
function () {
frm.trigger("sell_asset");
},
- __("Manage")
- );
-
- frm.add_custom_button(
- __("Split Asset"),
- function () {
- frm.trigger("split_asset");
- },
- __("Manage")
+ __("Actions")
);
} else if (frm.doc.status == "Scrapped") {
frm.add_custom_button(__("Restore Asset"), function () {
@@ -129,47 +177,9 @@ frappe.ui.form.on("Asset", {
}).addClass("btn-primary");
}
- if (frm.doc.maintenance_required && !frm.doc.maintenance_schedule) {
+ if (await frm.events.should_show_accounting_ledger(frm)) {
frm.add_custom_button(
- __("Maintain Asset"),
- function () {
- frm.trigger("create_asset_maintenance");
- },
- __("Manage")
- );
- }
-
- if (["Submitted", "Partially Depreciated"].includes(frm.doc.status)) {
- frm.add_custom_button(
- __("Adjust Asset Value"),
- function () {
- frm.trigger("create_asset_value_adjustment");
- },
- __("Manage")
- );
-
- frm.add_custom_button(
- __("Repair Asset"),
- function () {
- frm.trigger("create_asset_repair");
- },
- __("Manage")
- );
- }
-
- if (!frm.doc.calculate_depreciation) {
- frm.add_custom_button(
- __("Create Depreciation Entry"),
- function () {
- frm.trigger("make_journal_entry");
- },
- __("Manage")
- );
- }
-
- if (frm.doc.purchase_receipt || !frm.doc.is_existing_asset) {
- frm.add_custom_button(
- __("View General Ledger"),
+ __("Accounting Ledger"),
function () {
frappe.route_options = {
voucher_no: frm.doc.name,
@@ -179,7 +189,7 @@ frappe.ui.form.on("Asset", {
};
frappe.set_route("query-report", "General Ledger");
},
- __("Manage")
+ __("View")
);
}
@@ -195,7 +205,7 @@ frappe.ui.form.on("Asset", {
if (frm.doc.docstatus == 0) {
frm.toggle_reqd("finance_books", frm.doc.calculate_depreciation);
- if (frm.doc.is_composite_asset) {
+ if (frm.doc.asset_type == "Composite Asset") {
frappe.call({
method: "erpnext.assets.doctype.asset.asset.has_active_capitalization",
args: {
@@ -217,6 +227,28 @@ frappe.ui.form.on("Asset", {
}
},
+ should_show_accounting_ledger: async function (frm) {
+ if (["Capitalized"].includes(frm.doc.status)) {
+ return false;
+ }
+
+ if (
+ !frm.doc.purchase_receipt &&
+ !frm.doc.purchase_invoice &&
+ ["Existing Asset", "Composite Component"].includes(frm.doc.asset_type)
+ ) {
+ return false;
+ }
+
+ const asset_category = await frappe.db.get_value(
+ "Asset Category",
+ frm.doc.asset_category,
+ "enable_cwip_accounting"
+ );
+
+ return !!asset_category.message?.enable_cwip_accounting;
+ },
+
set_depr_posting_failure_alert: function (frm) {
const alert = `
@@ -232,7 +264,8 @@ frappe.ui.form.on("Asset", {
toggle_reference_doc: function (frm) {
const is_submitted = frm.doc.docstatus === 1;
- const is_special_asset = frm.doc.is_existing_asset || frm.doc.is_composite_asset;
+ const is_special_asset =
+ frm.doc.asset_type == "Existing Asset" || frm.doc.asset_type == "Composite Asset";
const clear_field = (field) => {
if (frm.doc[field]) {
@@ -508,18 +541,13 @@ frappe.ui.form.on("Asset", {
});
},
- is_existing_asset: function (frm) {
- frm.trigger("toggle_reference_doc");
- },
-
- is_composite_asset: function (frm) {
+ asset_type: function (frm) {
if (frm.doc.docstatus == 0) {
- if (frm.doc.is_composite_asset) {
+ if (frm.doc.asset_type == "Composite Asset") {
frm.set_value("net_purchase_amount", 0);
} else {
frm.set_df_property("net_purchase_amount", "read_only", 0);
}
- frm.trigger("toggle_reference_doc");
}
},
diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json
index 832f7c18e68..32f5ce9cf50 100644
--- a/erpnext/assets/doctype/asset/asset.json
+++ b/erpnext/assets/doctype/asset/asset.json
@@ -9,20 +9,17 @@
"engine": "InnoDB",
"field_order": [
"naming_series",
+ "company",
"item_code",
"item_name",
"asset_name",
- "asset_category",
- "location",
"image",
"column_break_3",
- "status",
- "company",
- "asset_owner",
- "asset_owner_company",
- "is_existing_asset",
- "is_composite_asset",
- "is_composite_component",
+ "location",
+ "asset_category",
+ "asset_type",
+ "maintenance_required",
+ "calculate_depreciation",
"purchase_details_section",
"purchase_receipt",
"purchase_receipt_item",
@@ -30,31 +27,44 @@
"purchase_invoice_item",
"purchase_date",
"available_for_use_date",
+ "disposal_date",
"column_break_23",
"net_purchase_amount",
"purchase_amount",
"asset_quantity",
"additional_asset_cost",
+ "section_break_uiyd",
+ "column_break_bbwr",
+ "column_break_bfkm",
"total_asset_cost",
- "disposal_date",
"depreciation_tab",
- "calculate_depreciation",
- "column_break_33",
+ "column_break_wqzi",
"opening_accumulated_depreciation",
- "opening_number_of_booked_depreciations",
"is_fully_depreciated",
+ "column_break_33",
+ "opening_number_of_booked_depreciations",
"section_break_36",
"finance_books",
"section_break_33",
"depreciation_method",
"value_after_depreciation",
- "total_number_of_depreciations",
- "column_break_24",
"frequency_of_depreciation",
+ "column_break_24",
"next_depreciation_date",
+ "total_number_of_depreciations",
"depreciation_schedule_sb",
"depreciation_schedule_view",
- "insurance_details_tab",
+ "other_info_tab",
+ "accounting_dimensions_section",
+ "cost_center",
+ "column_break_rjyw",
+ "asset_owner_section",
+ "asset_owner",
+ "column_break_yeds",
+ "asset_owner_company",
+ "customer",
+ "supplier",
+ "insurance_section",
"policy_number",
"insurer",
"insured_value",
@@ -62,22 +72,17 @@
"insurance_start_date",
"insurance_end_date",
"comprehensive_insurance",
- "other_info_tab",
- "accounting_dimensions_section",
- "cost_center",
"section_break_jtou",
+ "status",
"custodian",
+ "department",
"default_finance_book",
"depr_entry_posting_status",
- "booked_fixed_asset",
- "customer",
- "supplier",
"column_break_51",
- "department",
- "split_from",
"journal_entry_for_scrap",
+ "split_from",
"amended_from",
- "maintenance_required",
+ "booked_fixed_asset",
"connections_tab"
],
"fields": [
@@ -106,13 +111,6 @@
"options": "Item",
"reqd": 1
},
- {
- "depends_on": "item_code",
- "fetch_from": "item_code.item_name",
- "fieldname": "item_name",
- "fieldtype": "Read Only",
- "label": "Item Name"
- },
{
"depends_on": "item_code",
"fetch_from": "item_code.asset_category",
@@ -207,7 +205,7 @@
"fieldname": "purchase_date",
"fieldtype": "Date",
"label": "Purchase Date",
- "read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset",
+ "read_only_depends_on": "eval:doc.asset_type != \"Existing Asset\" && doc.asset_type != \"Composite Asset\"",
"reqd": 1
},
{
@@ -229,25 +227,18 @@
{
"fieldname": "available_for_use_date",
"fieldtype": "Date",
- "label": "Available-for-use Date",
- "mandatory_depends_on": "eval:(!(doc.is_composite_component || doc.is_composite_asset) || doc.docstatus==1)"
+ "label": "Available for Use Date",
+ "mandatory_depends_on": "eval:(!(doc.asset_type == \"Composite Component\" || doc.asset_type == \"Composite Asset\") || doc.docstatus==1)"
},
{
"default": "0",
"fieldname": "calculate_depreciation",
"fieldtype": "Check",
"label": "Calculate Depreciation",
- "read_only_depends_on": "eval:(doc.is_composite_asset && !doc.net_purchase_amount) || doc.is_composite_component"
+ "read_only_depends_on": "eval:(doc.asset_type == \"Composite Asset\" && !doc.net_purchase_amount) || doc.asset_type == \"Composite Component\""
},
{
- "default": "0",
- "depends_on": "eval:(!doc.is_composite_asset && !doc.is_composite_component)",
- "fieldname": "is_existing_asset",
- "fieldtype": "Check",
- "label": "Is Existing Asset"
- },
- {
- "depends_on": "eval:(doc.is_existing_asset)",
+ "depends_on": "eval:(doc.asset_type == \"Existing Asset\")",
"fieldname": "opening_accumulated_depreciation",
"fieldtype": "Currency",
"label": "Opening Accumulated Depreciation",
@@ -257,18 +248,20 @@
"columns": 10,
"fieldname": "finance_books",
"fieldtype": "Table",
+ "label": "Finance Books",
"options": "Asset Finance Book"
},
{
"fieldname": "section_break_33",
"fieldtype": "Section Break",
- "hidden": 1
+ "hidden": 1,
+ "label": "Depreciation Details"
},
{
"fieldname": "depreciation_method",
"fieldtype": "Select",
"label": "Depreciation Method",
- "options": "\nStraight Line\nDouble Declining Balance\nManual"
+ "options": "\nStraight Line\nDouble Declining Balance\nWritten Down Value\nManual"
},
{
"fieldname": "value_after_depreciation",
@@ -295,6 +288,7 @@
{
"fieldname": "next_depreciation_date",
"fieldtype": "Date",
+ "hidden": 1,
"label": "Next Depreciation Date",
"no_copy": 1
},
@@ -364,7 +358,7 @@
"fieldtype": "Column Break"
},
{
- "depends_on": "eval:!doc.is_composite_asset && !doc.is_existing_asset",
+ "depends_on": "eval:doc.asset_type != \"Composite Asset\" && doc.asset_type != \"Existing Asset\"",
"fieldname": "purchase_receipt",
"fieldtype": "Link",
"label": "Purchase Receipt",
@@ -373,7 +367,7 @@
"print_hide": 1
},
{
- "depends_on": "eval:!doc.is_composite_asset && !doc.is_existing_asset",
+ "depends_on": "eval:doc.asset_type != \"Composite Asset\" && doc.asset_type != \"Existing Asset\"",
"fieldname": "purchase_invoice",
"fieldtype": "Link",
"label": "Purchase Invoice",
@@ -399,7 +393,7 @@
"read_only": 1
},
{
- "collapsible_depends_on": "is_existing_asset",
+ "collapsible_depends_on": "eval:doc.asset_type == \"Existing Asset\"",
"fieldname": "purchase_details_section",
"fieldtype": "Section Break",
"label": "Purchase Details"
@@ -413,10 +407,9 @@
"fieldtype": "Column Break"
},
{
- "depends_on": "calculate_depreciation",
+ "depends_on": "eval: doc.calculate_depreciation",
"fieldname": "section_break_36",
- "fieldtype": "Section Break",
- "label": "Finance Books"
+ "fieldtype": "Section Break"
},
{
"fieldname": "split_from",
@@ -455,18 +448,11 @@
},
{
"default": "0",
- "depends_on": "eval:(doc.is_existing_asset)",
"fieldname": "is_fully_depreciated",
"fieldtype": "Check",
+ "hidden": 1,
"label": "Is Fully Depreciated"
},
- {
- "default": "0",
- "depends_on": "eval:(!doc.is_existing_asset && !doc.is_composite_component)",
- "fieldname": "is_composite_asset",
- "fieldtype": "Check",
- "label": "Is Composite Asset"
- },
{
"depends_on": "eval:doc.docstatus > 0",
"fieldname": "total_asset_cost",
@@ -496,7 +482,7 @@
"read_only": 1
},
{
- "depends_on": "eval:(doc.is_existing_asset)",
+ "depends_on": "eval:(doc.asset_type == \"Existing Asset\")",
"fieldname": "opening_number_of_booked_depreciations",
"fieldtype": "Int",
"label": "Opening Number of Booked Depreciations"
@@ -513,15 +499,10 @@
"hidden": 1,
"label": "Purchase Invoice Item"
},
- {
- "fieldname": "insurance_details_tab",
- "fieldtype": "Tab Break",
- "label": "Insurance"
- },
{
"fieldname": "other_info_tab",
"fieldtype": "Tab Break",
- "label": "Other Info"
+ "label": "More Info"
},
{
"fieldname": "connections_tab",
@@ -530,6 +511,7 @@
"show_dashboard": 1
},
{
+ "depends_on": "eval: doc.calculate_depreciation || doc.asset_type == \"Existing Asset\"",
"fieldname": "depreciation_tab",
"fieldtype": "Tab Break",
"label": "Depreciation"
@@ -544,20 +526,61 @@
"fieldtype": "Section Break",
"label": "Additional Info"
},
- {
- "default": "0",
- "depends_on": "eval:(!doc.is_existing_asset && !doc.is_composite_asset)",
- "fieldname": "is_composite_component",
- "fieldtype": "Check",
- "label": "Is Composite Component"
- },
{
"fieldname": "net_purchase_amount",
"fieldtype": "Currency",
"label": "Net Purchase Amount",
- "mandatory_depends_on": "eval:(!doc.is_composite_asset || doc.docstatus==1)",
+ "mandatory_depends_on": "eval:(doc.asset_type != \"Composite Asset\" || doc.docstatus==1)",
"options": "Company:company:default_currency",
- "read_only_depends_on": "eval: doc.is_composite_asset"
+ "read_only_depends_on": "eval: doc.asset_type == \"Composite Asset\""
+ },
+ {
+ "fieldname": "asset_type",
+ "fieldtype": "Select",
+ "label": "Asset Type",
+ "options": "\nExisting Asset\nComposite Asset\nComposite Component"
+ },
+ {
+ "fieldname": "column_break_wqzi",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "column_break_rjyw",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "insurance_section",
+ "fieldtype": "Section Break",
+ "label": "Insurance"
+ },
+ {
+ "fieldname": "section_break_uiyd",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "column_break_bbwr",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "column_break_bfkm",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fetch_from": "item_code.item_name",
+ "fetch_if_empty": 1,
+ "fieldname": "item_name",
+ "fieldtype": "Read Only",
+ "hidden": 1,
+ "label": "Item Name"
+ },
+ {
+ "fieldname": "asset_owner_section",
+ "fieldtype": "Section Break",
+ "label": "Ownership"
+ },
+ {
+ "fieldname": "column_break_yeds",
+ "fieldtype": "Column Break"
}
],
"idx": 72,
@@ -601,7 +624,7 @@
"link_fieldname": "target_asset"
}
],
- "modified": "2025-12-18 16:36:40.904246",
+ "modified": "2026-02-05 12:42:45.350216",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",
diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py
index 42c8e9f9dfa..95011c8bba1 100644
--- a/erpnext/assets/doctype/asset/asset.py
+++ b/erpnext/assets/doctype/asset/asset.py
@@ -56,6 +56,7 @@ class Asset(AccountsController):
asset_owner: DF.Literal["", "Company", "Supplier", "Customer"]
asset_owner_company: DF.Link | None
asset_quantity: DF.Int
+ asset_type: DF.Literal["", "Existing Asset", "Composite Asset", "Composite Component"]
available_for_use_date: DF.Date | None
booked_fixed_asset: DF.Check
calculate_depreciation: DF.Check
@@ -67,7 +68,9 @@ class Asset(AccountsController):
default_finance_book: DF.Link | None
department: DF.Link | None
depr_entry_posting_status: DF.Literal["", "Successful", "Failed"]
- depreciation_method: DF.Literal["", "Straight Line", "Double Declining Balance", "Manual"]
+ depreciation_method: DF.Literal[
+ "", "Straight Line", "Double Declining Balance", "Written Down Value", "Manual"
+ ]
disposal_date: DF.Date | None
finance_books: DF.Table[AssetFinanceBook]
frequency_of_depreciation: DF.Int
@@ -76,9 +79,6 @@ class Asset(AccountsController):
insurance_start_date: DF.Date | None
insured_value: DF.Data | None
insurer: DF.Data | None
- is_composite_asset: DF.Check
- is_composite_component: DF.Check
- is_existing_asset: DF.Check
is_fully_depreciated: DF.Check
item_code: DF.Link
item_name: DF.ReadOnly | None
@@ -243,7 +243,7 @@ class Asset(AccountsController):
self.set_total_booked_depreciations()
def before_submit(self):
- if self.is_composite_asset and not has_active_capitalization(self.name):
+ if self.asset_type == "Composite Asset" and not has_active_capitalization(self.name):
if self.split_from and has_active_capitalization(self.split_from):
return
frappe.throw(_("Please capitalize this asset before submitting."))
@@ -252,7 +252,11 @@ class Asset(AccountsController):
self.validate_in_use_date()
self.make_asset_movement()
self.reload()
- if not self.booked_fixed_asset and not self.is_composite_component and self.validate_make_gl_entry():
+ if (
+ not self.booked_fixed_asset
+ and self.asset_type != "Composite Component"
+ and self.validate_make_gl_entry()
+ ):
self.make_gl_entries()
if self.calculate_depreciation and not self.split_from:
convert_draft_asset_depr_schedules_into_active(self)
@@ -267,7 +271,7 @@ class Asset(AccountsController):
cancel_asset_depr_schedules(self)
self.set_status()
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry")
- if not self.is_composite_component:
+ if self.asset_type != "Composite Component":
make_reverse_gl_entries(voucher_type="Asset", voucher_no=self.name)
self.db_set("booked_fixed_asset", 0)
add_asset_activity(self.name, _("Asset cancelled"))
@@ -285,7 +289,7 @@ class Asset(AccountsController):
add_asset_activity(self.name, _("Asset deleted"))
def set_purchase_doc_row_item(self):
- if self.is_existing_asset or self.is_composite_asset:
+ if self.asset_type == "Existing Asset" or self.asset_type == "Composite Asset":
return
self.purchase_amount = self.net_purchase_amount
@@ -328,7 +332,7 @@ class Asset(AccountsController):
)
)
- if self.is_existing_asset and self.purchase_invoice:
+ if self.asset_type == "Existing Asset" and self.purchase_invoice:
frappe.throw(_("Purchase Invoice cannot be made against an existing asset {0}").format(self.name))
def validate_item(self):
@@ -374,7 +378,7 @@ class Asset(AccountsController):
)
def validate_in_use_date(self):
- if not self.available_for_use_date and not self.is_composite_component:
+ if not self.available_for_use_date and self.asset_type != "Composite Component":
frappe.throw(_("Available for use date is required"))
for d in self.finance_books:
@@ -442,13 +446,13 @@ class Asset(AccountsController):
if not self.asset_category:
self.asset_category = frappe.get_cached_value("Item", self.item_code, "asset_category")
- if not flt(self.net_purchase_amount) and not self.is_composite_asset:
+ if not flt(self.net_purchase_amount) and self.asset_type != "Composite Asset":
frappe.throw(_("Net Purchase Amount is mandatory"), frappe.MandatoryError)
if is_cwip_accounting_enabled(self.asset_category):
if (
- not self.is_existing_asset
- and not self.is_composite_asset
+ not self.asset_type == "Existing Asset"
+ and not self.asset_type == "Composite Asset"
and not self.purchase_receipt
and not self.purchase_invoice
):
@@ -477,7 +481,7 @@ class Asset(AccountsController):
if self.is_fully_depreciated:
frappe.throw(_("Depreciation cannot be calculated for fully depreciated assets"))
- if self.is_existing_asset:
+ if self.asset_type == "Existing Asset":
return
if self.available_for_use_date and getdate(self.available_for_use_date) < getdate(self.purchase_date):
@@ -549,7 +553,7 @@ class Asset(AccountsController):
)
def validate_gross_and_purchase_amount(self):
- if self.is_existing_asset:
+ if self.asset_type == "Existing Asset":
return
if self.net_purchase_amount and self.net_purchase_amount != self.purchase_amount:
@@ -617,7 +621,7 @@ class Asset(AccountsController):
self.validate_depreciation_start_date(row)
self.validate_total_number_of_depreciations_and_frequency(row)
- if not self.is_existing_asset:
+ if self.asset_type != "Existing Asset":
self.opening_accumulated_depreciation = 0
self.opening_number_of_booked_depreciations = 0
else:
@@ -770,7 +774,7 @@ class Asset(AccountsController):
def get_status(self):
"""Returns status based on whether it is draft, submitted, scrapped or depreciated"""
if self.docstatus == 0:
- if self.is_composite_asset:
+ if self.asset_type == "Composite Asset":
status = "Work In Progress"
else:
status = "Draft"
@@ -843,7 +847,7 @@ class Asset(AccountsController):
return records
def validate_make_gl_entry(self):
- if self.is_composite_asset:
+ if self.asset_type == "Composite Asset":
return True
purchase_document = self.get_purchase_document()
@@ -924,7 +928,7 @@ class Asset(AccountsController):
purchase_document = self.get_purchase_document()
fixed_asset_account, cwip_account = self.get_fixed_asset_account(), self.get_cwip_account()
- if (self.is_composite_asset or (purchase_document and self.purchase_amount)) and getdate(
+ if (self.asset_type == "Composite Asset" or (purchase_document and self.purchase_amount)) and getdate(
self.available_for_use_date
) <= getdate():
gl_entries.append(
@@ -964,7 +968,7 @@ class Asset(AccountsController):
self.db_set("booked_fixed_asset", 1)
def check_asset_capitalization_gl_entries(self):
- if self.is_composite_asset:
+ if self.asset_type == "Composite Asset":
result = frappe.db.get_value(
"Asset Capitalization",
{"target_asset": self.name, "docstatus": 1},
@@ -1395,7 +1399,7 @@ def process_asset_split(existing_asset, split_qty, splitted_asset=None, is_new_a
def set_split_asset_values(asset_doc, scaling_factor, split_qty, existing_asset, is_new_asset):
asset_doc.net_purchase_amount = existing_asset.net_purchase_amount * scaling_factor
- asset_doc.purchase_amount = existing_asset.net_purchase_amount
+ asset_doc.purchase_amount = existing_asset.net_purchase_amount * scaling_factor
asset_doc.additional_asset_cost = existing_asset.additional_asset_cost * scaling_factor
asset_doc.total_asset_cost = asset_doc.net_purchase_amount + asset_doc.additional_asset_cost
asset_doc.opening_accumulated_depreciation = (
diff --git a/erpnext/assets/doctype/asset/depreciation.py b/erpnext/assets/doctype/asset/depreciation.py
index 1e0cfedfbb9..832e3736e7d 100644
--- a/erpnext/assets/doctype/asset/depreciation.py
+++ b/erpnext/assets/doctype/asset/depreciation.py
@@ -786,10 +786,14 @@ def get_disposal_account_and_cost_center(company):
@frappe.whitelist()
-def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_book=None):
+def get_value_after_depreciation_on_disposal_date(
+ asset: str,
+ disposal_date: str,
+ finance_book: str | None = None,
+) -> float:
asset_doc = frappe.get_doc("Asset", asset)
- if asset_doc.is_composite_component:
+ if asset_doc.asset_type == "Composite Component":
validate_disposal_date(asset_doc.purchase_date, getdate(disposal_date), "purchase")
return flt(asset_doc.value_after_depreciation)
diff --git a/erpnext/assets/doctype/asset/test_asset.py b/erpnext/assets/doctype/asset/test_asset.py
index 6733a7f89e3..6440fcfad62 100644
--- a/erpnext/assets/doctype/asset/test_asset.py
+++ b/erpnext/assets/doctype/asset/test_asset.py
@@ -71,16 +71,16 @@ class TestAsset(AssetSetup):
self.assertRaises(frappe.MandatoryError, asset.save)
def test_pr_or_pi_mandatory_if_not_existing_asset(self):
- """Tests if either PI or PR is present if CWIP is enabled and is_existing_asset=0."""
+ """Tests if either PI or PR is present if CWIP is enabled and asset_type == Existing Asset."""
asset = create_asset(item_code="Macbook Pro", do_not_save=1)
- asset.is_existing_asset = 0
+ asset.asset_type = ""
self.assertRaises(frappe.ValidationError, asset.save)
def test_available_for_use_date_is_after_purchase_date(self):
asset = create_asset(item_code="Macbook Pro", calculate_depreciation=1, do_not_save=1)
- asset.is_existing_asset = 0
+ asset.asset_type = ""
asset.purchase_date = getdate("2021-10-10")
asset.available_for_use_date = getdate("2021-10-1")
@@ -183,7 +183,7 @@ class TestAsset(AssetSetup):
asset.submit()
def test_is_fixed_asset_set(self):
- asset = create_asset(is_existing_asset=1)
+ asset = create_asset(asset_type="Existing Asset")
doc = frappe.new_doc("Purchase Invoice")
doc.company = "_Test Company"
doc.supplier = "_Test Supplier"
@@ -710,7 +710,7 @@ class TestAsset(AssetSetup):
# create an asset
asset = create_asset(
item_code="Macbook Pro",
- is_existing_asset=1,
+ asset_type="Existing Asset",
calculate_depreciation=1,
available_for_use_date=purchase_date,
purchase_date=purchase_date,
@@ -890,7 +890,7 @@ class TestDepreciationMethods(AssetSetup):
asset = create_asset(
calculate_depreciation=1,
available_for_use_date="2030-06-06",
- is_existing_asset=1,
+ asset_type="Existing Asset",
opening_number_of_booked_depreciations=2,
opening_accumulated_depreciation=47178.08,
expected_value_after_useful_life=10000,
@@ -939,7 +939,7 @@ class TestDepreciationMethods(AssetSetup):
asset = create_asset(
calculate_depreciation=1,
available_for_use_date="2030-01-01",
- is_existing_asset=1,
+ asset_type="Existing Asset",
depreciation_method="Double Declining Balance",
opening_number_of_booked_depreciations=1,
opening_accumulated_depreciation=50000,
@@ -1680,7 +1680,7 @@ class TestDepreciationBasics(AssetSetup):
self.assertEqual(asset.finance_books[0].value_after_depreciation, 100000.0)
def test_asset_cost_center(self):
- asset = create_asset(is_existing_asset=1, do_not_save=1)
+ asset = create_asset(asset_type="Existing Asset", do_not_save=1)
asset.cost_center = "Main - WP"
self.assertRaises(frappe.ValidationError, asset.submit)
@@ -1717,7 +1717,7 @@ class TestDepreciationBasics(AssetSetup):
def test_manual_depreciation_for_existing_asset(self):
asset = create_asset(
item_code="Macbook Pro",
- is_existing_asset=1,
+ asset_type="Existing Asset",
purchase_date="2020-01-30",
available_for_use_date="2020-01-30",
submit=1,
@@ -1843,7 +1843,7 @@ class TestDepreciationBasics(AssetSetup):
# Create composite asset
wip_composite_asset = create_asset(
asset_name="Asset Capitalization WIP Composite Asset for Split",
- is_composite_asset=1,
+ asset_type="Composite Asset",
warehouse="Stores - TCP1",
company=company,
asset_quantity=2, # Set quantity > 1 to allow splitting
@@ -1937,9 +1937,7 @@ def create_asset(**args):
"available_for_use_date": args.available_for_use_date or "2020-06-06",
"location": args.location or "Test Location",
"asset_owner": args.asset_owner or "Company",
- "is_existing_asset": args.is_existing_asset or 1,
- "is_composite_asset": args.is_composite_asset or 0,
- "is_composite_component": args.is_composite_component or 0,
+ "asset_type": args.asset_type or "Existing Asset",
"asset_quantity": args.get("asset_quantity") or 1,
"depr_entry_posting_status": args.depr_entry_posting_status or "",
}
@@ -1961,7 +1959,7 @@ def create_asset(**args):
},
)
- if asset.is_composite_asset:
+ if asset.asset_type == "Composite Asset":
asset.net_purchase_amount = 0
asset.purchase_amount = 0
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
index c7f17bc48a3..e3a80db6610 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.js
@@ -18,10 +18,7 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
this.show_general_ledger();
erpnext.toggle_serial_batch_fields(this.frm);
- 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.show_stock_ledger();
}
@@ -42,7 +39,7 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
me.frm.set_query("target_asset", function () {
return {
- filters: { is_composite_asset: 1, docstatus: 0 },
+ filters: { asset_type: "Composite Asset", docstatus: 0 },
};
});
@@ -241,10 +238,6 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
this.calculate_totals();
}
- target_qty() {
- this.calculate_totals();
- }
-
rate() {
this.calculate_totals();
}
@@ -486,10 +479,7 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
me.frm.doc.stock_items_total + me.frm.doc.asset_items_total + me.frm.doc.service_items_total;
me.frm.doc.total_value = flt(me.frm.doc.total_value, precision("total_value"));
- me.frm.doc.target_qty = flt(me.frm.doc.target_qty, precision("target_qty"));
- me.frm.doc.target_incoming_rate = me.frm.doc.target_qty
- ? me.frm.doc.total_value / flt(me.frm.doc.target_qty)
- : me.frm.doc.total_value;
+ me.frm.doc.target_incoming_rate = me.frm.doc.total_value;
me.frm.refresh_fields();
}
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json
index 57642e41472..0fc6b454051 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.json
@@ -9,30 +9,33 @@
"field_order": [
"title",
"naming_series",
+ "company",
"target_asset",
"target_asset_name",
- "target_item_code",
- "finance_book",
- "target_qty",
"column_break_9",
- "company",
+ "finance_book",
"posting_date",
"posting_time",
"set_posting_time",
- "target_batch_no",
- "target_serial_no",
+ "target_item_code",
"amended_from",
- "target_is_fixed_asset",
- "target_has_batch_no",
- "target_has_serial_no",
"section_break_16",
"stock_items",
+ "section_break_urtz",
+ "column_break_gqep",
+ "column_break_yvlx",
"stock_items_total",
"section_break_26",
"asset_items",
+ "section_break_arbh",
+ "column_break_boeu",
+ "column_break_qecy",
"asset_items_total",
"service_expenses_section",
"service_items",
+ "section_break_ptna",
+ "column_break_szvh",
+ "column_break_katv",
"service_items_total",
"totals_section",
"total_value",
@@ -55,20 +58,12 @@
"depends_on": "eval:(doc.target_item_code && !doc.__islocal)",
"fieldname": "target_item_code",
"fieldtype": "Link",
+ "hidden": 1,
"in_standard_filter": 1,
"label": "Target Item Code",
"options": "Item",
"read_only": 1
},
- {
- "default": "0",
- "fetch_from": "target_item_code.is_fixed_asset",
- "fieldname": "target_is_fixed_asset",
- "fieldtype": "Check",
- "hidden": 1,
- "label": "Target Is Fixed Asset",
- "read_only": 1
- },
{
"fieldname": "target_asset",
"fieldtype": "Link",
@@ -143,6 +138,7 @@
"depends_on": "eval:doc.docstatus == 0 || (doc.stock_items && doc.stock_items.length)",
"fieldname": "section_break_16",
"fieldtype": "Section Break",
+ "hide_border": 1,
"label": "Consumed Stock Items"
},
{
@@ -151,49 +147,11 @@
"label": "Stock Items",
"options": "Asset Capitalization Stock Item"
},
- {
- "depends_on": "target_has_batch_no",
- "fieldname": "target_batch_no",
- "fieldtype": "Link",
- "label": "Target Batch No",
- "options": "Batch"
- },
- {
- "default": "1",
- "fieldname": "target_qty",
- "fieldtype": "Float",
- "hidden": 1,
- "label": "Target Qty",
- "read_only": 1
- },
- {
- "default": "0",
- "fetch_from": "target_item_code.has_batch_no",
- "fieldname": "target_has_batch_no",
- "fieldtype": "Check",
- "hidden": 1,
- "label": "Target Has Batch No",
- "read_only": 1
- },
- {
- "default": "0",
- "fetch_from": "target_item_code.has_serial_no",
- "fieldname": "target_has_serial_no",
- "fieldtype": "Check",
- "hidden": 1,
- "label": "Target Has Serial No",
- "read_only": 1
- },
- {
- "depends_on": "target_has_serial_no",
- "fieldname": "target_serial_no",
- "fieldtype": "Small Text",
- "label": "Target Serial No"
- },
{
"depends_on": "eval:doc.docstatus == 0 || (doc.asset_items && doc.asset_items.length)",
"fieldname": "section_break_26",
"fieldtype": "Section Break",
+ "hide_border": 1,
"label": "Consumed Assets"
},
{
@@ -203,6 +161,7 @@
"options": "Asset Capitalization Asset Item"
},
{
+ "depends_on": "eval: doc.stock_items_total",
"fieldname": "stock_items_total",
"fieldtype": "Currency",
"label": "Consumed Stock Total Value",
@@ -210,6 +169,7 @@
"read_only": 1
},
{
+ "depends_on": "eval: doc.asset_items_total",
"fieldname": "asset_items_total",
"fieldtype": "Currency",
"label": "Consumed Asset Total Value",
@@ -226,6 +186,7 @@
"depends_on": "eval:doc.docstatus == 0 || (doc.service_items && doc.service_items.length)",
"fieldname": "service_expenses_section",
"fieldtype": "Section Break",
+ "hide_border": 1,
"label": "Service Expenses"
},
{
@@ -235,6 +196,7 @@
"options": "Asset Capitalization Service Item"
},
{
+ "depends_on": "eval: doc.service_items_total",
"fieldname": "service_items_total",
"fieldtype": "Currency",
"label": "Service Expense Total Amount",
@@ -277,10 +239,10 @@
"options": "Cost Center"
},
{
- "fieldname": "project",
- "fieldtype": "Link",
- "label": "Project",
- "options": "Project"
+ "fieldname": "project",
+ "fieldtype": "Link",
+ "label": "Project",
+ "options": "Project"
},
{
"fieldname": "dimension_col_break",
@@ -292,12 +254,48 @@
"label": "Target Fixed Asset Account",
"options": "Account",
"read_only": 1
+ },
+ {
+ "fieldname": "section_break_urtz",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "column_break_gqep",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "column_break_yvlx",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_arbh",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "column_break_boeu",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "column_break_qecy",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "section_break_ptna",
+ "fieldtype": "Section Break"
+ },
+ {
+ "fieldname": "column_break_szvh",
+ "fieldtype": "Column Break"
+ },
+ {
+ "fieldname": "column_break_katv",
+ "fieldtype": "Column Break"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2025-05-20 15:15:12.110035",
+ "modified": "2026-02-06 01:52:41.890713",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Capitalization",
diff --git a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
index 7b9369d7390..0894bad2d3d 100644
--- a/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/asset_capitalization.py
@@ -39,9 +39,6 @@ force_fields = [
"target_asset_name",
"item_name",
"asset_name",
- "target_is_fixed_asset",
- "target_has_serial_no",
- "target_has_batch_no",
"stock_uom",
"fixed_asset_account",
"valuation_rate",
@@ -76,6 +73,7 @@ class AssetCapitalization(StockController):
naming_series: DF.Literal["ACC-ASC-.YYYY.-"]
posting_date: DF.Date
posting_time: DF.Time
+ project: DF.Link | None
service_items: DF.Table[AssetCapitalizationServiceItem]
service_items_total: DF.Currency
set_posting_time: DF.Check
@@ -83,15 +81,9 @@ class AssetCapitalization(StockController):
stock_items_total: DF.Currency
target_asset: DF.Link | None
target_asset_name: DF.Data | None
- target_batch_no: DF.Link | None
target_fixed_asset_account: DF.Link | None
- target_has_batch_no: DF.Check
- target_has_serial_no: DF.Check
target_incoming_rate: DF.Currency
- target_is_fixed_asset: DF.Check
target_item_code: DF.Link | None
- target_qty: DF.Float
- target_serial_no: DF.SmallText | None
title: DF.Data | None
total_value: DF.Currency
# end: auto-generated types
@@ -190,22 +182,13 @@ class AssetCapitalization(StockController):
if not target_item.is_fixed_asset:
frappe.throw(_("Target Item {0} must be a Fixed Asset item").format(target_item.name))
- if target_item.is_fixed_asset:
- self.target_qty = 1
- if flt(self.target_qty) <= 0:
- frappe.throw(_("Target Qty must be a positive number"))
- if not target_item.has_batch_no:
- self.target_batch_no = None
- if not target_item.has_serial_no:
- self.target_serial_no = ""
-
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 not target_asset.is_composite_asset:
+ if not target_asset.asset_type == "Composite Asset":
frappe.throw(_("Target Asset {0} needs to be composite asset").format(target_asset.name))
if target_asset.item_code != self.target_item_code:
@@ -314,7 +297,7 @@ class AssetCapitalization(StockController):
return frappe.db.get_value(
"Asset",
asset,
- ["name", "item_code", "company", "status", "docstatus", "is_composite_asset"],
+ ["name", "item_code", "company", "status", "docstatus", "asset_type"],
as_dict=1,
)
@@ -380,8 +363,7 @@ class AssetCapitalization(StockController):
self.total_value = self.stock_items_total + self.asset_items_total + self.service_items_total
self.total_value = flt(self.total_value, self.precision("total_value"))
- self.target_qty = flt(self.target_qty, self.precision("target_qty"))
- self.target_incoming_rate = self.total_value / self.target_qty
+ self.target_incoming_rate = self.total_value
def update_stock_ledger(self):
sl_entries = []
@@ -489,7 +471,7 @@ class AssetCapitalization(StockController):
for item in self.asset_items:
asset = frappe.get_doc("Asset", item.asset)
- if not asset.is_composite_component:
+ if asset.asset_type != "Composite Component":
if asset.calculate_depreciation:
notes = _(
"This schedule was created when Asset {0} was consumed through Asset Capitalization {1}."
@@ -542,30 +524,29 @@ class AssetCapitalization(StockController):
def get_composite_component_value(self):
composite_component_value = 0
for item in self.asset_items:
- asset = frappe.db.get_value("Asset", item.asset, ["is_composite_component"], as_dict=True)
- if asset and asset.is_composite_component:
+ asset = frappe.db.get_value("Asset", item.asset, ["asset_type"], as_dict=True)
+ if asset and asset.asset_type == "Composite Component":
composite_component_value += flt(item.asset_value, item.precision("asset_value"))
return composite_component_value
def get_gl_entries_for_target_item(
self, gl_entries, target_account, target_against, precision, composite_component_value
):
- if self.target_is_fixed_asset:
- total_value = flt(self.total_value - composite_component_value, precision)
- if total_value:
- # Capitalization
- gl_entries.append(
- self.get_gl_dict(
- {
- "account": target_account,
- "against": ", ".join(target_against),
- "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
- "debit": total_value,
- "cost_center": self.get("cost_center"),
- },
- item=self,
- )
+ total_value = flt(self.total_value - composite_component_value, precision)
+ if total_value:
+ # Capitalization
+ gl_entries.append(
+ self.get_gl_dict(
+ {
+ "account": target_account,
+ "against": ", ".join(target_against),
+ "remarks": self.get("remarks") or _("Accounting Entry for Asset"),
+ "debit": total_value,
+ "cost_center": self.get("cost_center"),
+ },
+ item=self,
)
+ )
def update_target_asset(self):
total_target_asset_value = flt(self.total_value, self.precision("total_value"))
@@ -611,14 +592,13 @@ class AssetCapitalization(StockController):
def set_consumed_asset_status(self, asset):
if self.docstatus == 1:
- if self.target_is_fixed_asset:
- asset.set_status("Capitalized")
- add_asset_activity(
- asset.name,
- _("Asset capitalized after Asset Capitalization {0} was submitted").format(
- get_link_to_form("Asset Capitalization", self.name)
- ),
- )
+ asset.set_status("Capitalized")
+ add_asset_activity(
+ asset.name,
+ _("Asset capitalized after Asset Capitalization {0} was submitted").format(
+ get_link_to_form("Asset Capitalization", self.name)
+ ),
+ )
else:
asset.set_status()
add_asset_activity(
@@ -630,7 +610,7 @@ class AssetCapitalization(StockController):
@frappe.whitelist()
-def get_target_item_details(item_code=None, company=None):
+def get_target_item_details(item_code: str | None = None, company: str | None = None) -> frappe._dict:
out = frappe._dict()
# Get Item Details
@@ -640,17 +620,6 @@ def get_target_item_details(item_code=None, company=None):
# Set Item Details
out.target_item_name = item.item_name
- out.target_is_fixed_asset = cint(item.is_fixed_asset)
- out.target_has_batch_no = cint(item.has_batch_no)
- out.target_has_serial_no = cint(item.has_serial_no)
-
- if out.target_is_fixed_asset:
- out.target_qty = 1
-
- if not out.target_has_batch_no:
- out.target_batch_no = None
- if not out.target_has_serial_no:
- out.target_serial_no = ""
# Cost Center
item_defaults = get_item_defaults(item.name, company)
@@ -667,7 +636,7 @@ def get_target_item_details(item_code=None, company=None):
@frappe.whitelist()
-def get_target_asset_details(asset=None, company=None):
+def get_target_asset_details(asset: str | None = None, company: str | None = None) -> frappe._dict:
out = frappe._dict()
# Get Asset Details
diff --git a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
index c87fff0b73e..914b87b728f 100644
--- a/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
+++ b/erpnext/assets/doctype/asset_capitalization/test_asset_capitalization.py
@@ -10,12 +10,14 @@ from erpnext.assets.doctype.asset.depreciation import post_depreciation_entries
from erpnext.assets.doctype.asset.test_asset import (
create_asset,
create_asset_data,
+ create_fixed_asset_item,
set_depreciation_settings_in_company,
)
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
get_asset_depr_schedule_doc,
)
from erpnext.stock.doctype.item.test_item import create_item
+from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle import (
make_serial_batch_bundle,
)
@@ -61,7 +63,7 @@ class TestAssetCapitalization(IntegrationTestCase):
wip_composite_asset = create_asset(
asset_name="Asset Capitalization WIP Composite Asset",
- is_composite_asset=1,
+ asset_type="Composite Asset",
warehouse="Stores - TCP1",
company=company,
)
@@ -81,7 +83,6 @@ class TestAssetCapitalization(IntegrationTestCase):
)
# Test Asset Capitalization values
- self.assertEqual(asset_capitalization.target_qty, 1)
self.assertEqual(asset_capitalization.stock_items[0].valuation_rate, stock_rate)
self.assertEqual(asset_capitalization.stock_items[0].amount, stock_amount)
@@ -156,7 +157,7 @@ class TestAssetCapitalization(IntegrationTestCase):
wip_composite_asset = create_asset(
asset_name="Asset Capitalization WIP Composite Asset",
- is_composite_asset=1,
+ asset_type="Composite Asset",
warehouse="Stores - TCP1",
company=company,
)
@@ -176,8 +177,6 @@ class TestAssetCapitalization(IntegrationTestCase):
)
# Test Asset Capitalization values
- self.assertEqual(asset_capitalization.target_qty, 1)
-
self.assertEqual(asset_capitalization.stock_items[0].valuation_rate, stock_rate)
self.assertEqual(asset_capitalization.stock_items[0].amount, stock_amount)
self.assertEqual(asset_capitalization.stock_items_total, stock_amount)
@@ -245,7 +244,7 @@ class TestAssetCapitalization(IntegrationTestCase):
wip_composite_asset = create_asset(
asset_name="Asset Capitalization WIP Composite Asset",
- is_composite_asset=1,
+ asset_type="Composite Asset",
warehouse="Stores - TCP1",
company=company,
)
@@ -262,8 +261,6 @@ class TestAssetCapitalization(IntegrationTestCase):
)
# Test Asset Capitalization values
- self.assertEqual(asset_capitalization.target_qty, 1)
-
self.assertEqual(asset_capitalization.stock_items[0].valuation_rate, stock_rate)
self.assertEqual(asset_capitalization.stock_items[0].amount, stock_amount)
self.assertEqual(asset_capitalization.stock_items_total, stock_amount)
@@ -313,7 +310,7 @@ class TestAssetCapitalization(IntegrationTestCase):
wip_composite_asset = create_asset(
asset_name="Asset Capitalization WIP Composite Asset",
- is_composite_asset=1,
+ asset_type="Composite Asset",
warehouse="Stores - TCP1",
company=company,
)
@@ -361,33 +358,45 @@ class TestAssetCapitalization(IntegrationTestCase):
wip_composite_asset = create_asset(
asset_name="Asset Capitalization WIP Composite Asset",
- is_composite_asset=1,
+ asset_type="Composite Asset",
warehouse="Stores - TCP1",
company=company,
)
consumed_asset_value = 100000
- consumed_asset = create_asset(
- asset_name="Asset Capitalization Consumable Asset",
- asset_value=consumed_asset_value,
- submit=1,
- warehouse="Stores - _TC",
- is_composite_component=1,
+ item = create_fixed_asset_item("Asset Capitalization Consumable Asset")
+
+ pr = make_purchase_receipt(
+ item_code=item.item_code,
+ qty=1,
+ rate=consumed_asset_value,
company=company,
+ warehouse="Stores - TCP1",
)
+ consumed_asset_name = frappe.db.get_value("Asset", {"purchase_receipt": pr.name}, "name")
+ consumed_asset_doc = frappe.get_doc("Asset", consumed_asset_name)
+
+ consumed_asset_doc.update(
+ {
+ "asset_type": "Composite Component",
+ "purchase_date": pr.posting_date,
+ "available_for_use_date": pr.posting_date,
+ }
+ )
+ consumed_asset_doc.save()
+ consumed_asset_doc.submit()
# Create and submit Asset Captitalization
asset_capitalization = create_asset_capitalization(
target_asset=wip_composite_asset.name,
target_asset_location="Test Location",
- consumed_asset=consumed_asset.name,
+ consumed_asset=consumed_asset_doc.name,
company=company,
submit=1,
)
# Test Asset Capitalization values
- self.assertEqual(asset_capitalization.target_qty, 1)
self.assertEqual(asset_capitalization.asset_items[0].asset_value, consumed_asset_value)
actual_gle = get_actual_gle_dict(asset_capitalization.name)
@@ -421,9 +430,6 @@ def create_asset_capitalization(**args):
"target_item_code": target_item_code,
"target_asset": target_asset.name,
"target_asset_location": "Test Location",
- "target_qty": flt(args.target_qty) or 1,
- "target_batch_no": args.target_batch_no,
- "target_serial_no": args.target_serial_no,
"finance_book": args.finance_book,
}
)
@@ -516,7 +522,7 @@ def create_depreciation_asset(**args):
args = frappe._dict(args)
asset = frappe.new_doc("Asset")
- asset.is_existing_asset = 1
+ asset.asset_type = args.asset_type or "Existing Asset"
asset.calculate_depreciation = 1
asset.asset_owner = "Company"
diff --git a/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py b/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py
index 2cca15a89f7..824c7cbba1f 100644
--- a/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py
+++ b/erpnext/assets/doctype/asset_depreciation_schedule/test_asset_depreciation_schedule.py
@@ -87,7 +87,7 @@ class TestAssetDepreciationSchedule(IntegrationTestCase):
calculate_depreciation=1,
depreciation_method="Straight Line",
available_for_use_date="2023-10-10",
- is_existing_asset=1,
+ asset_type="Existing Asset",
opening_number_of_booked_depreciations=9,
opening_accumulated_depreciation=265,
depreciation_start_date="2024-07-31",
@@ -127,7 +127,7 @@ class TestAssetDepreciationSchedule(IntegrationTestCase):
calculate_depreciation=1,
depreciation_method="Straight Line",
available_for_use_date="2023-10-10",
- is_existing_asset=1,
+ asset_type="Existing Asset",
opening_number_of_booked_depreciations=9,
opening_accumulated_depreciation=265.30,
depreciation_start_date="2024-07-31",
@@ -165,7 +165,7 @@ class TestAssetDepreciationSchedule(IntegrationTestCase):
calculate_depreciation=1,
depreciation_method="Straight Line",
available_for_use_date="2023-11-01",
- is_existing_asset=1,
+ asset_type="Existing Asset",
opening_number_of_booked_depreciations=4,
opening_accumulated_depreciation=223.15,
depreciation_start_date="2024-12-31",
@@ -529,7 +529,7 @@ class TestAssetDepreciationSchedule(IntegrationTestCase):
depreciation_start_date="2023-03-31",
frequency_of_depreciation=1,
total_number_of_depreciations=12,
- is_existing_asset=1,
+ asset_type="Existing Asset",
opening_accumulated_depreciation=64.52,
opening_number_of_booked_depreciations=2,
submit=1,
@@ -851,7 +851,7 @@ class TestAssetDepreciationSchedule(IntegrationTestCase):
depreciation_start_date="2023-03-31",
frequency_of_depreciation=1,
total_number_of_depreciations=12,
- is_existing_asset=1,
+ asset_type="Existing Asset",
opening_accumulated_depreciation=64.52,
opening_number_of_booked_depreciations=2,
submit=1,
@@ -925,7 +925,7 @@ class TestAssetDepreciationSchedule(IntegrationTestCase):
depreciation_start_date="2021-12-31",
frequency_of_depreciation=12,
total_number_of_depreciations=3,
- is_existing_asset=1,
+ asset_type="Existing Asset",
submit=1,
)
post_depreciation_entries(date="2021-12-31")
@@ -1014,7 +1014,7 @@ class TestAssetDepreciationSchedule(IntegrationTestCase):
depreciation_start_date="2021-12-31",
frequency_of_depreciation=12,
total_number_of_depreciations=3,
- is_existing_asset=1,
+ asset_type="Existing Asset",
submit=1,
)
post_depreciation_entries(date="2021-12-31")
@@ -1093,7 +1093,7 @@ class TestAssetDepreciationSchedule(IntegrationTestCase):
rate_of_depreciation=50,
frequency_of_depreciation=12,
total_number_of_depreciations=3,
- is_existing_asset=1,
+ asset_type="Existing Asset",
submit=1,
)
post_depreciation_entries(date="2021-12-31")
diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.json b/erpnext/assets/doctype/asset_repair/asset_repair.json
index b840b5a56b3..71b9469cfbd 100644
--- a/erpnext/assets/doctype/asset_repair/asset_repair.json
+++ b/erpnext/assets/doctype/asset_repair/asset_repair.json
@@ -9,9 +9,9 @@
"engine": "InnoDB",
"field_order": [
"naming_series",
+ "company",
"asset",
"asset_name",
- "company",
"column_break_2",
"repair_status",
"failure_date",
@@ -28,10 +28,6 @@
"column_break_ajbh",
"column_break_hkem",
"repair_cost",
- "accounting_dimensions_section",
- "cost_center",
- "column_break_14",
- "project",
"stock_consumption_details_section",
"stock_items",
"section_break_ltbb",
@@ -43,7 +39,12 @@
"capitalize_repair_cost",
"increase_in_asset_life",
"column_break_xebe",
- "total_repair_cost"
+ "total_repair_cost",
+ "accounting_dimensions_section",
+ "cost_center",
+ "column_break_14",
+ "project",
+ "connection_tab"
],
"fields": [
{
@@ -149,8 +150,7 @@
{
"fieldname": "accounting_details",
"fieldtype": "Section Break",
- "hide_border": 1,
- "label": "Repair Purchase Invoices"
+ "hide_border": 1
},
{
"fieldname": "stock_items",
@@ -206,6 +206,7 @@
{
"fieldname": "invoices",
"fieldtype": "Table",
+ "label": "Repair Purchase Invoices",
"mandatory_depends_on": "eval: doc.repair_status == 'Completed' && doc.repair_cost > 0;",
"no_copy": 1,
"options": "Asset Repair Purchase Invoice"
@@ -244,6 +245,7 @@
"fieldtype": "Column Break"
},
{
+ "depends_on": "eval: doc.consumed_items_cost",
"fieldname": "consumed_items_cost",
"fieldtype": "Currency",
"label": "Consumed Items Cost"
@@ -256,7 +258,13 @@
"depends_on": "capitalize_repair_cost",
"fieldname": "accounting_dimensions_section",
"fieldtype": "Section Break",
- "label": "Accounting Dimensions"
+ "label": "Accounting Dimension"
+ },
+ {
+ "fieldname": "connection_tab",
+ "fieldtype": "Tab Break",
+ "label": "Connection",
+ "show_dashboard": 1
}
],
"index_web_pages_for_search": 1,
@@ -267,7 +275,7 @@
"link_fieldname": "asset_repair"
}
],
- "modified": "2026-01-06 15:48:13.862505",
+ "modified": "2026-02-06 14:57:54.257572",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Repair",
diff --git a/erpnext/assets/doctype/asset_repair/test_asset_repair.py b/erpnext/assets/doctype/asset_repair/test_asset_repair.py
index d085a4c6e4b..c56622d6665 100644
--- a/erpnext/assets/doctype/asset_repair/test_asset_repair.py
+++ b/erpnext/assets/doctype/asset_repair/test_asset_repair.py
@@ -360,7 +360,7 @@ class TestAssetRepair(IntegrationTestCase):
self.assertEqual(stock_entry.asset_repair, asset_repair.name)
def test_gl_entries_with_capitalized_asset_repair(self):
- asset = create_asset(is_existing_asset=1, calculate_depreciation=1, submit=1)
+ asset = create_asset(asset_type="Existing Asset", calculate_depreciation=1, submit=1)
asset_repair = create_asset_repair(
asset=asset, capitalize_repair_cost=1, item="_Test Non Stock Item", submit=1
)
@@ -400,7 +400,7 @@ def create_asset_repair(**args):
if args.asset:
asset = args.asset
else:
- asset = create_asset(is_existing_asset=1, submit=1, company=args.company)
+ asset = create_asset(asset_type=args.asset_type or "Existing Asset", submit=1, company=args.company)
asset_repair = frappe.new_doc("Asset Repair")
asset_repair.update(
{
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 2103379df93..44bf59fc3ea 100644
--- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
+++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py
@@ -144,7 +144,7 @@ def get_conditions(filters):
conditions[date_field] = ["between", [filters.year_start_date, filters.year_end_date]]
if filters.get("only_existing_assets"):
- conditions["is_existing_asset"] = filters.get("only_existing_assets")
+ conditions["asset_type"] = "Existing Asset"
if filters.get("asset_category"):
conditions["asset_category"] = filters.get("asset_category")
if filters.get("cost_center"):
@@ -274,7 +274,7 @@ def get_asset_depreciation_amount_map(filters, finance_book):
)
if filters.only_existing_assets:
- query = query.where(asset.is_existing_asset == 1)
+ query = query.where(asset.asset_type == "Existing Asset")
if filters.asset_category:
query = query.where(asset.asset_category == filters.asset_category)
if filters.cost_center:
@@ -325,7 +325,7 @@ def get_asset_value_adjustment_map(filters, finance_book):
)
if filters.only_existing_assets:
- query = query.where(asset.is_existing_asset == 1)
+ query = query.where(asset.asset_type == "Existing Asset")
if filters.asset_category:
query = query.where(asset.asset_category == filters.asset_category)
if filters.cost_center:
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index dfff6af431a..f032876824f 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -468,5 +468,6 @@ erpnext.patches.v15_0.replace_http_with_https_in_sales_partner
erpnext.patches.v15_0.delete_quotation_lost_record_detail
erpnext.patches.v16_0.add_portal_redirects
erpnext.patches.v16_0.complete_onboarding_steps_for_older_sites #2
+erpnext.patches.v16_0.migrate_asset_type_checkboxes_to_select
erpnext.patches.v16_0.update_order_qty_and_requested_qty_based_on_mr_and_po
erpnext.patches.v16_0.enable_serial_batch_setting
diff --git a/erpnext/patches/v16_0/migrate_asset_type_checkboxes_to_select.py b/erpnext/patches/v16_0/migrate_asset_type_checkboxes_to_select.py
new file mode 100644
index 00000000000..11f341ce65a
--- /dev/null
+++ b/erpnext/patches/v16_0/migrate_asset_type_checkboxes_to_select.py
@@ -0,0 +1,25 @@
+import frappe
+from frappe.query_builder import Case
+
+
+def execute():
+ required_columns = [
+ "is_existing_asset",
+ "is_composite_asset",
+ "is_composite_component",
+ ]
+
+ # Skip patch if any required column is missing
+ if not all(frappe.db.has_column("Asset", col) for col in required_columns):
+ return
+
+ Asset = frappe.qb.DocType("Asset")
+
+ frappe.qb.update(Asset).set(
+ Asset.asset_type,
+ Case()
+ .when(Asset.is_existing_asset == 1, "Existing Asset")
+ .when(Asset.is_composite_asset == 1, "Composite Asset")
+ .when(Asset.is_composite_component == 1, "Composite Component")
+ .else_(""),
+ ).run()