Knowledge Base

Roles and permissions field definitions

Edit

Roles and permissions field definitions

What this is

A reference for every role and permission in mywork, what each one unlocks, and how a user actually gets one. Use this article as the canonical source whenever a process guide says "X requires the Y permission" — the meaning of that permission lives here.

The model has three independent dimensions, plus two derived statuses. Skim the section that matches your question:

  • Roles / permissions — what kind of action you can perform. (§1)
  • Areas — where in the warehouse you can act. (§2)
  • Products — which products you can transact on. (§3)
  • Department manager — derived from a foreign key, not a permission. (§4)
  • Stand-in / temp manager — date-scoped fall-back routing. (§4)

A user is allowed to do something only if all the dimensions that apply to that action say yes — having STOCK_MOVE_USER does not let you transfer stock in a warehouse area you do not have access to.

1. Roles and permissions (the AppPermission enum)

How a user gets a permission

A user's effective permission set is the union of grants from five sources, all merged on login into a UserAccessProfileDTO:

  • Legacy user_role table — historical direct assignment, one row per user × role × date range. Deactivates when the row's endDate passes.
  • user_app_role table — direct assignment to an AppRole; the role brings its full set of AppRolePermission rows.
  • user_app_group membership — group → group's app roles → permissions. Groups are managed in the user-management screens.
  • Active job position (via HrJobHistory) — the job position carries app roles that cascade permissions. HR-managed; assigning someone to a new position automatically grants the matching permissions.
  • Per-warehouse / per-area / per-product permission tables — user_warehouse_permission, user_area_permission, user_product_permission.

Permissions cache for the session. If an admin grants you a new role mid-session, you have to log out and back in for it to take effect.

Site Admin — the umbrella

ADMIN is the global override. SecurityController.has() short-circuits to true when sessionBean.isAdmin() is true, regardless of which specific permission is being checked. Use sparingly; almost every documented capability below is also reachable through a more granular role.

HR module

  • HR_READ — read-only access to employee profiles, documents, and HR-side reports.
  • HR_WRITE — also create and edit profiles, upload documents.
  • HR_DELETE — also delete documents/profiles. HR_DELETE is also the role that means "HR Admin" — SecurityController.isHrAdmin() returns true exactly when the user has HR_DELETE.
  • HR_SALARY_READ / HR_SALARY_WRITE — view / edit salary data. Separate from the rest of HR so payroll-restricted users can be barred from rates without losing profile access.

Attendance module (leave, OT, time-tracking)

  • ATTENDANCE_VIEW — view attendance pages and reports.
  • ATTENDANCE_CREATE — create or approve attendance records, schedule changes, manual adjustments.
  • ATTENDANCE_DELETE — delete attendance records.
  • ATTENDANCE_ADMIN — full module access (all of the above plus configuration).
  • REMOTE_ATTENDANCE — clock in / out remotely from the dashboard (instead of from a fixed terminal).

Department managers also get read access to their team's leave without holding any ATTENDANCE_* permission (SecurityController.canViewTeamLeave()).

Work Orders

Permissions exist in two flavours: generic (across all WO types) and type-specific (for one of REPAIR, PRODUCTION, INTERNAL, PROJECT).

  • WO_ADMIN — umbrella. Full access across all four types.
  • WO_<TYPE>_ADMIN — full access within that type (e.g. WO_REPAIR_ADMIN).
  • WO_CREATE / WO_<TYPE>_CREATE — create work orders from templates.
  • WO_<TYPE>_CREATE_BLANK — also create from scratch (no template).
  • WO_READ / WO_<TYPE>_READ — view WOs and their status.
  • WO_WRITE / WO_<TYPE>_WRITE — edit steps, log progress.
  • WO_DELETE / WO_<TYPE>_DELETE — cancel or delete.
  • WO_RELEASE / WO_<TYPE>_RELEASE — release a DRAFT WO to the floor.
  • WO_FORCE_COMPLETE — force-complete a step bypassing physical validation. High-risk; reserved for supervisors and admins.

Resolution order (SecurityController.canDoWo): WO_ADMIN → WO_<TYPE>_ADMIN → generic permission → type-specific permission. The first one that matches grants access.

Creator override: anyone can write, delete, or release a WO they themselves created, even without the matching permission. This keeps initiators unblocked while their request is in early states.

