diff --git a/erpnext/assets/doctype/asset/asset.json b/erpnext/assets/doctype/asset/asset.json index 487f67669ff..978eae55c7e 100644 --- a/erpnext/assets/doctype/asset/asset.json +++ b/erpnext/assets/doctype/asset/asset.json @@ -365,6 +365,7 @@ "label": "Maintenance Required" }, { +<<<<<<< HEAD "collapsible": 1, "fieldname": "other_details", "fieldtype": "Section Break", @@ -372,6 +373,8 @@ }, { "allow_on_submit": 1, +======= +>>>>>>> 1928a394c9 (fix: validate purchase invoice status and resolve related issues) "default": "Draft", "fieldname": "status", "fieldtype": "Select", @@ -379,7 +382,7 @@ "in_standard_filter": 1, "label": "Status", "no_copy": 1, - "options": "Draft\nSubmitted\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order\nIssue\nReceipt\nCapitalized\nWork In Progress", + "options": "Draft\nSubmitted\nCancelled\nPartially Depreciated\nFully Depreciated\nSold\nScrapped\nIn Maintenance\nOut of Order\nIssue\nReceipt\nCapitalized\nWork In Progress", "read_only": 1 }, { @@ -597,7 +600,11 @@ "link_fieldname": "target_asset" } ], +<<<<<<< HEAD "modified": "2025-10-23 22:43:33.634452", +======= + "modified": "2025-11-04 22:39:00.817405", +>>>>>>> 1928a394c9 (fix: validate purchase invoice status and resolve related issues) "modified_by": "Administrator", "module": "Assets", "name": "Asset", diff --git a/erpnext/assets/doctype/asset/asset.py b/erpnext/assets/doctype/asset/asset.py index 6fef1b21825..dda2ea33aa1 100644 --- a/erpnext/assets/doctype/asset/asset.py +++ b/erpnext/assets/doctype/asset/asset.py @@ -103,6 +103,7 @@ class Asset(AccountsController): status: DF.Literal[ "Draft", "Submitted", + "Cancelled", "Partially Depreciated", "Fully Depreciated", "Sold", diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.json b/erpnext/assets/doctype/asset_repair/asset_repair.json index 16f3da9b988..153233034eb 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.json +++ b/erpnext/assets/doctype/asset_repair/asset_repair.json @@ -139,7 +139,7 @@ "fieldtype": "Link", "in_list_view": 1, "label": "Asset", - "link_filters": "[[\"Asset\",\"status\",\"not in\",[\"Work In Progress\",\"Capitalized\",\"Fully Depreciated\",\"Sold\",\"Scrapped\",null]]]", + "link_filters": "[[\"Asset\",\"status\",\"not in\",[\"Work In Progress\",\"Capitalized\",\"Fully Depreciated\",\"Sold\",\"Scrapped\",\"Cancelled\",null]]]", "options": "Asset", "reqd": 1 }, @@ -250,7 +250,11 @@ "index_web_pages_for_search": 1, "is_submittable": 1, "links": [], +<<<<<<< HEAD "modified": "2025-07-29 15:14:34.044564", +======= + "modified": "2025-11-04 23:06:43.644846", +>>>>>>> 1928a394c9 (fix: validate purchase invoice status and resolve related issues) "modified_by": "Administrator", "module": "Assets", "name": "Asset Repair", diff --git a/erpnext/assets/doctype/asset_repair/asset_repair.py b/erpnext/assets/doctype/asset_repair/asset_repair.py index 358945edf87..b1445fecbd5 100644 --- a/erpnext/assets/doctype/asset_repair/asset_repair.py +++ b/erpnext/assets/doctype/asset_repair/asset_repair.py @@ -75,6 +75,67 @@ class AssetRepair(AccountsController): _("Completion Date can not be before Failure Date. Please adjust the dates accordingly.") ) +<<<<<<< HEAD +======= + def validate_purchase_invoices(self): + for d in self.invoices: + self.validate_purchase_invoice_status(d.purchase_invoice) + invoice_items = self.get_invoice_items(d.purchase_invoice) + self.validate_service_purchase_invoice(d.purchase_invoice, invoice_items) + self.validate_expense_account(d, invoice_items) + self.validate_purchase_invoice_repair_cost(d, invoice_items) + + def validate_purchase_invoice_status(self, purchase_invoice): + docstatus = frappe.db.get_value("Purchase Invoice", purchase_invoice, "docstatus") + if docstatus == 0: + frappe.throw( + _("{0} is still in Draft. Please submit it before saving the Asset Repair.").format( + get_link_to_form("Purchase Invoice", purchase_invoice) + ) + ) + + def get_invoice_items(self, pi): + invoice_items = frappe.get_all( + "Purchase Invoice Item", + filters={"parent": pi}, + fields=["item_code", "expense_account", "base_net_amount"], + ) + + return invoice_items + + def validate_service_purchase_invoice(self, purchase_invoice, invoice_items): + service_item_exists = False + for item in invoice_items: + if frappe.db.get_value("Item", item.item_code, "is_stock_item") == 0: + service_item_exists = True + break + + if not service_item_exists: + frappe.throw( + _("Service item not present in Purchase Invoice {0}").format( + get_link_to_form("Purchase Invoice", purchase_invoice) + ) + ) + + def validate_expense_account(self, row, invoice_items): + pi_expense_accounts = set([item.expense_account for item in invoice_items]) + if row.expense_account not in pi_expense_accounts: + frappe.throw( + _("Expense account {0} not present in Purchase Invoice {1}").format( + row.expense_account, get_link_to_form("Purchase Invoice", row.purchase_invoice) + ) + ) + + def validate_purchase_invoice_repair_cost(self, row, invoice_items): + pi_net_total = sum([flt(item.base_net_amount) for item in invoice_items]) + if flt(row.repair_cost) > pi_net_total: + frappe.throw( + _("Repair cost cannot be greater than purchase invoice base net total {0}").format( + pi_net_total + ) + ) + +>>>>>>> 1928a394c9 (fix: validate purchase invoice status and resolve related issues) def update_status(self): if self.repair_status == "Pending" and self.asset_doc.status != "Out of Order": frappe.db.set_value("Asset", self.asset, "status", "Out of Order")