Re_Backend/docs/STEP3_APPROVER_ANALYSIS.md

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