300 lines
10 KiB
Markdown
300 lines
10 KiB
Markdown
# 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;
|
|
})() && (
|
|
<Button onClick={() => setShowIOApprovalModal(true)}>
|
|
Approve and Organise IO
|
|
</Button>
|
|
)}
|
|
```
|
|
|
|
#### 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
|
|
|