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_roletable — historical direct assignment, one row per user × role × date range. Deactivates when the row'sendDatepasses. user_app_roletable — direct assignment to anAppRole; the role brings its full set ofAppRolePermissionrows.user_app_groupmembership — 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_DELETEis also the role that means "HR Admin" —SecurityController.isHrAdmin()returns true exactly when the user hasHR_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 aDRAFTWO 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_DIRECTvariant 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 forFIXED_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.activeAreaIdsfromuser_area_permissionand from anyAppRolethat 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_permissionand role-based grants intoUserAccessProfileDTO.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.SecurityControllerchecks 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
@PostConstructcalls tosecurity.enforce…(). The arguments list the exactAppPermissionvalues that unlock the page. - For a button — search the XHTML for
rendered="#{security.has(...)}"orrendered="#{userOldView.hasRole('…')}". The first form names anAppPermission; 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_DELETEis HR Admin — that's the actual checkisHrAdmin()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 usessecurity.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
HrProfileto render the form. - My Stuff → Pending Approvals —
ATTENDANCE_*permission or department-manager status. - Operations → Move Requests —
STOCK_MOVE_REQUEST,STOCK_MOVE_USER, orSTOCK_MOVE_ADMIN. - Operations → Stock Counts —
STOCK_COUNT_USER,STOCK_COUNT_ADMIN, or matchingUserWarehousePermissionTypeEnum. - Operations → Stock Check — any logged-in user (no role gate).
- Operations → Purchase Orders —
PURCHASE_ORDER_USER. - Operations → Local Receipts —
CREATE_LOCAL_RECEIPTorPROCESS_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_USERorSTOCK_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_READor any type-specificWO_<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 theUserAccessProfileDTOand exposesisAdmin(),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— themanager/tempManager/tempManagerDatefields.