Single Company, several departments: how do you isolate warehouses per department? (v16)

Hello everyone,

We are a non-profit running ERPNext v16 as a single legal entity, so one Company with centralized accounting.
We report per department through an Accounting Dimension.

We are building our own apps on top of ERPNext, and we want to follow the approach Frappe recommends from the
start: native mechanisms first, customization only where the framework expects it. That way we build on solid
foundations and keep future upgrades (v17 and beyond) smooth. So we are looking for the recommended way, not
just a way that works.

This is close to the Multi-branch Companies ( Multi-branch Companies ) thread,
which ended without a solution. Multi-Company is not an option for us: we are one entity, and each department
is an operational unit, not a subsidiary.

Setup

  • Each department has its own warehouses and its own item groups. One sub-department manages batch items with
    expiry dates.
  • Stock documents are receipts, issues and reconciliations. There are no transfers between departments.
  • Some users work for several departments.

What we need

  1. Users can only move stock in their own department’s warehouses.
  2. Users only see their own department’s stock documents, lists and reports. Hiding other departments’ items
    would be nice to have.
  3. Access to a parent department covers its sub-departments.

User Permissions on Warehouse are our starting point. As far as we can tell, though, they only filter the
parent document: child-table rows (s_warehouse / t_warehouse) and SQL-based stock reports are not restricted.
That gap is what we are asking about.

Questions

  • What is the recommended way to close that gap: configuration alone, or custom permission_query_conditions /
    has_permission hooks on Warehouse?
  • How do you handle users in several departments?
  • Do you know of any open-source app or public example of this pattern?

Thanks for any pointers!

User Permissions are not sufficient as an authorization boundary for your requirement.

Implement this as a custom Department to Warehouse authorization layer using native User Permissions for the UI filtering:

  1. Keep Warehouse as the actual security boundary.
  2. Associate each Warehouse with its department (A user’s department membership should be many-to-many). Don’t encode this using Roles. Roles answer what a user can do, department membership answers which records they can access.
  3. Don’t rely on User Permissions to secure source_warehouse / target_warehouse. Add a server-side validation to every stock transaction. Then hook this into the relevant stock DocTypes using your custom app’s doc_events.
  4. For the parent Stock Entry document, permission_query_conditions is appropriate.

Reports are the tricky part. A report querying tabStock Ledger Entry doesn’t have a Stock Entry parent on which Frappe can apply the user’s Warehouse permission. So every custom stock report needs to apply the same authorization function.

has_permission is useful.

Also check this Github issue: User Permission Issue with Stock Entry and Warehouse Selection · Issue #42859 · frappe/erpnext · GitHub

Thanks,
That matches the direction we were leaning towards. One follow-up: what about the standard stock
reports (Stock Balance, Stock Ledger)? Do they respect User Permissions on Warehouse, or does restricting them mean overriding the reports too?