From 1d9a46b9ebde27adc449b0d70ec56e3eeb70e09c Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Tue, 11 Feb 2025 16:05:02 +0530 Subject: [PATCH 1/4] fix: make purchase_receipt_item and purchase_invoice_item fields of data type --- erpnext/assets/doctype/asset/asset.json | 12 +++++------- erpnext/assets/doctype/asset/asset.py | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index 669d277755..4d97b292e7 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -507,17 +507,15 @@ }, { "fieldname": "purchase_receipt_item", - "fieldtype": "Link", + "fieldtype": "Data", "hidden": 1, - "label": "Purchase Receipt Item", - "options": "Purchase Receipt Item" + "label": "Purchase Receipt Item" }, { "fieldname": "purchase_invoice_item", - "fieldtype": "Link", + "fieldtype": "Data", "hidden": 1, - "label": "Purchase Invoice Item", - "options": "Purchase Invoice Item" + "label": "Purchase Invoice Item" }, { "fieldname": "insurance_details_tab", @@ -592,7 +590,7 @@ "link_fieldname": "target_asset" } ], - "modified": "2024-12-26 14:23:20.968882", + "modified": "2025-02-11 16:01:56.140904", "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index da23877075..1e5dd929bb 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -95,9 +95,9 @@ class Asset(AccountsController): purchase_amount: DF.Currency purchase_date: DF.Date | None purchase_invoice: DF.Link | None - purchase_invoice_item: DF.Link | None + purchase_invoice_item: DF.Data | None purchase_receipt: DF.Link | None - purchase_receipt_item: DF.Link | None + purchase_receipt_item: DF.Data | None split_from: DF.Link | None status: DF.Literal[ "Draft", -- GitLab From 59bd6335496261f486e5f995a209132da5943fe0 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Tue, 11 Feb 2025 16:17:42 +0530 Subject: [PATCH 2/4] fix: link correct row item of purchase doc --- erpnext/assets/doctype/asset/asset.js | 75 ++++++++++--------------- erpnext/assets/doctype/asset/asset.json | 6 +- erpnext/assets/doctype/asset/asset.py | 54 ++++++++++++++++++ 3 files changed, 87 insertions(+), 48 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 528b79cb65..8a40d17444 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -622,9 +622,7 @@ frappe.ui.form.on("Asset", { frm.trigger("toggle_reference_doc"); if (frm.doc.purchase_receipt) { if (frm.doc.item_code) { - frappe.db.get_doc("Purchase Receipt", frm.doc.purchase_receipt).then((pr_doc) => { - frm.events.set_values_from_purchase_doc(frm, "Purchase Receipt", pr_doc); - }); + frm.events.set_values_from_purchase_doc(frm, "Purchase Receipt"); } else { frm.set_value("purchase_receipt", ""); frappe.msgprint({ @@ -639,9 +637,7 @@ frappe.ui.form.on("Asset", { frm.trigger("toggle_reference_doc"); if (frm.doc.purchase_invoice) { if (frm.doc.item_code) { - frappe.db.get_doc("Purchase Invoice", frm.doc.purchase_invoice).then((pi_doc) => { - frm.events.set_values_from_purchase_doc(frm, "Purchase Invoice", pi_doc); - }); + frm.events.set_values_from_purchase_doc(frm, "Purchase Invoice"); } else { frm.set_value("purchase_invoice", ""); frappe.msgprint({ @@ -652,45 +648,36 @@ frappe.ui.form.on("Asset", { } }, - set_values_from_purchase_doc: function (frm, doctype, purchase_doc) { - frm.set_value("company", purchase_doc.company); - if (purchase_doc.bill_date) { - frm.set_value("purchase_date", purchase_doc.bill_date); - } else { - frm.set_value("purchase_date", purchase_doc.posting_date); - } - if (!frm.doc.is_existing_asset && !frm.doc.available_for_use_date) { - frm.set_value("available_for_use_date", frm.doc.purchase_date); - } - const item = purchase_doc.items.find((item) => item.item_code === frm.doc.item_code); - if (!item) { - let doctype_field = frappe.scrub(doctype); - frm.set_value(doctype_field, ""); - frappe.msgprint({ - title: __("Invalid {0}", [__(doctype)]), - message: __("The selected {0} does not contain the selected Asset Item.", [__(doctype)]), - indicator: "red", - }); - } - frappe.db.get_value("Item", item.item_code, "is_grouped_asset", (r) => { - var asset_quantity = r.is_grouped_asset ? item.qty : 1; - var purchase_amount = flt( - item.valuation_rate * asset_quantity, - precision("gross_purchase_amount") - ); + set_values_from_purchase_doc: (frm, doctype) => { + frappe.call({ + method: "erpnext.assets.doctype.asset.asset.get_values_from_purchase_doc", + args: { + purchase_doc_name: frm.doc.purchase_receipt || frm.doc.purchase_invoice, + item_code: frm.doc.item_code, + doctype: doctype, + }, + callback: (r) => { + if (r.message) { + let data = r.message; + frm.set_value("company", data.company); + frm.set_value("purchase_date", data.purchase_date); + frm.set_value("gross_purchase_amount", data.gross_purchase_amount); + frm.set_value("purchase_amount", data.gross_purchase_amount); + frm.set_value("asset_quantity", data.asset_quantity); + frm.set_value("cost_center", data.cost_center); + frm.set_value("location", data.asset_location); + + if (doctype === "Purchase Receipt") { + frm.set_value("purchase_receipt_item", data.purchase_receipt_item); + } else { + frm.set_value("purchase_invoice_item", data.purchase_invoice_item); + } - frm.set_value("gross_purchase_amount", purchase_amount); - frm.set_value("purchase_amount", purchase_amount); - frm.set_value("asset_quantity", asset_quantity); - frm.set_value("cost_center", item.cost_center || purchase_doc.cost_center); - if (item.asset_location) { - frm.set_value("location", item.asset_location); - } - if (doctype === "Purchase Receipt") { - frm.set_value("purchase_receipt_item", item.name); - } else if (doctype === "Purchase Invoice") { - frm.set_value("purchase_invoice_item", item.name); - } + let is_editable = !data.is_multiple_items; // if multiple items, then fields should not be read-only + frm.set_df_property("gross_purchase_amount", "read_only", is_editable); + frm.set_df_property("asset_quantity", "read_only", !is_editable); + } + }, }); }, diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index 4d97b292e7..78293c687d 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -228,8 +228,7 @@ "fieldtype": "Currency", "label": "Gross Purchase Amount", "mandatory_depends_on": "eval:(!doc.is_composite_asset || doc.docstatus==1)", - "options": "Company:company:default_currency", - "read_only_depends_on": "eval:!doc.is_existing_asset" + "options": "Company:company:default_currency" }, { "fieldname": "available_for_use_date", @@ -436,8 +435,7 @@ "default": "1", "fieldname": "asset_quantity", "fieldtype": "Int", - "label": "Asset Quantity", - "read_only_depends_on": "eval:!doc.is_existing_asset && !doc.is_composite_asset" + "label": "Asset Quantity" }, { "fieldname": "depr_entry_posting_status", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 1e5dd929bb..c4386d31d9 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -121,6 +121,7 @@ class Asset(AccountsController): def validate(self): self.validate_precision() + self.set_purchase_doc_row_item() self.validate_asset_values() self.validate_asset_and_reference() self.validate_item() @@ -200,6 +201,35 @@ class Asset(AccountsController): def after_delete(self): add_asset_activity(self.name, _("Asset deleted")) + def set_purchase_doc_row_item(self): + if self.is_existing_asset or self.is_composite_asset: + return + + self.purchase_amount = self.gross_purchase_amount + purchase_type = "Purchase Receipt" if self.purchase_receipt else "Purchase Invoice" + purchase_doc = self.purchase_receipt or self.purchase_invoice + + if not purchase_doc: + return + + purchase_doc = frappe.get_doc(purchase_type, purchase_doc) + + for item in purchase_doc.items: + if self.asset_quantity > 1: + if item.base_net_amount == self.gross_purchase_amount and item.qty == self.asset_quantity: + self.purchase_receipt_item = item.name if purchase_type == "Purchase Receipt" else None + self.purchase_invoice_item = item.name if purchase_type == "Purchase Invoice" else None + return + elif item.qty == self.asset_quantity: + self.purchase_receipt_item = item.name if purchase_type == "Purchase Receipt" else None + self.purchase_invoice_item = item.name if purchase_type == "Purchase Invoice" else None + return + else: + if item.base_net_rate == self.gross_purchase_amount: + self.purchase_receipt_item = item.name if purchase_type == "Purchase Receipt" else None + self.purchase_invoice_item = item.name if purchase_type == "Purchase Invoice" else None + return + def validate_asset_and_reference(self): if self.purchase_invoice or self.purchase_receipt: reference_doc = "Purchase Invoice" if self.purchase_invoice else "Purchase Receipt" @@ -1126,6 +1156,30 @@ def has_active_capitalization(asset): return active_capitalizations > 0 +@frappe.whitelist() +def get_values_from_purchase_doc(purchase_doc_name, item_code, doctype): + purchase_doc = frappe.get_doc(doctype, purchase_doc_name) + matching_items = [item for item in purchase_doc.items if item.item_code == item_code] + + if not matching_items: + frappe.throw(_(f"Selected {doctype} does not contain the Item Code {item_code}")) + + first_item = matching_items[0] + is_multiple_items = len(matching_items) > 1 + + return { + "company": purchase_doc.company, + "purchase_date": purchase_doc.get("bill_date") or purchase_doc.get("posting_date"), + "gross_purchase_amount": flt(first_item.base_net_amount), + "asset_quantity": first_item.qty, + "cost_center": first_item.cost_center or purchase_doc.get("cost_center"), + "asset_location": first_item.get("asset_location"), + "is_multiple_items": is_multiple_items, + "purchase_receipt_item": first_item.name if doctype == "Purchase Receipt" else None, + "purchase_invoice_item": first_item.name if doctype == "Purchase Invoice" else None, + } + + @frappe.whitelist() def split_asset(asset_name, split_qty): asset = frappe.get_doc("Asset", asset_name) -- GitLab From 4ce08888ed1523754e3a37e4e2e68171c91844b2 Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Wed, 19 Feb 2025 13:01:27 +0530 Subject: [PATCH 3/4] fix: validate if no matching item found --- erpnext/assets/doctype/asset/asset.js | 4 +-- erpnext/assets/doctype/asset/asset.py | 35 ++++++++++++++++++--------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 8a40d17444..4ea4f8c7d2 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -673,9 +673,9 @@ frappe.ui.form.on("Asset", { frm.set_value("purchase_invoice_item", data.purchase_invoice_item); } - let is_editable = !data.is_multiple_items; // if multiple items, then fields should not be read-only + let is_editable = !data.is_multiple_items; // if multiple items, then fields should be read-only frm.set_df_property("gross_purchase_amount", "read_only", is_editable); - frm.set_df_property("asset_quantity", "read_only", !is_editable); + frm.set_df_property("asset_quantity", "read_only", is_editable); } }, }); diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index c4386d31d9..5519ba6439 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -206,29 +206,40 @@ class Asset(AccountsController): return self.purchase_amount = self.gross_purchase_amount - purchase_type = "Purchase Receipt" if self.purchase_receipt else "Purchase Invoice" + purchase_doc_type = "Purchase Receipt" if self.purchase_receipt else "Purchase Invoice" purchase_doc = self.purchase_receipt or self.purchase_invoice if not purchase_doc: return - purchase_doc = frappe.get_doc(purchase_type, purchase_doc) + linked_item = self.get_linked_item(purchase_doc_type, purchase_doc) + + if linked_item: + if purchase_doc_type == "Purchase Receipt": + self.purchase_receipt_item = linked_item + else: + self.purchase_invoice_item = linked_item + + def get_linked_item(self, purchase_doc_type, purchase_doc): + purchase_doc = frappe.get_doc(purchase_doc_type, purchase_doc) for item in purchase_doc.items: if self.asset_quantity > 1: if item.base_net_amount == self.gross_purchase_amount and item.qty == self.asset_quantity: - self.purchase_receipt_item = item.name if purchase_type == "Purchase Receipt" else None - self.purchase_invoice_item = item.name if purchase_type == "Purchase Invoice" else None - return + return item.name elif item.qty == self.asset_quantity: - self.purchase_receipt_item = item.name if purchase_type == "Purchase Receipt" else None - self.purchase_invoice_item = item.name if purchase_type == "Purchase Invoice" else None - return + return item.name else: - if item.base_net_rate == self.gross_purchase_amount: - self.purchase_receipt_item = item.name if purchase_type == "Purchase Receipt" else None - self.purchase_invoice_item = item.name if purchase_type == "Purchase Invoice" else None - return + if item.base_net_rate == self.gross_purchase_amount and item.qty == self.asset_quantity: + return item.name + + # If no matching item found, raise validation error + frappe.throw( + _( + "No matching item found in {0} with item code {1}. " + "Please verify the purchase details and ensure the correct amount and quantity is recorded." + ).format(purchase_doc_type, self.item_code) + ) def validate_asset_and_reference(self): if self.purchase_invoice or self.purchase_receipt: -- GitLab From ab0c0839d564cc01991295211178af25b7ed813e Mon Sep 17 00:00:00 2001 From: Khushi Rawat <142375893+khushi8112@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:04:26 +0530 Subject: [PATCH 4/4] fix: reset location only if there is value in row item location field --- erpnext/assets/doctype/asset/asset.js | 1 - erpnext/assets/doctype/asset/asset.py | 8 -------- 2 files changed, 9 deletions(-) diff --git a/erpnext/assets/doctype/asset/asset.js b/erpnext/assets/doctype/asset/asset.js index 4ea4f8c7d2..c00aec8a1b 100644 --- a/erpnext/assets/doctype/asset/asset.js +++ b/erpnext/assets/doctype/asset/asset.js @@ -665,7 +665,6 @@ frappe.ui.form.on("Asset", { frm.set_value("purchase_amount", data.gross_purchase_amount); frm.set_value("asset_quantity", data.asset_quantity); frm.set_value("cost_center", data.cost_center); - frm.set_value("location", data.asset_location); if (doctype === "Purchase Receipt") { frm.set_value("purchase_receipt_item", data.purchase_receipt_item); diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 5519ba6439..afb41ee624 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -233,14 +233,6 @@ class Asset(AccountsController): if item.base_net_rate == self.gross_purchase_amount and item.qty == self.asset_quantity: return item.name - # If no matching item found, raise validation error - frappe.throw( - _( - "No matching item found in {0} with item code {1}. " - "Please verify the purchase details and ensure the correct amount and quantity is recorded." - ).format(purchase_doc_type, self.item_code) - ) - def validate_asset_and_reference(self): if self.purchase_invoice or self.purchase_receipt: reference_doc = "Purchase Invoice" if self.purchase_invoice else "Purchase Receipt" -- GitLab