mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-18 19:07:55 +00:00
fix: block disabled/frozen suppliers on Request for Quotation
Request for Quotation overrides validate() entirely and never calls
super().validate(), so it never goes through AccountsController's
party validation. Suppliers also sit in a child table, so the shared
PartyValidator wouldn't have caught it anyway (it only checks a single
top-level party field). A disabled or frozen Supplier could be added
to an RFQ and the RFQ submitted without any warning.
Also filters the suppliers grid's supplier Link field to disabled=0,
matching the same client-side fix applied to Opportunity's party_name.
(cherry picked from commit 4bf65ffc1d)
# Conflicts:
# erpnext/buying/doctype/request_for_quotation/request_for_quotation.py
# erpnext/buying/doctype/request_for_quotation/test_request_for_quotation.py
This commit is contained in:
@@ -22,6 +22,10 @@ frappe.ui.form.on("Request for Quotation", {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
frm.set_query("supplier", "suppliers", function () {
|
||||||
|
return { filters: { disabled: 0 } };
|
||||||
|
});
|
||||||
|
|
||||||
frm.set_query("warehouse", "items", () => ({
|
frm.set_query("warehouse", "items", () => ({
|
||||||
filters: {
|
filters: {
|
||||||
company: frm.doc.company,
|
company: frm.doc.company,
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ from frappe.utils import get_url
|
|||||||
from frappe.utils.print_format import download_pdf
|
from frappe.utils.print_format import download_pdf
|
||||||
from frappe.utils.user import get_user_fullname
|
from frappe.utils.user import get_user_fullname
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
from erpnext.accounts.party import get_party_account_currency, get_party_details
|
from erpnext.accounts.party import get_party_account_currency, get_party_details
|
||||||
|
=======
|
||||||
|
from erpnext.accounts.party import validate_party_frozen_disabled
|
||||||
|
>>>>>>> 4bf65ffc1d (fix: block disabled/frozen suppliers on Request for Quotation)
|
||||||
from erpnext.buying.utils import validate_for_items
|
from erpnext.buying.utils import validate_for_items
|
||||||
from erpnext.controllers.buying_controller import BuyingController
|
from erpnext.controllers.buying_controller import BuyingController
|
||||||
from erpnext.stock.doctype.material_request.material_request import set_missing_values
|
from erpnext.stock.doctype.material_request.material_request import set_missing_values
|
||||||
@@ -123,6 +127,8 @@ class RequestforQuotation(BuyingController):
|
|||||||
|
|
||||||
def validate_supplier_list(self):
|
def validate_supplier_list(self):
|
||||||
for d in self.suppliers:
|
for d in self.suppliers:
|
||||||
|
validate_party_frozen_disabled(self.company, "Supplier", d.supplier)
|
||||||
|
|
||||||
prevent_rfqs = frappe.db.get_value("Supplier", d.supplier, "prevent_rfqs")
|
prevent_rfqs = frappe.db.get_value("Supplier", d.supplier, "prevent_rfqs")
|
||||||
if prevent_rfqs:
|
if prevent_rfqs:
|
||||||
standing = frappe.db.get_value("Supplier Scorecard", d.supplier, "status")
|
standing = frappe.db.get_value("Supplier Scorecard", d.supplier, "status")
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ from erpnext.buying.doctype.request_for_quotation.request_for_quotation import (
|
|||||||
from erpnext.controllers.accounts_controller import InvalidQtyError
|
from erpnext.controllers.accounts_controller import InvalidQtyError
|
||||||
from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq
|
from erpnext.crm.doctype.opportunity.opportunity import make_request_for_quotation as make_rfq
|
||||||
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
from erpnext.crm.doctype.opportunity.test_opportunity import make_opportunity
|
||||||
|
from erpnext.exceptions import PartyDisabled
|
||||||
from erpnext.stock.doctype.item.test_item import make_item
|
from erpnext.stock.doctype.item.test_item import make_item
|
||||||
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
from erpnext.templates.pages.rfq import check_supplier_has_docname_access
|
||||||
|
|
||||||
@@ -57,6 +58,56 @@ class TestRequestforQuotation(FrappeTestCase):
|
|||||||
self.assertEqual(rfq.get("suppliers")[0].quote_status, "Received")
|
self.assertEqual(rfq.get("suppliers")[0].quote_status, "Received")
|
||||||
self.assertEqual(rfq.get("suppliers")[1].quote_status, "Pending")
|
self.assertEqual(rfq.get("suppliers")[1].quote_status, "Pending")
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
def test_duplicate_supplier_rejected(self):
|
||||||
|
rfq = frappe.new_doc("Request for Quotation")
|
||||||
|
rfq.transaction_date = nowdate()
|
||||||
|
rfq.company = "_Test Company"
|
||||||
|
rfq.message_for_supplier = "Please quote"
|
||||||
|
rfq.append("suppliers", {"supplier": "_Test Supplier"})
|
||||||
|
rfq.append("suppliers", {"supplier": "_Test Supplier"})
|
||||||
|
rfq.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": "_Test Item",
|
||||||
|
"qty": 5,
|
||||||
|
"uom": "_Test UOM",
|
||||||
|
"stock_uom": "_Test UOM",
|
||||||
|
"conversion_factor": 1.0,
|
||||||
|
"warehouse": "_Test Warehouse - _TC",
|
||||||
|
"schedule_date": nowdate(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertRaises(frappe.ValidationError, rfq.insert)
|
||||||
|
|
||||||
|
def test_rfq_blocked_for_supplier_with_prevent_rfqs(self):
|
||||||
|
frappe.db.set_value("Supplier", "_Test Supplier", "prevent_rfqs", 1)
|
||||||
|
rfq = make_request_for_quotation(
|
||||||
|
supplier_data=[{"supplier": "_Test Supplier", "supplier_name": "_Test Supplier"}],
|
||||||
|
do_not_save=True,
|
||||||
|
)
|
||||||
|
self.assertRaises(frappe.ValidationError, rfq.save)
|
||||||
|
|
||||||
|
def test_rfq_blocked_for_disabled_supplier(self):
|
||||||
|
frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 1)
|
||||||
|
rfq = make_request_for_quotation(
|
||||||
|
supplier_data=[{"supplier": "_Test Supplier", "supplier_name": "_Test Supplier"}],
|
||||||
|
do_not_save=True,
|
||||||
|
)
|
||||||
|
self.assertRaises(PartyDisabled, rfq.save)
|
||||||
|
|
||||||
|
frappe.db.set_value("Supplier", "_Test Supplier", "disabled", 0)
|
||||||
|
rfq.save()
|
||||||
|
|
||||||
|
def test_rfq_status_lifecycle(self):
|
||||||
|
rfq = make_request_for_quotation()
|
||||||
|
self.assertEqual(rfq.status, "Submitted")
|
||||||
|
|
||||||
|
rfq.cancel()
|
||||||
|
self.assertEqual(rfq.status, "Cancelled")
|
||||||
|
|
||||||
|
>>>>>>> 4bf65ffc1d (fix: block disabled/frozen suppliers on Request for Quotation)
|
||||||
def test_make_supplier_quotation(self):
|
def test_make_supplier_quotation(self):
|
||||||
rfq = make_request_for_quotation()
|
rfq = make_request_for_quotation()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user