# Task D.1: Enquiry Assignment and CRM Role Stabilization ## 1. Files Added - `src/app/api/crm/enquiries/[id]/_schemas.ts` - `src/app/api/crm/enquiries/[id]/assign/route.ts` - `src/app/api/crm/enquiries/[id]/reassign/route.ts` - `src/features/crm/enquiries/components/enquiry-assignment-dialog.tsx` - `drizzle/0008_clean_justin_hammer.sql` - `drizzle/meta/0008_snapshot.json` ## 2. Files Modified - `src/db/schema.ts` - `src/lib/auth/rbac.ts` - `src/app/dashboard/crm/enquiries/page.tsx` - `src/app/dashboard/crm/enquiries/[id]/page.tsx` - `src/features/crm/enquiries/api/types.ts` - `src/features/crm/enquiries/api/service.ts` - `src/features/crm/enquiries/api/mutations.ts` - `src/features/crm/enquiries/server/service.ts` - `src/features/crm/enquiries/components/enquiry-columns.tsx` - `src/features/crm/enquiries/components/enquiries-table.tsx` - `src/features/crm/enquiries/components/enquiry-listing.tsx` - `src/features/crm/enquiries/components/enquiry-detail.tsx` - `src/features/crm/enquiries/components/enquiry-cell-action.tsx` - `src/features/users/api/types.ts` - `src/features/users/schemas/user.ts` - `src/features/users/components/user-form-sheet.tsx` - `src/app/api/users/_lib.ts` - `src/app/api/users/route.ts` - `src/app/api/organizations/route.ts` - `src/features/foundation/auth-context/service.ts` ## 3. Schema Added Added assignment fields to `crm_enquiries`: - `assigned_to_user_id` - `assigned_at` - `assigned_by` - `assignment_remark` Rules implemented: - assignee must belong to the same organization - assigner is the current user - latest assignment timestamp is persisted - assignment remark is optional ## 4. API Routes Added - `POST /api/crm/enquiries/[id]/assign` - `POST /api/crm/enquiries/[id]/reassign` Payload: ```ts { assignedToUserId: string; remark?: string; } ``` Behavior: - requires organization access - enforces `crm.enquiry.assign` or `crm.enquiry.reassign` - validates assignee organization membership - rejects assign on already-assigned enquiry - rejects reassign on unassigned enquiry ## 5. Permissions Added - `crm.enquiry.assign` - `crm.enquiry.reassign` CRM business-role set was also stabilized around: - `sales_manager` - `sales` - `sales_support` - `department_manager` - `top_manager` Legacy IT-CENTER business roles were removed from active runtime paths and defaults. ## 6. UI Added Enquiry detail now supports: - `Assign Sales` - `Reassign Sales` - assigned sales metadata display Enquiry list now shows: - `Assigned Sales` column Assignment dialog now includes: - `Sales User` - `Remark` The sales-user dropdown is populated from organization memberships instead of hardcoded values. ## 7. Audit Integration Assignment writes audit logs under: - `entityType = crm_enquiry` Actions added: - `assign` - `reassign` Audit payload shape: - `beforeData.oldAssignedToUserId` - `afterData.newAssignedToUserId` - `afterData.remark` ## 8. Membership / Permission Stabilization Workspace membership management now uses CRM-aligned business roles instead of the old template roles. Updated areas: - user API types and validation - membership defaults - organization-management fallbacks - auth-context business-role fallback ## 9. Remaining Risks - current `sales` access still operates at organization scope; there is not yet a server-enforced “own or assigned only” data policy - old database rows that still carry removed legacy business-role strings may need a one-time data backfill if they exist in a real environment - assignable-user filtering currently accepts organization admins plus sales-oriented roles; if future CRM staffing rules become stricter, that policy should move into a dedicated assignment rule layer ## 10. Verification - `npx tsc --noEmit` - `npx oxlint` on changed Task D.1 files