4.2 Branch Hierarchy
Branches model a tenant’s organizational structure. Every tenant has its own branch tree; branch IDs and hierarchy are never shared across tenants.
Data model
BranchesTable uses CakePHP’s Tree behavior with parent_id, lft, and rght. parent_id expresses the business relationship; lft and rght are maintained by the behavior for efficient ancestor and descendant queries. Do not assign nested-set columns directly.
A branch also has a branch type, public ID, status/soft-delete metadata, and associations used by members, roles, gatherings, officers, and plugin records. The exact schema is defined by tenant migrations and BranchesTable, not by this guide.
Working with the tree
Use Tree behavior operations and existing table helpers to retrieve children, descendants, ancestors, and formatted branch lists. When moving a branch, patch parent_id and save through the table so the nested set is updated transactionally. Use recover() only as an explicit repair operation after diagnosing corrupt tree metadata.
Branch-scoped authorization
Branch hierarchy is also a permission boundary. Policies may allow an action on one branch and its descendants without granting tenant-wide access. Query endpoints must use applyScope() or an existing scoped finder; filtering an already-loaded list in PHP risks leaking counts, exports, or associated records.
KmpIdentityInterface and PermissionsLoader expose policy/permission information used by the authorization layer. Domain code should ask the policy layer whether an operation is allowed rather than infer access from branch ancestry alone.
Multi-tenant invariants
- Resolve and bind the tenant before loading the tree.
- Never join a platform table to
branches. - Do not put tenant identifiers into the branch hierarchy; the database connection supplies that boundary.
- Treat cached branch paths and lists as tenant-scoped data.
- Validate that referenced parent, type, and related records come from the same active tenant connection.
Primary code
app/src/Model/Entity/Branch.phpapp/src/Model/Table/BranchesTable.phpapp/src/Controller/BranchesController.phpapp/src/Policy/BranchPolicy.phpapp/src/Policy/BranchesTablePolicy.phpapp/src/KMP/GridColumns/BranchesGridColumns.php
Officer reporting relationships are separate tenant configuration layered on this tree; see Office reporting structure.