fix: block disabled/frozen customers on Opportunity

Opportunity inherits TransactionBase instead of AccountsController, so
it never ran validate_party_frozen_disabled like Quotation, Sales Order
and Sales Invoice do. A disabled Customer could be saved as an
Opportunity's party and only get caught later at Quotation stage.

Also fixes the party_name Link query on the client: it referenced
erpnext.queries.customer, which was never defined, so disabled
customers showed up in the picker.
This commit is contained in:
Jatin3128
2026-08-10 18:02:16 +05:30
parent 8e8ef1602e
commit 90937ce6d9
3 changed files with 18 additions and 0 deletions

View File

@@ -12,6 +12,7 @@ from frappe.query_builder import DocType, Interval
from frappe.query_builder.functions import Now
from frappe.utils import flt, get_fullname
from erpnext.accounts.party import validate_party_frozen_disabled
from erpnext.crm.utils import (
CRMNote,
copy_comments,
@@ -132,6 +133,7 @@ class Opportunity(TransactionBase, CRMNote):
self.validate_item_details()
self.validate_uom_is_integer("uom", "qty")
self.validate_cust_name()
self.validate_party()
self.map_fields()
self.validate_qty()
self.set_exchange_rate()
@@ -355,6 +357,9 @@ class Opportunity(TransactionBase, CRMNote):
return False
return True
def validate_party(self) -> None:
validate_party_frozen_disabled(self.company, self.opportunity_from, self.party_name)
def validate_cust_name(self):
if self.party_name:
if self.opportunity_from == "Customer":

View File

@@ -9,6 +9,7 @@ from erpnext.crm.doctype.lead.test_lead import make_lead
from erpnext.crm.doctype.opportunity.mapper import make_quotation
from erpnext.crm.doctype.opportunity.opportunity import auto_close_opportunity, get_item_details
from erpnext.crm.utils import get_linked_communication_list
from erpnext.exceptions import PartyDisabled
from erpnext.tests.utils import ERPNextTestSuite
@@ -71,6 +72,14 @@ class TestOpportunity(ERPNextTestSuite):
opportunity_doc = make_opportunity(with_items=1, rate=1100, qty=2)
self.assertEqual(opportunity_doc.total, 2200)
def test_disabled_customer_not_allowed(self):
frappe.db.set_value("Customer", "_Test Customer", "disabled", 1)
self.assertRaises(PartyDisabled, make_opportunity, with_items=0)
frappe.db.set_value("Customer", "_Test Customer", "disabled", 0)
make_opportunity(with_items=0)
def test_carry_forward_of_email_and_comments(self):
frappe.db.set_single_value("CRM Settings", "carry_forward_communication_and_comments", 1)
lead_doc = make_lead()

View File

@@ -12,6 +12,10 @@ $.extend(erpnext.queries, {
return { query: "erpnext.controllers.queries.lead_query" };
},
customer: function () {
return { filters: { disabled: 0 } };
},
item: function (filters) {
var args = { query: "erpnext.controllers.queries.item_query" };
if (filters) args["filters"] = filters;