diff --git a/erpnext/buying/doctype/supplier/supplier.js b/erpnext/buying/doctype/supplier/supplier.js index acdbed969e8..c95bdf864e7 100644 --- a/erpnext/buying/doctype/supplier/supplier.js +++ b/erpnext/buying/doctype/supplier/supplier.js @@ -2,6 +2,12 @@ // License: GNU General Public License v3. See license.txt frappe.ui.form.on("Supplier", { + restrict_to_companies(frm) { + if (!frm.doc.restrict_to_companies) { + frm.set_value("allowed_companies", []); + } + }, + setup: function (frm) { frm.set_query("allowed_companies", () => ({ query: "erpnext.stock.doctype.company_restriction.company_restriction.company_query", diff --git a/erpnext/buying/doctype/supplier/supplier.json b/erpnext/buying/doctype/supplier/supplier.json index caee355c57c..d9d8c11edb2 100644 --- a/erpnext/buying/doctype/supplier/supplier.json +++ b/erpnext/buying/doctype/supplier/supplier.json @@ -55,6 +55,7 @@ "tax_withholding_group", "settings_tab", "company_restrictions_section", + "restrict_to_companies", "allowed_companies", "invoice_settings_section", "is_transporter", @@ -430,16 +431,22 @@ { "fieldname": "company_restrictions_section", "fieldtype": "Section Break", - "label": "Company Restrictions", - "description": "If set, this Supplier is only available for transactions in the listed companies. Leave empty for no restriction.", - "depends_on": "eval:cint(frappe.sys_defaults.enable_company_wise_masters)" + "label": "Company Restrictions" + }, + { + "default": "0", + "fieldname": "restrict_to_companies", + "fieldtype": "Check", + "label": "Restrict to Companies", + "description": "If checked, this Supplier is only available for transactions in the companies listed below." }, { "fieldname": "allowed_companies", "fieldtype": "Table MultiSelect", "label": "Allowed Companies", "options": "Company Restriction", - "depends_on": "eval:cint(frappe.sys_defaults.enable_company_wise_masters)" + "depends_on": "eval:doc.restrict_to_companies", + "mandatory_depends_on": "eval:doc.restrict_to_companies" }, { "fieldname": "contact_and_address_tab", @@ -578,7 +585,7 @@ "link_fieldname": "party" } ], - "modified": "2026-07-14 21:00:00.000000", + "modified": "2026-07-14 23:00:00.000000", "modified_by": "Administrator", "module": "Buying", "name": "Supplier", diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index e666c32b1c3..e36b9c05546 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -73,6 +73,7 @@ class Supplier(TransactionBase): primary_address: DF.TextEditor | None release_date: DF.Date | None represents_company: DF.Link | None + restrict_to_companies: DF.Check supplier_details: DF.Text | None supplier_group: DF.Link | None supplier_name: DF.Data diff --git a/erpnext/selling/doctype/customer/customer.js b/erpnext/selling/doctype/customer/customer.js index 5ee6dd871c2..ae5d230bebd 100644 --- a/erpnext/selling/doctype/customer/customer.js +++ b/erpnext/selling/doctype/customer/customer.js @@ -2,6 +2,12 @@ // License: GNU General Public License v3. See license.txt frappe.ui.form.on("Customer", { + restrict_to_companies(frm) { + if (!frm.doc.restrict_to_companies) { + frm.set_value("allowed_companies", []); + } + }, + setup: function (frm) { frm.set_query("allowed_companies", () => ({ query: "erpnext.stock.doctype.company_restriction.company_restriction.company_query", diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json index 786c834a06f..c6502200ac3 100644 --- a/erpnext/selling/doctype/customer/customer.json +++ b/erpnext/selling/doctype/customer/customer.json @@ -66,6 +66,7 @@ "tax_withholding_category", "settings_tab", "company_restrictions_section", + "restrict_to_companies", "allowed_companies", "section_break_ario", "so_required", @@ -516,18 +517,24 @@ "label": "Settings" }, { - "description": "If set, this Customer is only available for transactions in the listed companies. Leave empty for no restriction.", "fieldname": "company_restrictions_section", "fieldtype": "Section Break", - "label": "Company Restrictions", - "depends_on": "eval:cint(frappe.sys_defaults.enable_company_wise_masters)" + "label": "Company Restrictions" + }, + { + "default": "0", + "fieldname": "restrict_to_companies", + "fieldtype": "Check", + "label": "Restrict to Companies", + "description": "If checked, this Customer is only available for transactions in the companies listed below." }, { "fieldname": "allowed_companies", "fieldtype": "Table MultiSelect", "label": "Allowed Companies", "options": "Company Restriction", - "depends_on": "eval:cint(frappe.sys_defaults.enable_company_wise_masters)" + "depends_on": "eval:doc.restrict_to_companies", + "mandatory_depends_on": "eval:doc.restrict_to_companies" }, { "collapsible": 1, @@ -717,7 +724,7 @@ "link_fieldname": "party" } ], - "modified": "2026-07-14 21:00:00.000000", + "modified": "2026-07-14 23:00:00.000000", "modified_by": "Administrator", "module": "Selling", "name": "Customer", diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index 1bdae5b2944..1c150bb4676 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -99,6 +99,7 @@ class Customer(TransactionBase): primary_address: DF.TextEditor | None prospect_name: DF.Link | None represents_company: DF.Link | None + restrict_to_companies: DF.Check sales_team: DF.Table[SalesTeam] so_required: DF.Check supplier_numbers: DF.Table[SupplierNumberAtCustomer] diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.json b/erpnext/setup/doctype/global_defaults/global_defaults.json index 305972a5cea..8dc35200946 100644 --- a/erpnext/setup/doctype/global_defaults/global_defaults.json +++ b/erpnext/setup/doctype/global_defaults/global_defaults.json @@ -17,8 +17,7 @@ "disable_rounded_total", "disable_in_words", "column_break_hnew", - "use_posting_datetime_for_naming_documents", - "enable_company_wise_masters" + "use_posting_datetime_for_naming_documents" ], "fields": [ { @@ -93,13 +92,6 @@ "fieldtype": "Check", "label": "Use Posting Datetime for Naming Documents" }, - { - "default": "0", - "description": "When enabled, Supplier, Customer, and Item records can be restricted to specific companies via their Allowed Companies table. Transactions will only show masters configured for the selected company.", - "fieldname": "enable_company_wise_masters", - "fieldtype": "Check", - "label": "Enable Company-wise Master Filtering" - }, { "fieldname": "defaults_section", "fieldtype": "Section Break", @@ -121,7 +113,7 @@ "in_create": 1, "issingle": 1, "links": [], - "modified": "2026-07-14 18:30:00.000000", + "modified": "2026-07-14 23:00:00.000000", "modified_by": "Administrator", "module": "Setup", "name": "Global Defaults", diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py index 9684566d3a9..8930390e4b3 100644 --- a/erpnext/setup/doctype/global_defaults/global_defaults.py +++ b/erpnext/setup/doctype/global_defaults/global_defaults.py @@ -18,7 +18,6 @@ keydict = { "account_url": "account_url", "disable_rounded_total": "disable_rounded_total", "disable_in_words": "disable_in_words", - "enable_company_wise_masters": "enable_company_wise_masters", } ROUNDED_TOTAL_DOCTYPES = ( @@ -52,7 +51,6 @@ class GlobalDefaults(Document): demo_company: DF.Link | None disable_in_words: DF.Check disable_rounded_total: DF.Check - enable_company_wise_masters: DF.Check hide_currency_symbol: DF.Check use_posting_datetime_for_naming_documents: DF.Check # end: auto-generated types diff --git a/erpnext/stock/doctype/company_restriction/company_restriction.py b/erpnext/stock/doctype/company_restriction/company_restriction.py index 6b995e75a33..2a4aee36fb2 100644 --- a/erpnext/stock/doctype/company_restriction/company_restriction.py +++ b/erpnext/stock/doctype/company_restriction/company_restriction.py @@ -26,9 +26,6 @@ class CompanyRestriction(Document): def get_allowed_companies(user, doctype): from frappe.permissions import get_allowed_docs_for_doctype, get_user_permissions - if not frappe.get_single_value("Global Defaults", "enable_company_wise_masters"): - return None - user_permissions = get_user_permissions(user or frappe.session.user) if "Company" not in user_permissions: return None @@ -45,31 +42,39 @@ def get_permission_query_conditions(user, doctype=None): parent = frappe.qb.DocType(doctype) restriction = frappe.qb.DocType("Company Restriction") - restriction_rows = ( + allowed_rows = ( frappe.qb.from_(restriction) .select(restriction.name) .where( (restriction.parenttype == doctype) & (restriction.parentfield == "allowed_companies") & (restriction.parent == parent.name) + & (restriction.company.isin(allowed_companies)) ) ) - allowed_rows = restriction_rows.where(restriction.company.isin(allowed_companies)) - return Bracket(ExistsCriterion(allowed_rows) | ExistsCriterion(restriction_rows).negate()) + return Bracket((parent.restrict_to_companies == 0) | ExistsCriterion(allowed_rows)) def has_permission(doc, ptype=None, user=None): + if not doc.get("restrict_to_companies"): + return True + allowed_companies = get_allowed_companies(user, doc.doctype) if not allowed_companies: return True - companies = [row.company for row in doc.get("allowed_companies") or []] - if not companies: - return True - return any(company in allowed_companies for company in companies) + return any(row.company in allowed_companies for row in doc.get("allowed_companies") or []) def validate_allowed_companies(doc): + if not doc.get("restrict_to_companies"): + doc.set("allowed_companies", []) + elif not doc.get("allowed_companies") and not doc.flags.ignore_mandatory: + frappe.throw( + _("Allowed Companies is required when Restrict to Companies is checked"), + frappe.MandatoryError, + ) + if doc.flags.ignore_permissions: return diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js index d59a208dad6..fa6be1fdd6f 100644 --- a/erpnext/stock/doctype/item/item.js +++ b/erpnext/stock/doctype/item/item.js @@ -60,6 +60,12 @@ frappe.ui.form.on("Item", { erpnext.utils.confirm_negative_stock(frm); }, + restrict_to_companies(frm) { + if (!frm.doc.restrict_to_companies) { + frm.set_value("allowed_companies", []); + } + }, + setup: function (frm) { frm.set_query("allowed_companies", () => ({ query: "erpnext.stock.doctype.company_restriction.company_restriction.company_query", diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index 81975cd50f1..ea6f7023463 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -41,6 +41,7 @@ "column_break_wugd", "over_billing_allowance", "company_restrictions_section", + "restrict_to_companies", "allowed_companies", "section_break_11", "brand", @@ -1089,16 +1090,22 @@ { "fieldname": "company_restrictions_section", "fieldtype": "Section Break", - "label": "Company Restrictions", - "description": "If set, this Item is only available for transactions in the listed companies. Leave empty for no restriction.", - "depends_on": "eval:cint(frappe.sys_defaults.enable_company_wise_masters)" + "label": "Company Restrictions" + }, + { + "default": "0", + "fieldname": "restrict_to_companies", + "fieldtype": "Check", + "label": "Restrict to Companies", + "description": "If checked, this Item is only available for transactions in the companies listed below." }, { "fieldname": "allowed_companies", "fieldtype": "Table MultiSelect", "label": "Allowed Companies", "options": "Company Restriction", - "depends_on": "eval:cint(frappe.sys_defaults.enable_company_wise_masters)" + "depends_on": "eval:doc.restrict_to_companies", + "mandatory_depends_on": "eval:doc.restrict_to_companies" } ], "icon": "fa fa-tag", @@ -1106,7 +1113,7 @@ "image_field": "image", "links": [], "make_attachments_public": 1, - "modified": "2026-07-14 21:00:00.000000", + "modified": "2026-07-14 23:00:00.000000", "modified_by": "Administrator", "module": "Stock", "name": "Item", diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 1fc62169daa..e00fe9c8fd8 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -134,6 +134,7 @@ class Item(Document): quality_inspection_template: DF.Link | None reorder_levels: DF.Table[ItemReorder] retain_sample: DF.Check + restrict_to_companies: DF.Check safety_stock: DF.Float sales_tax_withholding_category: DF.Link | None sales_uom: DF.Link | None