Complete QA Documentation, Permission Framework, and Feature Matrix for WCW CRM v1.0
| Role ID | Role Name | Description | System Type | Status |
|---|---|---|---|---|
| 1 | Admin | Super admin with full system access | SUPER_ACCESS | Active |
| 2 | Sales Rep | Sales representative with customer/opportunity access | STANDARD | Active |
| 3 | Inside Rep | Inside representative with limited access | STANDARD | Active |
| 4 | Manager | Manager with super admin access | SUPER_ACCESS | Active |
Super Access Role IDs: [1, 4] (Admin, Manager) Standard Sales Role IDs: [2, 3] (Sales Rep, Inside Rep)
Path: src/app/features/User Management/
Routes:
/users (Users List with CRUD)/rolesCRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| Create User | /users/create | POST | ✅ |
| List Users | /users/list | GET | ✅ |
| Datatable Users | /users/datatable | GET | ✅ |
| Update User | /users/update/{userId} | PUT | ✅ |
| Delete User | /users/delete/{userId} | DELETE | ✅ |
| Get User Roles | /roles/list | GET | ✅ |
Permissions Enforced:
Add User - Controls new user creationEdit User - Controls user modificationDelete User - Controls user deletionView User - Controls user view access (Route permission)View Role - Controls role panel accessAdd Role - Controls role creationEdit Role - Controls role editingDelete Role - Controls role deletionPermission Check Pattern:
const addPermission = auth?.user?.roles?.some((role) =>
role.permissions?.some((p) => p.name === 'Add User')
);
Path: src/app/features/Customers/
Route: /customers
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| List Customers | /customers/list?params | GET | ✅ |
| Show Customer | /customers/show/{id} | GET | ✅ |
| Create Customer | /customers/create | POST | ✅ |
| Update Customer | /customers/update/{id} | PUT | ✅ |
| Delete Customer | /customers/delete/{id} | DELETE | ✅ |
| Get Customer Meetings | /customers/meetings/{customerId} | GET | ✅ |
| Get Customer Contacts | /customers/contacts/{customerId} | GET | ✅ |
| Get Customer Tasks | /customers/tasks/{customerId} | GET | ✅ |
| Convert Prospect Request | /prospects/convert-request/{prospectId} | POST | ✅ |
| Convert Prospect by Task | /prospects/convert/{taskId} | POST | ✅ |
| Get PPro Requests | /prospects/requests | GET | ✅ |
Sub-features:
Access Control:
Path: src/app/features/Opportunity/
Route: /opportunities
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| List Opportunities | /opportunities/list?params | GET | ✅ |
| Show Opportunity | /opportunities/show/{id} | GET | ✅ |
| Create Opportunity | /opportunities/create | POST | ✅ |
| Update Opportunity | /opportunities/update/{id} | PUT | ✅ |
| Delete Opportunity | /opportunities/delete/{id} | DELETE | ✅ |
| Update Status | /opportunities/status/update/{id} | PUT | ✅ |
| Get Analytics | /opportunities/analytics?userId={id} | GET | ✅ |
Sub-features:
Role Requirements:
keepVisibleWhenViewingOtherRep: truePath: src/app/features/Tasks/ and src/app/features/Opportunity/services/taskApi.tsx
Routes:
/tasks - Task List (permission: ‘non-admin’)/team-requests - Team Requests/PPro Tasks (all users)CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| List Tasks | /tasks/list?params | GET | ✅ |
| Show Task | /tasks/show/{id} | GET | ✅ |
| Create Task | /tasks/create | POST | ✅ |
| Update Task | /tasks/update/{id} | PUT | ✅ |
| Delete Task | /tasks/delete/{id} | DELETE | ✅ |
| Assign Task | /tasks/assign/{id} | PUT | ✅ |
Task Types:
Task Properties:
| Taskable Type: Customer | Opportunity |
Role Requirements:
Path: src/app/features/Calendar/
Route: /calendar
Status: ⚠️ BLOCKER - Hardcoded mock data (September 2025)
Features:
Path: src/app/pages/schedule/
Routes:
/schedule - Weekly Schedule (permission: ‘non-admin’)/day-schedule - Daily Schedule (permission: ‘non-admin’)Features:
Role Requirements:
Path: src/app/features/DailyAlerts/
Route: /daily-alerts (permission: ‘non-admin’)
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| Get Notifications | /notifications/list | GET | ✅ |
| Unread Count | (via API) | GET | ✅ |
| Mark Read | (via mutation) | PATCH | ✅ |
Role Requirements:
Path: src/app/features/Commitments/
Route: /commitments
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| Get Commitments | /commitments/list?params | GET | ✅ |
| Create Commitment | /commitments/create | POST | ✅ |
| Update Commitment | /commitments/update/{id} | PUT | ✅ |
| Delete Commitment | /commitments/delete/{id} | DELETE | ✅ |
Features:
Role Requirements:
Path: src/app/features/Opportunity/services/targetApi.tsx
Route: /targets
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| List Targets | /targets/list?params | GET | ✅ |
| Create Target | /targets/create | POST | ✅ |
| Update Target | /targets/update/{id} | PUT | ✅ |
| Delete Target | /targets/delete/{id} | DELETE | ✅ |
| Show Target | /targets/show/{id} | GET | ✅ |
Features:
Role Requirements:
Path: src/app/features/Contacts/
Route: /contacts
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| List Contacts | /contacts/list?params | GET | ✅ |
| Show Contact | /contacts/show/{id} | GET | ✅ |
| Create Contact | /contacts/create | POST | ✅ |
| Update Contact | /contacts/update/{id} | PUT | ✅ |
| Delete Contact | /contacts/delete/{id} | DELETE | ✅ |
| Get Contact Roles | /contact-roles/list | GET | ✅ |
Sub-features:
Role Requirements:
Path: src/app/features/Groups/
Route: /groups
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| List Groups | /groups/list?userId={id} | GET | ✅ |
| Show Group | /groups/show/{id} | GET | ✅ |
| Create Group | /groups/create | POST | ✅ |
| Update Group | /groups/update/{id} | PUT | ✅ |
| Delete Group | /groups/delete/{id} | DELETE | ✅ |
Features:
Operations Identified:
Path: src/app/features/GlobalSettings/
Route: /global-settings
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| List Settings | /global-settings/opportunity/list | GET | ✅ |
| Add Setting | /global-settings/opportunity/create | POST | ✅ |
| Update Setting | /global-settings/opportunity/update | PUT | ✅ |
| Delete Setting | /global-settings/opportunity/delete/{id} | DELETE | ✅ |
| Update Meeting Checklist | /global-settings/meeting-checklists/update | PUT | ✅ |
Features:
Role Requirements:
Path: src/app/features/User Management/Roles/
Route: /roles (Commented out)
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| List Roles | /roles/list | GET | ✅ |
| Create Role | /roles/create | POST | ✅ |
| Update Role | /roles/update/{roleId} | PUT | ✅ |
| Delete Role | /roles/delete/{roleId} | DELETE | ✅ |
| Get Permissions | /roles/permissions | GET | ✅ |
Features:
Permission Grouping: Permissions are organized by feature sections:
Path: src/app/features/Dashboard/
Route: /dashboard
/dashboard/cities - City details/dashboard/rep/{repId} - Rep detailsOperations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| Get Regions | /dashboard/companies | GET | ✅ |
| Net New Customers (Region) | /dashboard/region/net-new-customers/{regionId} | GET | ✅ |
| Net New Customers (Rep) | /dashboard/rep/net-new-customers/{userId} | GET | ✅ |
| Get Rep Details | /dashboard/rep/{userId}?regionId={id} | GET | ✅ |
Features:
Path: src/app/features/Subscription/
Route: /subscription
CRUD Operations:
| Operation | Endpoint | Method | Status |
|———–|———-|——–|——–|
| Get Plans | /subscription/plans | GET | ⚠️ |
| Create Subscription | /subscription/create | POST | ⚠️ |
Status: ⚠️ BLOCKER - Verification middleware disabled (NO REVENUE PROTECTION)
Features:
User Management Permissions:
Add UserEdit UserDelete UserView UserAdd RoleEdit RoleDelete RoleView RoleLikely Permission Format:
Based on PermissionBody component grouping by feature section, permissions follow pattern:
[ACTION] [FEATURE]
Where ACTION: Add | Edit | Delete | View
Where FEATURE: User | Role | Customer | Opportunity | ... (19+ features)
Based on module analysis, likely permissions include:
User Management (8):
Customers (4):
Opportunities (4):
Tasks (4):
Meetings (4):
Commitments (4):
Targets (4):
Groups (4):
Contacts (4):
Global Settings (2):
Total Estimated Permissions: 40+ permissions across 10+ feature groups
SUPER_ACCESS_ROLE_IDS = [1, 4]
GLOBAL_SETTINGS_MANAGEMENT_ROLES = [1, 4, 4] // Admin, Manager, Manager
Access Includes:
SALES_REP_ROLE_ID = 2
Sidebar Accessible Paths:
Keep Visible When Viewing Other Rep: YES
INSIDE_REP_ROLE_ID = 3
Sidebar Accessible Paths:
Viewing Other Sales Rep Context:
isViewingOtherRepContext(rep_id, current_user_id) = rep_id !== current_user_id
Restrictions When Viewing Other Rep:
Allowed Paths When Viewing Other Rep:
MANAGER_REP_CONTEXT_ALLOWED_PATHS)File: src/app/router/middlewares/ProtectedRoute.tsx
<ProtectedRoute permission={route.permission}>
{children}
</ProtectedRoute>
Route Permissions Used:
'View User' - Users list route'View Role' - Roles list route (commented out)'non-admin' - Tasks, Schedule, Daily Alerts routesPattern:
const addPermission = auth?.user?.roles?.some((role) =>
role.permissions?.some((p) => p.name === 'Add User')
);
{addPermission && <AddButton />}
Implemented in:
File: src/app/shared/components/datatables/Table2.tsx
interface UsersTable {
addPermission: boolean;
editPermission: boolean;
deletePermission: boolean;
}
Table Features Controlled:
File: src/app/shared/config/sidebarAccess.config.ts
const getSidebarAccessDefinition = (path: string): SidebarAccessDefinition
Menu Visibility by Role:
All API calls include:
headers: {
Authorization: `Bearer ${getState().auth.token}`,
'Content-Type': 'application/json' // (where applicable)
}
File: src/app/slices/baseApiSlice.tsx
export const baseApi = createApi({
baseUrl: backendApiAddress,
tagTypes: [
'Auth', 'Users', 'Roles', 'Customer', 'Opportunity',
'Tasks', 'Meeting', 'Department', 'GlobalSetting', 'Target',
'LoyaltyFlags', 'Contact', 'ContactRole', 'ProductDepartment',
'Schedule', 'Commitment', 'Dashboard', 'Regions', 'Groups',
'Notifications'
]
})
| Gap | Location | Impact | Status |
|---|---|---|---|
| No token refresh mechanism | Global | Session expiration | ⚠️ CRITICAL |
| Subscription verification disabled | Subscription module | No revenue protection | ⚠️ CRITICAL |
| Calendar mock data hardcoded | Calendar module | Data accuracy | ⚠️ BLOCKER |
| Tasks always show full permissions | Tasks page | Should check permissions | ⚠️ INCOMPLETE |
| No granular permission caching | Global | Performance issue | ⚠️ MEDIUM |
| Admin row restriction inconsistent | Table components | Privilege escalation risk | ⚠️ MEDIUM |
Routes accessible via URL without specific checks:
/customers, /opportunities, /contactsRole → has many → Permissions
User → has many → Roles → has many → Permissions
interface IPermission {
id: number;
name: string; // format: "[ACTION] [FEATURE]"
}
interface IRole {
id: number;
name: string;
description: string;
permissions: IPermission[] | null;
}
interface IUser {
id: number;
roles: IRole[];
// ... other fields
}
| Module | Status | CRUD | Permissions | Permission Check | API Protected |
|---|---|---|---|---|---|
| Authentication | ✅ | N/A | N/A | N/A | ✅ |
| Users | ✅ | ✅ | Yes (4) | ✅ Component | ✅ |
| Roles | ✅ | ✅ | Yes (4) | ✅ Component | ✅ |
| Customers | ✅ | ✅ | No | ❌ None | ✅ |
| Opportunities | ✅ | ✅ | No | ❌ None | ✅ |
| Tasks | ✅ | ✅ | No | ⚠️ Incomplete | ✅ |
| Meetings | ✅ | ✅ | No | ⚠️ Context-based | ✅ |
| Contacts | ✅ | ✅ | No | ❌ None | ✅ |
| Groups | ✅ | ✅ | No | ❌ None | ✅ |
| Calendar | ⚠️ | N/A | No | ❌ None | ✅ |
| Schedule | ✅ | Read | No | ⚠️ Role-based | ✅ |
| Global Settings | ✅ | ✅ | No | ⚠️ Role-based | ✅ |
| Commitments | ✅ | ✅ | No | ❌ None | ✅ |
| Targets | ✅ | ✅ | No | ❌ None | ✅ |
| Daily Alerts | ✅ | Read | No | ⚠️ Role-based | ✅ |
| Dashboard | ✅ | Read | No | ✅ Auth | ✅ |
| Subscription | ⚠️ | ⚠️ | No | ❌ DISABLED | ⚠️ |
/tests/modules/Base API Service Tags:
Codebase Location: /src/app/slices/baseApiSlice.tsx