Currently we are working in a multi-company setup in ERPNext with a large item master. There is a requirement to control item visibility across companies. Currently, since the Item DocType is shared, all items are visible to all companies by default.
In our scenario, some items need to be shared across specific companies, while being restricted from others. For example, an item may be accessible to Company A and Company B, but should not be visible or usable by Company C.
Since each company operates with its own product portfolio, the current behavior creates challenges in managing items and increases the risk of incorrect usage.
Is there a recommended approach to restrict item visibility based on company, while still allowing selective sharing of items across multiple companies?
However this is per user. If you want to do per user group (e.g. all users with permission for Company A should be able to see Item Group A AND Group M) then maybe its possible with permission hooks - Hooks
Also check out permission queries in server scripts - Server Script
Each item explicitly declares which companies are allowed to use it. If no companies are declared, the item is visible to everyone (backward compatible). If companies are declared, only those companies can see and select that item in transactions.
This requires customization in exactly two places — the Item Master and the Item Code field on transaction doctypes. Everything else, including accounting, reports, GL entries, and inter-company flows, remains completely untouched.
Part 1 — Item Master Customization
A new child table called Allowed Companies is added to the Item master. This table contains a simple list of companies that are permitted to use the item.
The behavior is intentionally designed to be backward compatible:
If the Allowed Companies table is empty, the item is treated as unrestricted and remains visible to all companies — exactly as it behaves today. This means no disruption to existing items during migration.
If the Allowed Companies table has one or more entries, only those listed companies will see the item in their transaction dropdowns.
This gives full flexibility — some items can be company-specific, some can be shared between two or three companies, and some can remain globally visible, all within the same item master.
Part 2 — Transaction-Level Filter on Item Code Field
The second part of the solution is applying a custom search query filter on the Item Code field across all relevant transaction doctypes.
When a user opens a transaction — say a Sales Invoice — and searches for an item, the system currently shows all active items. With this customization, the search query is intercepted and filtered based on the company selected on that transaction.
The filter logic checks two conditions:
Does this item have any company restrictions defined?
If yes, is the current transaction’s company listed in those restrictions?
If the item has no restrictions, it passes through. If it has restrictions and the transaction’s company is listed, it passes through. Otherwise, it is excluded from the search results entirely.
This filter is applied via a single centralized query function that is reused across all transaction doctypes. The same function is referenced on the Item Code field of:
Sales Order, Sales Invoice, Quotation
Purchase Order, Purchase Invoice
Delivery Note, Purchase Receipt
Stock Entry, Payment Entry
And any other custom doctypes where items are selected
Since the filter is driven by doc.company — a field that already exists on all these doctypes — no structural changes are needed anywhere else.
Thank you @asieftejani
At present we have added the field Company to the items and using user permissions. User Group with permission and using hooks is a good idea, will explore more into it.