Files
alla-allaos-fullstack/plans/task-l.1.md
phaichayon 771ebfc308 task-l.1
2026-06-22 10:59:31 +07:00

576 lines
8.2 KiB
Markdown

# Task L.1: CRM Multi-Role User Assignment & Scope Management
## Objective
Extend Task L authorization foundation so one user can hold multiple CRM role profiles within the same organization.
Business decision:
```txt
1 User = Many CRM Roles
```
Examples:
```txt
Sales Manager + Sales
CRM Admin + Department Manager
Sales Support + Marketing
```
This task adds role assignment persistence, assignment UI, and updates effective CRM access resolution.
---
# Background
Task L introduced:
```txt
crmRoleProfiles
memberships.branchScopeIds
memberships.productTypeScopeIds
resolved CRM access helper
CRM Settings > Roles
```
Current limitation:
```txt
membership.businessRole = single role
```
This is not enough for real business operation.
Task L.1 moves CRM role assignment into a dedicated model while keeping membership as organization access.
---
# Target Model
Membership remains organization-level access:
```txt
memberships
- userId
- organizationId
- role
- permissions
```
CRM role assignments become CRM-specific authorization rows:
```txt
crm_user_role_assignments
- id
- organizationId
- userId
- roleProfileId
- branchScopeMode
- branchScopeIds
- productTypeScopeMode
- productTypeScopeIds
- isPrimary
- isActive
- assignedBy
- assignedAt
- createdAt
- updatedAt
- deletedAt
```
---
# Scope L1.1 Schema
Add table:
```txt
crm_user_role_assignments
```
Fields:
```txt
id
organizationId
userId
roleProfileId
branchScopeMode
branchScopeIds
productTypeScopeMode
productTypeScopeIds
isPrimary
isActive
assignedBy
assignedAt
createdAt
updatedAt
deletedAt
```
Recommended scope modes:
```txt
all
selected
none
inherit
```
Unique constraint:
```txt
organizationId + userId + roleProfileId
```
Rules:
* one user can have many role profiles
* same role profile cannot be duplicated for the same user/org
* only one primary CRM role per user/org
* soft delete supported
* old `membership.businessRole` remains temporarily for compatibility
---
# Scope L1.2 Migration / Backfill
Backfill existing users.
For each membership:
```txt
membership.businessRole
```
create one CRM role assignment matching the role profile.
Rules:
* if businessRole has a matching `crmRoleProfiles.code`, create assignment
* if no matching role profile exists, skip and log warning
* set `isPrimary = true`
* branch/product scope from membership fields if available
* idempotent migration
* no duplicate assignments
---
# Scope L1.3 Effective CRM Access Resolver
Update resolved access helper.
Old:
```txt
membership.businessRole
+
membership.permissions
+
roleProfile.permissions
```
New:
```txt
membership
+
all active crm_user_role_assignments
+
all assigned crmRoleProfiles
+
direct membership.permissions
```
Permission behavior:
```txt
effectivePermissions = union(all roleProfile.permissions, membership.permissions)
```
Ownership behavior:
Use most permissive access among active role profiles:
```txt
own
team
branch
organization
all
```
Branch scope behavior:
```txt
if any role has all -> all
else union selected branchScopeIds
else none
```
Product type scope behavior:
```txt
if any role has all -> all
else union selected productTypeScopeIds
else none
```
Approval authority:
```txt
effectiveApprovalAuthority = union(all roleProfile.approvalAuthority)
```
Primary role:
```txt
used for display only
not permission limit
```
---
# Scope L1.4 User Assignment UI
Add page or tab:
```txt
CRM Settings
└─ User Role Assignments
```
or add tab inside existing user detail:
```txt
Users
└─ CRM Roles
```
Recommended UI:
```txt
User
Assigned CRM Roles
Branch Scope
Product Type Scope
Primary Role
Status
Actions
```
Actions:
```txt
Assign Role
Edit Scope
Set Primary
Deactivate Assignment
Reactivate Assignment
Remove Assignment
```
---
# Scope L1.5 Assignment Form
Fields:
```txt
User
Role Profile
Branch Scope Mode
Branches
Product Type Scope Mode
Product Types
Primary
Active
```
Behavior:
* role profile dropdown from active `crmRoleProfiles`
* branch options from `crm_branch`
* product type options from `crm_product_type`
* if scope mode = all, disable selected list
* if scope mode = selected, require at least one selected option
* if primary = true, unset other primary role assignments for same user/org
---
# Scope L1.6 API Routes
Add:
```txt
GET /api/crm/settings/user-role-assignments
POST /api/crm/settings/user-role-assignments
PATCH /api/crm/settings/user-role-assignments/[id]
DELETE /api/crm/settings/user-role-assignments/[id]
```
Optional:
```txt
GET /api/crm/settings/users/[userId]/role-assignments
```
All APIs must:
```txt
requireOrganizationAccess
requirePermission("crm.role.assignment.manage")
filter by organizationId
audit mutations
return user-safe errors
```
---
# Scope L1.7 Permissions
Add permissions:
```txt
crm.role.assignment.read
crm.role.assignment.create
crm.role.assignment.update
crm.role.assignment.delete
crm.role.assignment.manage
```
Grant default to:
```txt
system_admin
crm_admin
```
Optional read to:
```txt
sales_manager
department_manager
top_manager
```
---
# Scope L1.8 Audit
Audit entity type:
```txt
crm_user_role_assignment
```
Actions:
```txt
create
update
delete
activate
deactivate
set_primary
scope_update
```
Audit payload should include:
```txt
userId
roleProfileId
branchScopeMode
branchScopeIds
productTypeScopeMode
productTypeScopeIds
isPrimary
isActive
```
---
# Scope L1.9 Compatibility Layer
Keep `membership.businessRole` temporarily.
Rules:
* do not remove column yet
* do not rely on it when role assignments exist
* fallback to `membership.businessRole` only when user has no active CRM role assignment
* document deprecation
Add technical debt:
```txt
membership.businessRole is deprecated for CRM authorization after Task L.1.
```
---
# Scope L1.10 Server-Side Enforcement Migration
Update all CRM modules to use resolved multi-role access:
```txt
Leads
Enquiries
Customers
Contacts
Quotations
Approvals
Dashboard
Settings
Reports if present
```
Priority:
1. Leads / Enquiries
2. Quotations
3. Dashboard
4. Approval
5. Customers / Contacts
6. Settings
Rules:
* no UI-only enforcement
* all list/detail/action routes must check resolved CRM access
* pricing visibility must remain permission-based
---
# Scope L1.11 Verification Matrix
Create verification cases:
## Marketing + Sales Support
Expected:
```txt
can view leads
can create support quotation if permission exists
cannot approve
cannot view revenue unless granted
```
## Sales + Sales Manager
Expected:
```txt
can see own sales records
can see team records if manager role scope allows
can create quotation
can approve only if role profile has authority
```
## CRM Admin + Department Manager
Expected:
```txt
can manage CRM settings
can approve department-level workflow
can view configured analytics
```
## Sales with Crane + Bangkok Scope
Expected:
```txt
can see Crane Bangkok records
cannot see Solar Rayong records
```
---
# Scope L1.12 Documentation / ADR
Create ADR:
```txt
docs/adr/0014-crm-multi-role-user-assignment.md
```
Document:
```txt
1 user = many CRM roles
membership is organization access
crm_user_role_assignments is CRM authorization
permission union rule
scope union rule
primary role display-only rule
businessRole deprecation
```
Update:
```txt
docs/implementation/technical-debt.md
```
---
# Explicit Non-Scope
Do NOT implement:
```txt
Keycloak group sync
External identity role sync
Team hierarchy module
Advanced ABAC rules
Approval delegation
Temporary role expiration
Role request workflow
```
---
# Output
After completion, summarize:
1. Files Added
2. Files Modified
3. Schema Added
4. Migration / Backfill
5. Resolver Changes
6. UI Added
7. API Added
8. Permissions Added
9. Audit Added
10. Verification Result
11. Remaining Risks
---
# Definition of Done
Task L.1 is complete when:
* user can have multiple CRM role assignments
* each assignment can have branch/product scope
* one primary role can be selected
* effective permissions are unioned from all active roles
* effective branch/product scope is resolved correctly
* membership.businessRole is no longer primary CRM authorization source
* role assignment UI works
* role assignment API works
* all CRM critical routes use multi-role resolver
* audit logs are created for assignment changes
* ADR 0014 exists