Stock & inventory

  • STOCK_MOVE_REQUEST — create or accept stock-move requests.
  • STOCK_MOVE_USER — perform stock moves (collect + dispatch items assigned to you).
  • STOCK_MOVE_ADMIN — assign movers, filter all requests, force-close.
  • STOCK_TRANSFER / STOCK_TRANSFER_DIRECT — transfer between warehouses; the _DIRECT variant skips the request workflow.
  • STOCK_COUNT_ADMIN — create new stock counts; manage counters in your area.
  • STOCK_COUNT_USER — perform counts assigned to you.
  • STOCK_COUNT_ADJUST_CASE — make adjustments from count results (write-down or write-up).
  • VIEW_ALL_PRODUCTS — see every product, ignoring per-product gating.
  • CREATE_LOCATION / LOCATION_PRINT — create / print warehouse-location labels.
  • CUSTOM_ASSEMBLIES / ASM_ADMIN — assembly creation and admin.
  • REQ_ADJ_* — separate request-adjustment permissions for FIXED_ASSET, DAMAGED, PERSONAL_INV, PERSONAL_CONS, CONSUMABLES, PACKAGING. Each gates a different adjustment reason.
  • UNLEASHED_ADJUSTMENT — senior role: push an adjustment through to Unleashed (the upstream system) directly from mywork.

Sales, purchases, repairs

  • SALES — general access to sales-related pages.
  • SALES_ORDERS_ADMIN — full access to Sales Orders.
  • PURCHASE_ORDER_USER — view and process purchase orders.
  • SALES_SHIPMENT_USER / STOCK_SHIPMENTS_USER — sales-shipment / stock-shipment access.
  • CREDIT_NOTE_USER — credit-note workflows.
  • RO_CREATE — create repair orders (RMAs).
  • RO_APPROVE — approve repair orders.
  • RO_RECEIVING / REPAIR_RECEIVING — receive incoming repairs.
  • REPAIR_ADMIN — approve repair orders at the workflow level.
  • REPAIRER — perform actual repair tasks (the floor side of repair WOs).

Other module-specific

  • PRODUCT_READ / PRODUCT_WRITE — product master-data.
  • BOM_READ / BOM_WRITE — bill of materials.
  • MARKETING_READ / MARKETING_WRITE / MARKETING_DELETE — marketing content.
  • QMS_ADMIN / QMS_CREATE — QMS doc module.
  • CHAT_USE / CHAT_GROUP_CREATE / CHAT_MODERATOR — internal chat.
  • ACCOUNTING — accounting menu access.
  • DEVELOPER / TESTING — internal-only roles for build/staging access.
  • ASSEMBLER — low-level assembler floor access.

2. Areas (warehouse zones)

Areas are physical zones in a warehouse — Production, Stores, Goods Receiving, Dispatch, etc. Stock moves, stock counts, and product-location operations are gated per area.

  • A user's allowed areas are loaded into UserAccessProfileDTO.activeAreaIds from user_area_permission and from any AppRole that includes area grants.
  • Operations on a location filter by area: SecurityController.canAccessArea(areaId) is checked before the user can pick an item or post a count there.
  • Site Admin and VIEW_ALL_AREAS-style permissions bypass the gate.

If a user has the right action permission but the wrong area, the action will fail with a "no access to this area" message — don't troubleshoot it as a role problem.

3. Products

Products can be gated per-user in the same way as areas — a user might have full stock-count permissions but only see specific product lines.

  • Loaded from user_product_permission and role-based grants into UserAccessProfileDTO.activeProductGuids.
  • Checked via SecurityController.canAccessProduct(productGuid).
  • The most common use is restricting a contractor or reseller-staff account to only their assigned product range.

4. Department manager and stand-in (derived, not permissions)

Manager status is not an AppPermission. It is computed from foreign keys on HrDepartment:

  • HrDepartment.manager (FK to HrProfile) — the permanent department manager.
  • HrDepartment.tempManager (FK to HrProfile) — the temporary cover for today only. The 06:00 scheduler sets this when the real manager goes on approved leave; it auto-clears when their leave ends.
  • HrDepartment.tempManagerDate — the date the temp assignment is valid for. SecurityController checks this against today; tomorrow's stand-in does not see today's queue.

A user is "any-department manager" if they manage at least one department directly or one of its parents recursively, or they are HR Admin. That status unlocks the manager-only views:

  • Pending Approvals — leave + OT + OT-cancel inbox for everyone in the chain.
  • Team Schedules — view and edit shift templates for the team.
  • Team Organigram — the org tree with the user's branch highlighted.
  • Create Leave for Employee — submit auto-approved leave on behalf of a team member.

