feat: composite WIP asset (#37352)

feat: wip composite asset
This commit is contained in:
Anand Baburajan
2023-10-04 10:29:14 +05:30
committed by GitHub
parent 643bb0511c
commit 0ecd7d2bf5
12 changed files with 406 additions and 54 deletions

View File

@@ -460,6 +460,12 @@ cur_frm.set_query("expense_account", "items", function(doc) {
}
});
cur_frm.set_query("wip_composite_asset", "items", function() {
return {
filters: {'is_composite_asset': 1, 'docstatus': 0 }
}
});
cur_frm.cscript.expense_account = function(doc, cdt, cdn){
var d = locals[cdt][cdn];
if(d.idx == 1 && d.expense_account){

View File

@@ -75,6 +75,7 @@
"manufacturer_part_no",
"accounting",
"expense_account",
"wip_composite_asset",
"col_break5",
"is_fixed_asset",
"asset_location",
@@ -877,12 +878,18 @@
"fieldname": "apply_tds",
"fieldtype": "Check",
"label": "Apply TDS"
},
{
"fieldname": "wip_composite_asset",
"fieldtype": "Link",
"label": "WIP Composite Asset",
"options": "Asset"
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-07-04 17:22:21.501152",
"modified": "2023-10-03 21:01:01.824892",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Purchase Invoice Item",
@@ -892,4 +899,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -147,6 +147,15 @@ 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 && !frm.doc.capitalized_in) {
$('.primary-action').prop('hidden', true);
$('.form-message').text('Capitalize this asset to confirm');
frm.add_custom_button(__("Capitalize Asset"), function() {
frm.trigger("create_asset_capitalization");
});
}
}
},
@@ -168,7 +177,7 @@ frappe.ui.form.on('Asset', {
frm.set_df_property('purchase_invoice', 'read_only', 1);
frm.set_df_property('purchase_receipt', 'read_only', 1);
}
else if (frm.doc.is_existing_asset) {
else if (frm.doc.is_existing_asset || frm.doc.is_composite_asset) {
frm.toggle_reqd('purchase_receipt', 0);
frm.toggle_reqd('purchase_invoice', 0);
}
@@ -300,7 +309,17 @@ frappe.ui.form.on('Asset', {
is_existing_asset: function(frm) {
frm.trigger("toggle_reference_doc");
// frm.toggle_reqd("next_depreciation_date", (!frm.doc.is_existing_asset && frm.doc.calculate_depreciation));
},
is_composite_asset: function(frm) {
if(frm.doc.is_composite_asset) {
frm.set_value('gross_purchase_amount', 0);
frm.set_df_property('gross_purchase_amount', 'read_only', 1);
} else {
frm.set_df_property('gross_purchase_amount', 'read_only', 0);
}
frm.trigger("toggle_reference_doc");
},
make_schedules_editable: function(frm) {
@@ -361,6 +380,19 @@ frappe.ui.form.on('Asset', {
});
},
create_asset_capitalization: function(frm) {
frappe.call({
args: {
"asset": frm.doc.name,
},
method: "erpnext.assets.doctype.asset.asset.create_asset_capitalization",
callback: function(r) {
var doclist = frappe.model.sync(r.message);
frappe.set_route("Form", doclist[0].doctype, doclist[0].name);
}
});
},
split_asset: function(frm) {
const title = __('Split Asset');
@@ -424,9 +456,11 @@ frappe.ui.form.on('Asset', {
},
gross_purchase_amount: function(frm) {
frm.doc.finance_books.forEach(d => {
frm.events.set_depreciation_rate(frm, d);
})
if (frm.doc.finance_books) {
frm.doc.finance_books.forEach(d => {
frm.events.set_depreciation_rate(frm, d);
})
}
},
purchase_receipt: (frm) => {

View File

@@ -14,6 +14,7 @@
"asset_owner",
"asset_owner_company",
"is_existing_asset",
"is_composite_asset",
"supplier",
"customer",
"image",
@@ -72,7 +73,8 @@
"purchase_receipt_amount",
"default_finance_book",
"depr_entry_posting_status",
"amended_from"
"amended_from",
"capitalized_in"
],
"fields": [
{
@@ -199,7 +201,7 @@
"fieldtype": "Date",
"label": "Purchase Date",
"read_only": 1,
"read_only_depends_on": "eval:!doc.is_existing_asset",
"read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset",
"reqd": 1
},
{
@@ -237,10 +239,12 @@
"default": "0",
"fieldname": "calculate_depreciation",
"fieldtype": "Check",
"label": "Calculate Depreciation"
"label": "Calculate Depreciation",
"read_only_depends_on": "eval:doc.is_composite_asset && !doc.gross_purchase_amount"
},
{
"default": "0",
"depends_on": "eval:!doc.is_composite_asset",
"fieldname": "is_existing_asset",
"fieldtype": "Check",
"label": "Is Existing Asset"
@@ -492,7 +496,7 @@
"fieldname": "asset_quantity",
"fieldtype": "Int",
"label": "Asset Quantity",
"read_only_depends_on": "eval:!doc.is_existing_asset"
"read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset"
},
{
"fieldname": "depr_entry_posting_status",
@@ -510,6 +514,21 @@
"fieldname": "is_fully_depreciated",
"fieldtype": "Check",
"label": "Is Fully Depreciated"
},
{
"default": "0",
"depends_on": "eval:!doc.is_existing_asset",
"fieldname": "is_composite_asset",
"fieldtype": "Check",
"label": "Is Composite Asset"
},
{
"fieldname": "capitalized_in",
"fieldtype": "Link",
"hidden": 1,
"label": "Capitalized In",
"options": "Asset Capitalization",
"read_only": 1
}
],
"idx": 72,
@@ -538,7 +557,7 @@
"table_fieldname": "accounts"
}
],
"modified": "2023-08-10 20:25:09.913073",
"modified": "2023-10-03 23:28:26.732269",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset",

View File

@@ -234,7 +234,7 @@ 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.gross_purchase_amount):
if not flt(self.gross_purchase_amount) and not self.is_composite_asset:
frappe.throw(_("Gross Purchase Amount is mandatory"), frappe.MandatoryError)
if is_cwip_accounting_enabled(self.asset_category):
@@ -1166,6 +1166,15 @@ def create_asset_repair(asset, asset_name):
return asset_repair
@frappe.whitelist()
def create_asset_capitalization(asset):
asset_capitalization = frappe.new_doc("Asset Capitalization")
asset_capitalization.update(
{"target_asset": asset, "capitalization_method": "Choose a WIP composite asset"}
)
return asset_capitalization
@frappe.whitelist()
def create_asset_value_adjustment(asset, asset_category, company):
asset_value_adjustment = frappe.new_doc("Asset Value Adjustment")

View File

@@ -1686,6 +1686,7 @@ def create_asset(**args):
"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,
"asset_quantity": args.get("asset_quantity") or 1,
"depr_entry_posting_status": args.depr_entry_posting_status or "",
}

View File

@@ -15,9 +15,15 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
refresh() {
this.show_general_ledger();
if ((this.frm.doc.stock_items && this.frm.doc.stock_items.length) || !this.frm.doc.target_is_fixed_asset) {
this.show_stock_ledger();
}
if (this.frm.doc.stock_items && !this.frm.doc.stock_items.length && this.frm.doc.target_asset && this.frm.doc.capitalization_method === "Choose a WIP composite asset") {
this.set_consumed_stock_items_tagged_to_wip_composite_asset(this.frm.doc.target_asset);
this.get_target_asset_details();
}
}
setup_queries() {
@@ -34,18 +40,9 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
});
me.frm.set_query("target_asset", function() {
var filters = {};
if (me.frm.doc.target_item_code) {
filters['item_code'] = me.frm.doc.target_item_code;
}
filters['status'] = ["not in", ["Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"]];
filters['docstatus'] = 1;
return {
filters: filters
};
filters: {'is_composite_asset': 1, 'docstatus': 0 }
}
});
me.frm.set_query("asset", "asset_items", function() {
@@ -104,6 +101,39 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
return this.get_target_item_details();
}
target_asset() {
if (this.frm.doc.target_asset && this.frm.doc.capitalization_method === "Choose a WIP composite asset") {
this.set_consumed_stock_items_tagged_to_wip_composite_asset(this.frm.doc.target_asset);
this.get_target_asset_details();
}
}
set_consumed_stock_items_tagged_to_wip_composite_asset(asset) {
var me = this;
if (asset) {
return me.frm.call({
method: "erpnext.assets.doctype.asset_capitalization.asset_capitalization.get_items_tagged_to_wip_composite_asset",
args: {
asset: asset,
},
callback: function (r) {
if (!r.exc && r.message) {
me.frm.clear_table("stock_items");
for (let item of r.message) {
me.frm.add_child("stock_items", item);
}
refresh_field("stock_items");
me.calculate_totals();
}
}
});
}
}
item_code(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
if (cdt === "Asset Capitalization Stock Item") {
@@ -218,6 +248,26 @@ 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) {
var me = this;

View File

@@ -8,24 +8,25 @@
"engine": "InnoDB",
"field_order": [
"title",
"company",
"naming_series",
"entry_type",
"target_item_code",
"target_asset",
"target_item_name",
"target_is_fixed_asset",
"target_has_batch_no",
"target_has_serial_no",
"column_break_9",
"target_asset_name",
"capitalization_method",
"target_item_code",
"target_asset_location",
"target_asset",
"target_asset_name",
"target_warehouse",
"target_qty",
"target_stock_uom",
"target_batch_no",
"target_serial_no",
"column_break_5",
"company",
"finance_book",
"posting_date",
"posting_time",
@@ -57,12 +58,13 @@
"label": "Title"
},
{
"depends_on": "eval:(doc.target_item_code && !doc.__islocal && doc.capitalization_method !== 'Choose a WIP composite asset') || ((doc.entry_type=='Capitalization' && doc.capitalization_method=='Create a new composite asset') || doc.entry_type=='Decapitalization')",
"fieldname": "target_item_code",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Target Item Code",
"options": "Item",
"reqd": 1
"mandatory_depends_on": "eval:(doc.entry_type=='Capitalization' && doc.capitalization_method=='Create a new composite asset') || doc.entry_type=='Decapitalization'",
"options": "Item"
},
{
"depends_on": "eval:doc.target_item_code && doc.target_item_name != doc.target_item_code",
@@ -86,16 +88,18 @@
"fieldtype": "Column Break"
},
{
"depends_on": "eval:(doc.target_asset && !doc.__islocal) || (doc.entry_type=='Capitalization' && doc.capitalization_method=='Choose a WIP composite asset')",
"fieldname": "target_asset",
"fieldtype": "Link",
"in_standard_filter": 1,
"label": "Target Asset",
"mandatory_depends_on": "eval:doc.entry_type=='Capitalization' && doc.capitalization_method=='Choose a WIP composite asset'",
"no_copy": 1,
"options": "Asset",
"read_only": 1
"read_only_depends_on": "eval:(doc.entry_type=='Decapitalization') || (doc.entry_type=='Capitalization' && doc.capitalization_method=='Create a new composite asset')"
},
{
"depends_on": "eval:doc.entry_type=='Capitalization'",
"depends_on": "eval:(doc.target_asset_name && !doc.__islocal) || (doc.target_asset && doc.entry_type=='Capitalization' && doc.capitalization_method=='Choose a WIP composite asset')",
"fetch_from": "target_asset.asset_name",
"fieldname": "target_asset_name",
"fieldtype": "Data",
@@ -186,12 +190,14 @@
},
{
"default": "1",
"depends_on": "eval:doc.entry_type=='Decapitalization'",
"fieldname": "target_qty",
"fieldtype": "Float",
"label": "Target Qty",
"read_only_depends_on": "eval:doc.entry_type=='Capitalization'"
},
{
"depends_on": "eval:doc.entry_type=='Decapitalization'",
"fetch_from": "target_item_code.stock_uom",
"fieldname": "target_stock_uom",
"fieldtype": "Link",
@@ -331,18 +337,26 @@
"read_only": 1
},
{
"depends_on": "eval:doc.entry_type=='Capitalization'",
"depends_on": "eval:doc.entry_type=='Capitalization' && doc.capitalization_method=='Create a new composite asset'",
"fieldname": "target_asset_location",
"fieldtype": "Link",
"label": "Target Asset Location",
"mandatory_depends_on": "eval:doc.entry_type=='Capitalization'",
"mandatory_depends_on": "eval:doc.entry_type=='Capitalization' && doc.capitalization_method=='Create a new composite asset'",
"options": "Location"
},
{
"depends_on": "eval:doc.entry_type=='Capitalization'",
"fieldname": "capitalization_method",
"fieldtype": "Select",
"label": "Capitalization Method",
"mandatory_depends_on": "eval:doc.entry_type=='Capitalization'",
"options": "\nCreate a new composite asset\nChoose a WIP composite asset"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2023-06-22 14:17:07.995120",
"modified": "2023-10-03 22:55:59.461456",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Capitalization",

View File

@@ -53,6 +53,7 @@ class AssetCapitalization(StockController):
self.validate_posting_time()
self.set_missing_values(for_validate=True)
self.validate_target_item()
self.validate_target_asset()
self.validate_consumed_stock_item()
self.validate_consumed_asset_item()
self.validate_service_item()
@@ -63,12 +64,12 @@ class AssetCapitalization(StockController):
def before_submit(self):
self.validate_source_mandatory()
if self.entry_type == "Capitalization":
self.create_target_asset()
self.create_target_asset()
def on_submit(self):
self.update_stock_ledger()
self.make_gl_entries()
self.update_target_asset()
def on_cancel(self):
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Repost Item Valuation")
@@ -85,6 +86,11 @@ class AssetCapitalization(StockController):
if self.meta.has_field(k) and (not self.get(k) or k in force_fields):
self.set(k, v)
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:
args = self.as_dict()
args.update(d.as_dict())
@@ -146,6 +152,33 @@ class AssetCapitalization(StockController):
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:
frappe.throw(_("Target Asset {0} needs to be composite asset").format(target_asset.name))
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)
)
if target_asset.status in ("Scrapped", "Sold", "Capitalized", "Decapitalized"):
frappe.throw(
_("Target Asset {0} cannot be {1}").format(target_asset.name, target_asset.status)
)
if target_asset.docstatus == 1:
frappe.throw(_("Target Asset {0} cannot be submitted").format(target_asset.name))
elif target_asset.docstatus == 2:
frappe.throw(_("Target Asset {0} cannot be cancelled").format(target_asset.name))
if target_asset.company != self.company:
frappe.throw(
_("Target Asset {0} does not belong to company {1}").format(target_asset.name, self.company)
)
def validate_consumed_stock_item(self):
for d in self.stock_items:
if d.item_code:
@@ -170,7 +203,23 @@ class AssetCapitalization(StockController):
)
asset = self.get_asset_for_validation(d.asset)
self.validate_asset(asset)
if asset.status in ("Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"):
frappe.throw(
_("Row #{0}: Consumed Asset {1} cannot be {2}").format(d.idx, asset.name, asset.status)
)
if asset.docstatus == 0:
frappe.throw(_("Row #{0}: Consumed Asset {1} cannot be Draft").format(d.idx, asset.name))
elif asset.docstatus == 2:
frappe.throw(_("Row #{0}: Consumed Asset {1} cannot be cancelled").format(d.idx, asset.name))
if asset.company != self.company:
frappe.throw(
_("Row #{0}: Consumed Asset {1} does not belong to company {2}").format(
d.idx, asset.name, self.company
)
)
def validate_service_item(self):
for d in self.service_items:
@@ -205,21 +254,12 @@ class AssetCapitalization(StockController):
def get_asset_for_validation(self, asset):
return frappe.db.get_value(
"Asset", asset, ["name", "item_code", "company", "status", "docstatus"], as_dict=1
"Asset",
asset,
["name", "item_code", "company", "status", "docstatus", "is_composite_asset"],
as_dict=1,
)
def validate_asset(self, asset):
if asset.status in ("Draft", "Scrapped", "Sold", "Capitalized", "Decapitalized"):
frappe.throw(_("Asset {0} is {1}").format(asset.name, asset.status))
if asset.docstatus == 0:
frappe.throw(_("Asset {0} is Draft").format(asset.name))
if asset.docstatus == 2:
frappe.throw(_("Asset {0} is cancelled").format(asset.name))
if asset.company != self.company:
frappe.throw(_("Asset {0} does not belong to company {1}").format(asset.name, self.company))
@frappe.whitelist()
def set_warehouse_details(self):
for d in self.get("stock_items"):
@@ -485,16 +525,25 @@ class AssetCapitalization(StockController):
)
def create_target_asset(self):
if (
self.entry_type != "Capitalization"
or self.capitalization_method != "Create a new composite asset"
):
return
total_target_asset_value = flt(self.total_value, self.precision("total_value"))
asset_doc = frappe.new_doc("Asset")
asset_doc.company = self.company
asset_doc.item_code = self.target_item_code
asset_doc.is_existing_asset = 1
asset_doc.is_composite_asset = 1
asset_doc.location = self.target_asset_location
asset_doc.available_for_use_date = self.posting_date
asset_doc.purchase_date = self.posting_date
asset_doc.gross_purchase_amount = total_target_asset_value
asset_doc.purchase_receipt_amount = total_target_asset_value
asset_doc.purchase_receipt_amount = total_target_asset_value
asset_doc.capitalized_in = self.name
asset_doc.flags.ignore_validate = True
asset_doc.insert()
@@ -510,6 +559,28 @@ class AssetCapitalization(StockController):
).format(get_link_to_form("Asset", asset_doc.name))
)
def update_target_asset(self):
if (
self.entry_type != "Capitalization"
or self.capitalization_method != "Choose a WIP composite asset"
):
return
total_target_asset_value = flt(self.total_value, self.precision("total_value"))
asset_doc = frappe.get_doc("Asset", self.target_asset)
asset_doc.gross_purchase_amount = total_target_asset_value
asset_doc.purchase_receipt_amount = total_target_asset_value
asset_doc.capitalized_in = self.name
asset_doc.flags.ignore_validate = True
asset_doc.save()
frappe.msgprint(
_(
"Asset {0} has been updated. 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)
@@ -568,6 +639,33 @@ def get_target_item_details(item_code=None, company=None):
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()
def get_consumed_stock_item_details(args):
if isinstance(args, string_types):
@@ -716,3 +814,30 @@ def get_service_item_details(args):
)
return out
@frappe.whitelist()
def get_items_tagged_to_wip_composite_asset(asset):
fields = [
"item_code",
"item_name",
"batch_no",
"serial_no",
"stock_qty",
"stock_uom",
"warehouse",
"cost_center",
"qty",
"valuation_rate",
"amount",
]
pi_items = frappe.get_all(
"Purchase Invoice Item", filters={"wip_composite_asset": asset}, fields=fields
)
pr_items = frappe.get_all(
"Purchase Receipt Item", filters={"wip_composite_asset": asset}, fields=fields
)
return pi_items + pr_items

View File

@@ -50,6 +50,7 @@ class TestAssetCapitalization(unittest.TestCase):
# Create and submit Asset Captitalization
asset_capitalization = create_asset_capitalization(
entry_type="Capitalization",
capitalization_method="Create a new composite asset",
target_item_code="Macbook Pro",
target_asset_location="Test Location",
stock_qty=stock_qty,
@@ -139,6 +140,7 @@ class TestAssetCapitalization(unittest.TestCase):
# Create and submit Asset Captitalization
asset_capitalization = create_asset_capitalization(
entry_type="Capitalization",
capitalization_method="Create a new composite asset",
target_item_code="Macbook Pro",
target_asset_location="Test Location",
stock_qty=stock_qty,
@@ -203,6 +205,77 @@ class TestAssetCapitalization(unittest.TestCase):
self.assertFalse(get_actual_gle_dict(asset_capitalization.name))
self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
def test_capitalization_with_wip_composite_asset(self):
company = "_Test Company with perpetual inventory"
set_depreciation_settings_in_company(company=company)
stock_rate = 1000
stock_qty = 2
stock_amount = 2000
total_amount = 2000
wip_composite_asset = create_asset(
asset_name="Asset Capitalization WIP Composite Asset",
is_composite_asset=1,
warehouse="Stores - TCP1",
company=company,
)
# Create and submit Asset Captitalization
asset_capitalization = create_asset_capitalization(
entry_type="Capitalization",
capitalization_method="Choose a WIP composite asset",
target_asset=wip_composite_asset,
target_asset_location="Test Location",
stock_qty=stock_qty,
stock_rate=stock_rate,
service_expense_account="Expenses Included In Asset Valuation - TCP1",
company=company,
submit=1,
)
# Test Asset Capitalization values
self.assertEqual(asset_capitalization.entry_type, "Capitalization")
self.assertEqual(asset_capitalization.capitalization_method, "Choose a WIP composite asset")
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)
self.assertEqual(asset_capitalization.total_value, total_amount)
self.assertEqual(asset_capitalization.target_incoming_rate, total_amount)
# Test Target Asset values
target_asset = frappe.get_doc("Asset", asset_capitalization.target_asset)
self.assertEqual(target_asset.gross_purchase_amount, total_amount)
self.assertEqual(target_asset.purchase_receipt_amount, total_amount)
# Test General Ledger Entries
expected_gle = {
"_Test Fixed Asset - TCP1": 2000,
"_Test Warehouse - TCP1": -2000,
}
actual_gle = get_actual_gle_dict(asset_capitalization.name)
self.assertEqual(actual_gle, expected_gle)
# Test Stock Ledger Entries
expected_sle = {
("Capitalization Source Stock Item", "_Test Warehouse - TCP1"): {
"actual_qty": -stock_qty,
"stock_value_difference": -stock_amount,
}
}
actual_sle = get_actual_sle_dict(asset_capitalization.name)
self.assertEqual(actual_sle, expected_sle)
# Cancel Asset Capitalization and make test entries and status are reversed
asset_capitalization.cancel()
self.assertFalse(get_actual_gle_dict(asset_capitalization.name))
self.assertFalse(get_actual_sle_dict(asset_capitalization.name))
def test_decapitalization_with_depreciation(self):
# Variables
purchase_date = "2020-01-01"
@@ -326,6 +399,7 @@ def create_asset_capitalization(**args):
asset_capitalization.update(
{
"entry_type": args.entry_type or "Capitalization",
"capitalization_method": args.capitalization_method or None,
"company": company,
"posting_date": args.posting_date or now.strftime("%Y-%m-%d"),
"posting_time": args.posting_time or now.strftime("%H:%M:%S.%f"),

View File

@@ -35,6 +35,12 @@ frappe.ui.form.on("Purchase Receipt", {
}
});
frm.set_query("wip_composite_asset", "items", function() {
return {
filters: {'is_composite_asset': 1, 'docstatus': 0 }
}
});
frm.set_query("taxes_and_charges", function() {
return {
filters: {'company': frm.doc.company }

View File

@@ -110,6 +110,7 @@
"manufacturer_part_no",
"accounting_details_section",
"expense_account",
"wip_composite_asset",
"column_break_102",
"provisional_expense_account",
"accounting_dimensions_section",
@@ -1018,12 +1019,18 @@
"no_copy": 1,
"print_hide": 1,
"read_only": 1
},
{
"fieldname": "wip_composite_asset",
"fieldtype": "Link",
"label": "WIP Composite Asset",
"options": "Asset"
}
],
"idx": 1,
"istable": 1,
"links": [],
"modified": "2023-07-04 17:22:02.830029",
"modified": "2023-10-03 21:11:50.547261",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
@@ -1034,4 +1041,4 @@
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
}