10 KiB
10 KiB
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 IDclaimData: Includes optionalselectedManagerEmailfor user selection
Step 3 Approver Resolution Process:
Phase 1: Pre-Validation (Before Creating Records)
// 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
// 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:
// 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:
// 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:
// 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:
- Get
managerdisplayName from initiator's User record - Search Okta directory by displayName using
userService.searchOktaByDisplayName() - If 0 matches: Return
null(fallback to legacy method) - If 1 match: Create user in DB if needed, return User object
- If multiple matches: Throw error with
MULTIPLE_MANAGERS_FOUNDcode and list of managers
- Get
Method 2: resolveDepartmentLead() (Fallback/Legacy)
- Location:
Re_Backend/src/services/dealerClaim.service.ts:699 - Priority Order:
- User with
MANAGEMENTrole in same department - User with designation containing "Lead"/"Head"/"Manager" in same department
- User matching
initiator.manageremail field - Any user in same department (excluding initiator)
- Any user with "Department Lead" designation (across all departments)
- Any user with
MANAGEMENTrole (across all departments) - Any user with
ADMINrole (across all departments)
- User with
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:
// Lines 61-75: Form data structure
const [formData, setFormData] = useState({
activityName: '',
activityType: '',
dealerCode: '',
// ... other fields
// Note: No selectedManagerEmail field in wizard
});
Submission:
// 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:
// 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
handleAddApproverandAddApproverModal - 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:
// 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;
})() && (
<Button onClick={() => setShowIOApprovalModal(true)}>
Approve and Organise IO
</Button>
)}
Step 3 Approval Handler:
// 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:
-
Request Creation:
- User creates claim request via
ClaimManagementWizard - No UI for selecting Step 3 approver
- Backend automatically resolves department lead using:
- Initiator's
managerdisplayName → Okta search - Fallback to legacy resolution methods
- Initiator's
- User creates claim request via
-
Multiple Managers Scenario:
- If Okta search returns multiple managers:
- Backend throws
MULTIPLE_MANAGERS_FOUNDerror - Error includes list of manager options
- Frontend needs to handle this (currently not implemented in wizard)
- Backend throws
- If Okta search returns multiple managers:
-
Approval Level Creation:
- Step 3 approver is fixed at request creation
- Stored in
ApprovalLeveltable with:levelNumber: 3approverId: Department Lead's userIdapproverEmail: Department Lead's emailstatus: PENDING(activated when Step 2 is approved)
-
After Request Creation:
- Step 3 approver cannot be changed via UI
- Generic
AddApproverModalexists but is not used for Step 3 - Step 3 approver is determined by backend logic only
Limitations:
-
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
-
No Post-Creation Modification:
- No UI to change Step 3 approver after request is created
- Would require backend API to update
ApprovalLevel.approverId
-
Fixed Resolution Logic:
- Department lead resolution is hardcoded in backend
- No configuration or override mechanism
Potential Enhancement Areas
- Frontend: Add manager selection UI in wizard when multiple managers found
- Frontend: Add "Change Approver" option for Step 3 (if allowed by business rules)
- Backend: Add API endpoint to update Step 3 approver after request creation
- Backend: Add configuration for department lead resolution rules
- Both: Handle
MULTIPLE_MANAGERS_FOUNDerror gracefully in frontend
Related Files
Backend:
Re_Backend/src/services/dealerClaim.service.ts- Main serviceRe_Backend/src/controllers/dealerClaim.controller.ts- API endpointsRe_Backend/src/services/user.service.ts- User/Okta integrationRe_Backend/src/models/ApprovalLevel.ts- Database model
Frontend:
Re_Figma_Code/src/dealer-claim/components/request-creation/ClaimManagementWizard.tsx- Request creationRe_Figma_Code/src/dealer-claim/pages/RequestDetail.tsx- Request detail viewRe_Figma_Code/src/dealer-claim/components/request-detail/WorkflowTab.tsx- Workflow displayRe_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