Stand-in routing is automatic: when a leave / OT request is submitted and the direct manager has a tempManager set for today, the request routes to the temp manager instead. See Manage your team's leave for the chain-manager detail.

5. Reading the gates in the wild

When a process guide says "this action requires X permission", find the actual gate:

  • For a view — open the backing bean and look for @PostConstruct calls to security.enforce…(). The arguments list the exact AppPermission values that unlock the page.
  • For a button — search the XHTML for rendered="#{security.has(...)}" or rendered="#{userOldView.hasRole('…')}". The first form names an AppPermission; the second is a legacy string-named role.
  • For a service-side action — follow security.has(...) calls in the EJB. Often a single permission gates both the button and the underlying service call.

If you find a gate that is not described in this article (or in a process guide that uses it), update this article and the relevant guide in the same change.

6. Common gotchas

  • HR_DELETE is HR Admin — that's the actual check isHrAdmin() performs. There is no separate "HR Admin" permission row.
  • Site Admin bypasses everything — including soft gates like "only the assigned counter can complete a count". Be careful when an admin acts on behalf of a regular user; some workflows record the actor and the record will say Admin rather than the team member.
  • Legacy vs new check styles — older view beans use sessionBean.containsRole("StockMoveUser") (string name); newer code uses security.has(AppPermission.STOCK_MOVE_USER) (enum). They reach the same underlying grant table but the strings can drift. If a permission seems to work in one view and not another, that mismatch is usually why.
  • Permission cache — set on login; only clearCache() (logout + login, or admin-triggered) refreshes. "I just got the role and it doesn't work yet" always means a cache issue.
  • Job-position cascade is one-way — assigning a position adds permissions; the same permissions stay if the user later moves to a position that doesn't have them. To revoke, use the explicit role tables.
  • Area + product gates are AND, not OR — having permission in Area A and access to Product X does not let you transact Product X in Area B. Both gates evaluate independently for each row.

7. Quick reference — what unlocks what

For each module, the minimum permission set to enter the main page (additional permissions gate specific buttons inside):

  • My Stuff → My Leave — none beyond a normal account; needs an HrProfile to render the form.
  • My Stuff → Pending Approvals — ATTENDANCE_* permission or department-manager status.
  • Operations → Move Requests — STOCK_MOVE_REQUEST, STOCK_MOVE_USER, or STOCK_MOVE_ADMIN.
  • Operations → Stock Counts — STOCK_COUNT_USER, STOCK_COUNT_ADMIN, or matching UserWarehousePermissionTypeEnum.
  • Operations → Stock Check — any logged-in user (no role gate).
  • Operations → Purchase Orders — PURCHASE_ORDER_USER.
  • Operations → Local Receipts — CREATE_LOCAL_RECEIPT or PROCESS_LOCAL_RECEIPT (both required for full create-and-receive).
  • Operations → Local Shipments — warehouse-staff access (page-level access; no explicit role).
  • Operations → Sales Shipments — SALES_SHIPMENT_USER or STOCK_SHIPMENTS_USER.
  • Operations → External Service Shipments — same as repair-order shipments; no explicit role gate.
  • Operations → Aramex — same gate as the parent shipment view; no separate permission.
  • Operations → Locations / Product Locations — any logged-in user; specific actions need LOCATION_PRINT, STOCK_COUNT_ADMIN, etc.
  • Operations → SerialNumber Location — read-only for any user; moves go through the picking dialog.
  • Work Orders — WO_READ or any type-specific WO_<TYPE>_READ; create / write / release each needs the matching permission.

8. Where this lives in code

  • src/main/java/com/solarmd/mywork/business/system/controller/SecurityController.java — the central gate (enforce…, has, canDoWo, manager checks).
  • src/main/java/com/solarmd/mywork/business/system/entity/AppPermission.java — the enum of every permission name.
  • src/main/java/com/unleashed/api/views/user/SessionBean.java — caches the UserAccessProfileDTO and exposes isAdmin(), containsRole(name), hasAreaAccess(), hasProductAccess().
  • src/main/java/com/unleashed/api/ejb/facade/UserSecurityFacade.java — loads the five sources of permissions on login.
  • src/main/java/com/solarmd/mywork/business/hr/enitity/HrDepartment.java — the manager / tempManager / tempManagerDate fields.