# Step 3 (Department Lead Approval) - User Addition Flow Analysis ## Overview This document analyzes how Step 3 approvers (Department Lead) are added to the dealer claim workflow, covering both frontend and backend implementation. --- ## Backend Implementation ### 1. Request Creation Flow (`dealerClaim.service.ts`) #### Entry Point: `createClaimRequest()` - **Location**: `Re_Backend/src/services/dealerClaim.service.ts:37` - **Parameters**: - `userId`: Initiator's user ID - `claimData`: Includes optional `selectedManagerEmail` for user selection #### Step 3 Approver Resolution Process: **Phase 1: Pre-Validation (Before Creating Records)** ```typescript // Lines 67-87: Resolve Department Lead BEFORE creating workflow let departmentLead: User | null = null; if (claimData.selectedManagerEmail) { // User selected a manager from multiple options departmentLead = await this.userService.ensureUserExists({ email: claimData.selectedManagerEmail, }); } else { // Search Okta using manager displayName from initiator's user record departmentLead = await this.resolveDepartmentLeadFromManager(initiator); // If no manager found, throw error BEFORE creating any records if (!departmentLead) { throw new Error(`No reporting manager found...`); } } ``` **Phase 2: Approval Level Creation** ```typescript // Line 136: Create approval levels with pre-resolved department lead await this.createClaimApprovalLevels( workflowRequest.requestId, userId, claimData.dealerEmail, claimData.selectedManagerEmail, departmentLead // Pre-resolved to avoid re-searching ); ``` ### 2. Approval Level Creation (`createClaimApprovalLevels()`) #### Location: `Re_Backend/src/services/dealerClaim.service.ts:253` #### Step 3 Configuration: ```typescript // Lines 310-318: Step 3 definition { level: 3, name: 'Department Lead Approval', tatHours: 72, isAuto: false, approverType: 'department_lead' as const, approverId: departmentLead?.userId || null, approverEmail: departmentLead?.email || initiator.manager || 'deptlead@royalenfield.com', } ``` #### Approver Resolution Logic: ```typescript // Lines 405-417: Department Lead resolution else if (step.approverType === 'department_lead') { if (finalDepartmentLead) { approverId = finalDepartmentLead.userId; approverName = finalDepartmentLead.displayName || finalDepartmentLead.email || 'Department Lead'; approverEmail = finalDepartmentLead.email; } else { // This should never happen as we validate manager before creating records throw new Error('Department lead not found...'); } } ``` #### Database Record Creation: ```typescript // Lines 432-454: Create ApprovalLevel record await ApprovalLevel.create({ requestId, levelNumber: 3, levelName: 'Department Lead Approval', approverId: approverId, // Department Lead's userId approverEmail, approverName, tatHours: 72, status: ApprovalStatus.PENDING, // Will be activated when Step 2 is approved isFinalApprover: false, // ... other fields }); ``` ### 3. Department Lead Resolution Methods #### Method 1: `resolveDepartmentLeadFromManager()` (Primary) - **Location**: `Re_Backend/src/services/dealerClaim.service.ts:622` - **Flow**: 1. Get `manager` displayName from initiator's User record 2. Search Okta directory by displayName using `userService.searchOktaByDisplayName()` 3. **If 0 matches**: Return `null` (fallback to legacy method) 4. **If 1 match**: Create user in DB if needed, return User object 5. **If multiple matches**: Throw error with `MULTIPLE_MANAGERS_FOUND` code and list of managers #### Method 2: `resolveDepartmentLead()` (Fallback/Legacy) - **Location**: `Re_Backend/src/services/dealerClaim.service.ts:699` - **Priority Order**: 1. User with `MANAGEMENT` role in same department 2. User with designation containing "Lead"/"Head"/"Manager" in same department 3. User matching `initiator.manager` email field 4. Any user in same department (excluding initiator) 5. Any user with "Department Lead" designation (across all departments) 6. Any user with `MANAGEMENT` role (across all departments) 7. Any user with `ADMIN` role (across all departments) ### 4. Participant Creation #### Location: `Re_Backend/src/services/dealerClaim.service.ts:463` - Department Lead is automatically added as a participant when approval levels are created - Participant type: `APPROVER` - Allows department lead to view, comment, and approve the request --- ## Frontend Implementation ### 1. Request Creation (`ClaimManagementWizard.tsx`) #### Location: `Re_Figma_Code/src/dealer-claim/components/request-creation/ClaimManagementWizard.tsx` #### Current Implementation: - **No UI for selecting Step 3 approver during creation** - Step 3 approver is automatically resolved by backend based on: - Initiator's manager field - Department hierarchy - Role-based lookup #### Form Data Structure: ```typescript // Lines 61-75: Form data structure const [formData, setFormData] = useState({ activityName: '', activityType: '', dealerCode: '', // ... other fields // Note: No selectedManagerEmail field in wizard }); ``` #### Submission: ```typescript // Lines 152-216: handleSubmit() const claimData = { ...formData, templateType: 'claim-management', // selectedManagerEmail is NOT included in current wizard // Backend will auto-resolve department lead }; ``` ### 2. Request Detail View (`RequestDetail.tsx`) #### Location: `Re_Figma_Code/src/dealer-claim/pages/RequestDetail.tsx` #### Step 3 Approver Detection: ```typescript // Lines 147-173: Finding Step 3 approver const step3Level = approvalFlow.find((level: any) => (level.step || level.levelNumber || level.level_number) === 3 ) || approvals.find((level: any) => (level.levelNumber || level.level_number) === 3 ); const deptLeadUserId = step3Level?.approverId || step3Level?.approver_id || step3Level?.approver?.userId; const deptLeadEmail = (step3Level?.approverEmail || '').toLowerCase().trim(); // User is department lead if they match Step 3 approver const isDeptLead = (deptLeadUserId && deptLeadUserId === currentUserId) || (deptLeadEmail && currentUserEmail && deptLeadEmail === currentUserEmail); ``` #### Add Approver Functionality: - **Lines 203-217, 609, 621, 688, 701, 711**: References to `handleAddApprover` and `AddApproverModal` - **Note**: This appears to be generic approver addition (for other workflow types), not specifically for Step 3 - Step 3 approver is **fixed** and cannot be changed after request creation ### 3. Workflow Tab (`WorkflowTab.tsx`) #### Location: `Re_Figma_Code/src/dealer-claim/components/request-detail/WorkflowTab.tsx` #### Step 3 Action Button Visibility: ```typescript // Lines 1109-1126: Step 3 approval button {step.step === 3 && (() => { // Find step 3 from approvalFlow to get approverEmail const step3Level = approvalFlow.find((l: any) => (l.step || l.levelNumber || l.level_number) === 3); const step3ApproverEmail = (step3Level?.approverEmail || '').toLowerCase(); const isStep3ApproverByEmail = step3ApproverEmail && userEmail === step3ApproverEmail; return isStep3ApproverByEmail || isStep3Approver || isCurrentApprover; })() && ( )} ``` #### Step 3 Approval Handler: ```typescript // Lines 535-583: handleIOApproval() // 1. Finds Step 3 levelId from approval levels // 2. Updates IO details (ioNumber, ioRemark) // 3. Approves Step 3 using approveLevel() API // 4. Moves workflow to Step 4 (auto-processed) ``` --- ## Key Findings ### Current Flow Summary: 1. **Request Creation**: - User creates claim request via `ClaimManagementWizard` - **No UI for selecting Step 3 approver** - Backend automatically resolves department lead using: - Initiator's `manager` displayName → Okta search - Fallback to legacy resolution methods 2. **Multiple Managers Scenario**: - If Okta search returns multiple managers: - Backend throws `MULTIPLE_MANAGERS_FOUND` error - Error includes list of manager options - **Frontend needs to handle this** (currently not implemented in wizard) 3. **Approval Level Creation**: - Step 3 approver is **fixed** at request creation - Stored in `ApprovalLevel` table with: - `levelNumber: 3` - `approverId`: Department Lead's userId - `approverEmail`: Department Lead's email - `status: PENDING` (activated when Step 2 is approved) 4. **After Request Creation**: - Step 3 approver **cannot be changed** via UI - Generic `AddApproverModal` exists but is not used for Step 3 - Step 3 approver is determined by backend logic only ### Limitations: 1. **No User Selection During Creation**: - Wizard doesn't allow user to select/override Step 3 approver - If multiple managers found, error handling not implemented in frontend 2. **No Post-Creation Modification**: - No UI to change Step 3 approver after request is created - Would require backend API to update `ApprovalLevel.approverId` 3. **Fixed Resolution Logic**: - Department lead resolution is hardcoded in backend - No configuration or override mechanism --- ## Potential Enhancement Areas 1. **Frontend**: Add manager selection UI in wizard when multiple managers found 2. **Frontend**: Add "Change Approver" option for Step 3 (if allowed by business rules) 3. **Backend**: Add API endpoint to update Step 3 approver after request creation 4. **Backend**: Add configuration for department lead resolution rules 5. **Both**: Handle `MULTIPLE_MANAGERS_FOUND` error gracefully in frontend --- ## Related Files ### Backend: - `Re_Backend/src/services/dealerClaim.service.ts` - Main service - `Re_Backend/src/controllers/dealerClaim.controller.ts` - API endpoints - `Re_Backend/src/services/user.service.ts` - User/Okta integration - `Re_Backend/src/models/ApprovalLevel.ts` - Database model ### Frontend: - `Re_Figma_Code/src/dealer-claim/components/request-creation/ClaimManagementWizard.tsx` - Request creation - `Re_Figma_Code/src/dealer-claim/pages/RequestDetail.tsx` - Request detail view - `Re_Figma_Code/src/dealer-claim/components/request-detail/WorkflowTab.tsx` - Workflow display - `Re_Figma_Code/src/dealer-claim/components/request-detail/modals/DeptLeadIOApprovalModal.tsx` - Step 3 approval modal ### Documentation: - `Re_Backend/docs/CLAIM_MANAGEMENT_APPROVER_MAPPING.md` - Approver mapping rules