diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 7676dfad752..9e3bd91a164 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -211,16 +211,28 @@ def item_query(doctype, txt, searchfield, start, page_len, filters, as_dict=Fals if filters and isinstance(filters, dict): if filters.get("customer") or filters.get("supplier"): + party_type = "Customer" if filters.get("customer") else "Supplier" party = filters.get("customer") or filters.get("supplier") + group = "Customer Group" if filters.get("customer") else "Supplier Group" item_rules_list = frappe.get_all( "Party Specific Item", filters={ "party": ["!=", party], - "party_type": "Customer" if filters.get("customer") else "Supplier", + "party_type": party_type, }, fields=["restrict_based_on", "based_on_value"], ) + party_group_rules_list = frappe.get_all( + "Party Specific Item", + filters={"party_type": group}, + fields=["party as party_group", "restrict_based_on", "based_on_value"], + ) + current_party_group = frappe.get_value(party_type, party, frappe.scrub(group)) + for rule in party_group_rules_list: + if current_party_group != rule.party_group: + item_rules_list.append(rule) + filters_dict = {} for rule in item_rules_list: if rule["restrict_based_on"] == "Item": diff --git a/erpnext/selling/doctype/party_specific_item/party_specific_item.js b/erpnext/selling/doctype/party_specific_item/party_specific_item.js index 0decc70d7ac..779f2683102 100644 --- a/erpnext/selling/doctype/party_specific_item/party_specific_item.js +++ b/erpnext/selling/doctype/party_specific_item/party_specific_item.js @@ -2,6 +2,21 @@ // For license information, please see license.txt frappe.ui.form.on("Party Specific Item", { - // refresh: function(frm) { - // } + setup: function (frm) { + frm.trigger("party_type"); + }, + + party_type: function (frm) { + if (["Customer Group", "Supplier Group"].includes(frm.doc.party_type)) { + frm.set_query("party", function () { + return { + filters: { + is_group: 0, + }, + }; + }); + } else { + frm.set_query("party", null); + } + }, }); diff --git a/erpnext/selling/doctype/party_specific_item/party_specific_item.json b/erpnext/selling/doctype/party_specific_item/party_specific_item.json index 999cb61af61..b1aa5bfa59b 100644 --- a/erpnext/selling/doctype/party_specific_item/party_specific_item.json +++ b/erpnext/selling/doctype/party_specific_item/party_specific_item.json @@ -1,5 +1,6 @@ { "actions": [], + "allow_bulk_edit": 1, "allow_import": 1, "creation": "2021-08-27 19:28:07.559978", "doctype": "DocType", @@ -18,7 +19,7 @@ "fieldtype": "Select", "in_list_view": 1, "label": "Party Type", - "options": "Customer\nSupplier", + "options": "Customer\nCustomer Group\nSupplier\nSupplier Group", "reqd": 1 }, { @@ -52,7 +53,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2024-03-27 13:10:08.752476", + "modified": "2026-05-17 11:46:17.634855", "modified_by": "Administrator", "module": "Selling", "name": "Party Specific Item", @@ -71,9 +72,10 @@ "write": 1 } ], + "row_format": "Dynamic", "sort_field": "creation", "sort_order": "DESC", "states": [], "title_field": "party", "track_changes": 1 -} \ No newline at end of file +} diff --git a/erpnext/selling/doctype/party_specific_item/party_specific_item.py b/erpnext/selling/doctype/party_specific_item/party_specific_item.py index d1775c2467c..77eb9095305 100644 --- a/erpnext/selling/doctype/party_specific_item/party_specific_item.py +++ b/erpnext/selling/doctype/party_specific_item/party_specific_item.py @@ -17,7 +17,7 @@ class PartySpecificItem(Document): based_on_value: DF.DynamicLink party: DF.DynamicLink - party_type: DF.Literal["Customer", "Supplier"] + party_type: DF.Literal["Customer", "Customer Group", "Supplier", "Supplier Group"] restrict_based_on: DF.Literal["Item", "Item Group", "Brand"] # end: auto-generated types diff --git a/erpnext/selling/doctype/party_specific_item/test_party_specific_item.py b/erpnext/selling/doctype/party_specific_item/test_party_specific_item.py index a94837452e6..eaa68232d27 100644 --- a/erpnext/selling/doctype/party_specific_item/test_party_specific_item.py +++ b/erpnext/selling/doctype/party_specific_item/test_party_specific_item.py @@ -49,6 +49,23 @@ class TestPartySpecificItem(ERPNextTestSuite): ) self.assertTrue(item in flatten(items)) + def test_party_group(self): + customer = "_Test Customer With Template" + item = "_Test Item" + frappe.set_value("Customer", customer, "customer_group", "Government") + + create_party_specific_item( + party_type="Customer Group", + party="Government", + restrict_based_on="Item", + based_on_value=item, + ) + filters = {"is_sales_item": 1, "customer": customer} + items = item_query( + doctype="Item", txt="", searchfield="name", start=0, page_len=20, filters=filters, as_dict=False + ) + self.assertTrue(item in flatten(items)) + def flatten(lst): result = []