fix: exclude already consumed purchase receipt items from asset capitalization (backport #46329) (#46336)

* fix: exclude already consumed purchase receipt items from asset capitalization (#46329)

* feat: link purchase receipt row item to capitalization

* fix: avoid fetching already consumed stock and asset items during capitalization

* fix(patch): added patch to link purchase receipt item to stock item child table

* fix: added nosemgrep

* refactor: rename  to

(cherry picked from commit f50d479bfd)

# Conflicts:
#	erpnext/assets/doctype/asset_capitalization_stock_item/asset_capitalization_stock_item.json
#	erpnext/patches.txt

* fix: resolved conflicts

* fix: resolved conflicts

---------

Co-authored-by: Khushi Rawat <142375893+khushi8112@users.noreply.github.com>
This commit is contained in:
mergify[bot]
2025-03-05 18:07:14 +05:30
committed by GitHub
parent 1e85f69072
commit 6c1ceff8ee
6 changed files with 100 additions and 19 deletions

View File

@@ -143,14 +143,19 @@ erpnext.assets.AssetCapitalization = class AssetCapitalization extends erpnext.s
} }
} }
set_consumed_stock_items_tagged_to_wip_composite_asset(asset) { set_consumed_stock_items_tagged_to_wip_composite_asset(target_asset) {
var me = this; var me = this;
if (asset) { if (target_asset) {
return me.frm.call({ return me.frm.call({
method: "erpnext.assets.doctype.asset_capitalization.asset_capitalization.get_items_tagged_to_wip_composite_asset", method: "erpnext.assets.doctype.asset_capitalization.asset_capitalization.get_items_tagged_to_wip_composite_asset",
args: { args: {
asset: asset, params: {
target_asset: target_asset,
finance_book: me.frm.doc.finance_book,
posting_date: me.frm.doc.posting_date,
posting_time: me.frm.doc.posting_time,
},
}, },
callback: function (r) { callback: function (r) {
if (!r.exc && r.message) { if (!r.exc && r.message) {

View File

@@ -856,7 +856,10 @@ def get_service_item_details(args):
@frappe.whitelist() @frappe.whitelist()
def get_items_tagged_to_wip_composite_asset(asset): def get_items_tagged_to_wip_composite_asset(params):
if isinstance(params, str):
params = json.loads(params)
fields = [ fields = [
"item_code", "item_code",
"item_name", "item_name",
@@ -871,25 +874,66 @@ def get_items_tagged_to_wip_composite_asset(asset):
"amount", "amount",
"is_fixed_asset", "is_fixed_asset",
"parent", "parent",
"name",
] ]
pr_items = frappe.get_all( pr_items = frappe.get_all(
"Purchase Receipt Item", filters={"wip_composite_asset": asset, "docstatus": 1}, fields=fields "Purchase Receipt Item",
filters={"wip_composite_asset": params.get("target_asset"), "docstatus": 1},
fields=fields,
) )
stock_items = [] stock_items = []
asset_items = [] asset_items = []
for d in pr_items: for d in pr_items:
if not d.is_fixed_asset: if not d.is_fixed_asset:
stock_items.append(frappe._dict(d)) stock_item = process_stock_item(d)
if stock_item:
stock_items.append(stock_item)
else: else:
asset_details = frappe.db.get_value( asset_item = process_fixed_asset(d)
"Asset", if asset_item:
{"item_code": d.item_code, "purchase_receipt": d.parent}, asset_items.append(asset_item)
["name as asset", "asset_name"],
as_dict=1,
)
d.update(asset_details)
asset_items.append(frappe._dict(d))
return stock_items, asset_items return stock_items, asset_items
def process_stock_item(d):
stock_capitalized = frappe.db.exists(
"Asset Capitalization Stock Item",
{
"purchase_receipt_item": d.name,
"parentfield": "stock_items",
"parenttype": "Asset Capitalization",
"docstatus": 1,
},
)
if stock_capitalized:
return None
stock_item_data = frappe._dict(d)
stock_item_data.purchase_receipt_item = d.name
return stock_item_data
def process_fixed_asset(d):
asset_details = frappe.db.get_value(
"Asset",
{
"item_code": d.item_code,
"purchase_receipt": d.parent,
"status": ("not in", ["Draft", "Scrapped", "Sold", "Capitalized"]),
},
["name as asset", "asset_name", "company"],
as_dict=1,
)
if asset_details:
asset_details.update(d)
asset_details.update(get_consumed_asset_details(asset_details))
d.update(asset_details)
return frappe._dict(d)
return None

View File

@@ -10,12 +10,13 @@
"column_break_3", "column_break_3",
"warehouse", "warehouse",
"section_break_6", "section_break_6",
"purchase_receipt_item",
"stock_qty", "stock_qty",
"stock_uom",
"actual_qty", "actual_qty",
"column_break_9", "column_break_9",
"valuation_rate", "valuation_rate",
"amount", "amount",
"stock_uom",
"batch_and_serial_no_section", "batch_and_serial_no_section",
"serial_and_batch_bundle", "serial_and_batch_bundle",
"use_serial_batch_fields", "use_serial_batch_fields",
@@ -53,14 +54,14 @@
{ {
"fieldname": "section_break_6", "fieldname": "section_break_6",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Qty and Rate" "label": "Purchase Details"
}, },
{ {
"columns": 1, "columns": 1,
"fieldname": "stock_qty", "fieldname": "stock_qty",
"fieldtype": "Float", "fieldtype": "Float",
"in_list_view": 1, "in_list_view": 1,
"label": "Qty", "label": "Quantity",
"non_negative": 1 "non_negative": 1
}, },
{ {
@@ -172,18 +173,26 @@
{ {
"fieldname": "column_break_mbuv", "fieldname": "column_break_mbuv",
"fieldtype": "Column Break" "fieldtype": "Column Break"
},
{
"fieldname": "purchase_receipt_item",
"fieldtype": "Data",
"hidden": 1,
"label": "Purchase Receipt Item"
} }
], ],
"grid_page_length": 50,
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2024-06-26 17:06:22.564438", "modified": "2025-03-05 12:46:01.074742",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Assets", "module": "Assets",
"name": "Asset Capitalization Stock Item", "name": "Asset Capitalization Stock Item",
"owner": "Administrator", "owner": "Administrator",
"permissions": [], "permissions": [],
"sort_field": "modified", "row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC", "sort_order": "DESC",
"states": [], "states": [],
"track_changes": 1 "track_changes": 1

View File

@@ -23,6 +23,7 @@ class AssetCapitalizationStockItem(Document):
parent: DF.Data parent: DF.Data
parentfield: DF.Data parentfield: DF.Data
parenttype: DF.Data parenttype: DF.Data
purchase_receipt_item: DF.Data | None
serial_and_batch_bundle: DF.Link | None serial_and_batch_bundle: DF.Link | None
serial_no: DF.Text | None serial_no: DF.Text | None
stock_qty: DF.Float stock_qty: DF.Float

View File

@@ -400,3 +400,4 @@ erpnext.patches.v15_0.rename_sla_fields
erpnext.patches.v15_0.update_query_report erpnext.patches.v15_0.update_query_report
erpnext.patches.v15_0.rename_field_from_rate_difference_to_amount_difference erpnext.patches.v15_0.rename_field_from_rate_difference_to_amount_difference
erpnext.patches.v15_0.recalculate_amount_difference_field erpnext.patches.v15_0.recalculate_amount_difference_field
erpnext.patches.v15_0.set_purchase_receipt_row_item_to_capitalization_stock_item

View File

@@ -0,0 +1,21 @@
import frappe
def execute():
# nosemgrep
frappe.db.sql(
"""
UPDATE `tabAsset Capitalization Stock Item` ACSI
JOIN `tabAsset Capitalization` AC
ON ACSI.parent = AC.name
JOIN `tabPurchase Receipt Item` PRI
ON
PRI.item_code = ACSI.item_code
AND PRI.wip_composite_asset = AC.target_asset
SET
ACSI.purchase_receipt_item = PRI.name
WHERE
ACSI.purchase_receipt_item IS NULL
AND AC.docstatus = 1
"""
)