752 lines
19 KiB
Markdown
752 lines
19 KiB
Markdown
# Skip Approver & Dynamic Approver Addition
|
|
|
|
## Overview
|
|
|
|
This feature allows initiators and approvers to manage approval workflows dynamically when approvers are unavailable or additional approval is needed.
|
|
|
|
### **Key Features:**
|
|
|
|
1. **Skip Approver** - Skip non-responding approvers and move to next level
|
|
2. **Add Approver at Specific Level** - Insert new approver at any position
|
|
3. **Automatic Level Shifting** - Existing approvers are automatically renumbered
|
|
4. **Smart Validation** - Cannot modify completed levels (approved/rejected/skipped)
|
|
5. **TAT Management** - New approvers get their own TAT, jobs scheduled automatically
|
|
|
|
---
|
|
|
|
## Use Cases
|
|
|
|
### **Use Case 1: Approver on Leave**
|
|
|
|
**Scenario:**
|
|
```
|
|
Level 1: Sarah (Approved) ✅
|
|
Level 2: Mike (Pending) ⏳ ← On vacation, not responding
|
|
Level 3: Lisa (Waiting) ⏸️
|
|
```
|
|
|
|
**Solution:**
|
|
```
|
|
Initiator clicks "Skip This Approver" on Level 2
|
|
→ Mike is marked as SKIPPED
|
|
→ Level 3 (Lisa) becomes active
|
|
→ Lisa receives notification
|
|
→ TAT jobs cancelled for Mike, scheduled for Lisa
|
|
```
|
|
|
|
**Result:**
|
|
```
|
|
Level 1: Sarah (Approved) ✅
|
|
Level 2: Mike (Skipped) ⏭️ ← Skipped
|
|
Level 3: Lisa (In Review) ⏳ ← Now active
|
|
```
|
|
|
|
---
|
|
|
|
### **Use Case 2: Add Additional Reviewer**
|
|
|
|
**Scenario:**
|
|
```
|
|
Level 1: Sarah (Approved) ✅
|
|
Level 2: Mike (In Review) ⏳
|
|
Level 3: Lisa (Waiting) ⏸️
|
|
```
|
|
|
|
**Need:** Add Finance Manager (John) between Mike and Lisa
|
|
|
|
**Solution:**
|
|
```
|
|
Click "Add Approver"
|
|
→ Email: john@example.com
|
|
→ TAT: 48 hours
|
|
→ Level: 3 (between Mike and Lisa)
|
|
→ Submit
|
|
```
|
|
|
|
**Result:**
|
|
```
|
|
Level 1: Sarah (Approved) ✅
|
|
Level 2: Mike (In Review) ⏳ ← Still at level 2
|
|
Level 3: John (Waiting) ⏸️ ← NEW! Inserted here
|
|
Level 4: Lisa (Waiting) ⏸️ ← Shifted from 3 to 4
|
|
```
|
|
|
|
---
|
|
|
|
### **Use Case 3: Replace Skipped Approver**
|
|
|
|
**Scenario:**
|
|
```
|
|
Level 1: Sarah (Approved) ✅
|
|
Level 2: Mike (Skipped) ⏭️
|
|
Level 3: Lisa (In Review) ⏳
|
|
```
|
|
|
|
**Need:** Add replacement for Mike at level 2
|
|
|
|
**Solution:**
|
|
```
|
|
Click "Add Approver"
|
|
→ Email: john@example.com
|
|
→ TAT: 24 hours
|
|
→ Level: 2 (Mike's old position)
|
|
→ Submit
|
|
```
|
|
|
|
**Result:**
|
|
```
|
|
Level 1: Sarah (Approved) ✅
|
|
Level 2: John (Waiting) ⏸️ ← NEW! Inserted at level 2
|
|
Level 3: Mike (Skipped) ⏭️ ← Shifted from 2 to 3
|
|
Level 4: Lisa (In Review) ⏳ ← Shifted from 3 to 4
|
|
```
|
|
|
|
---
|
|
|
|
## Database Schema
|
|
|
|
### **New Fields in `approval_levels` Table:**
|
|
|
|
```sql
|
|
-- Migration: add_is_skipped_to_approval_levels.sql
|
|
|
|
ALTER TABLE approval_levels
|
|
ADD COLUMN is_skipped BOOLEAN DEFAULT FALSE,
|
|
ADD COLUMN skipped_at TIMESTAMP,
|
|
ADD COLUMN skipped_by UUID REFERENCES users(user_id),
|
|
ADD COLUMN skip_reason TEXT;
|
|
```
|
|
|
|
### **Status Enum Update:**
|
|
|
|
Already includes `SKIPPED` status:
|
|
```sql
|
|
status ENUM('PENDING', 'IN_PROGRESS', 'APPROVED', 'REJECTED', 'SKIPPED')
|
|
```
|
|
|
|
### **Example Data:**
|
|
|
|
```sql
|
|
-- Level 2 was skipped
|
|
SELECT
|
|
level_number,
|
|
approver_name,
|
|
status,
|
|
is_skipped,
|
|
skipped_at,
|
|
skip_reason
|
|
FROM approval_levels
|
|
WHERE request_id = 'xxx';
|
|
|
|
-- Results:
|
|
-- 1 | Sarah | APPROVED | FALSE | NULL | NULL
|
|
-- 2 | Mike | SKIPPED | TRUE | 2025-11-05 | On vacation
|
|
-- 3 | Lisa | PENDING | FALSE | NULL | NULL
|
|
```
|
|
|
|
---
|
|
|
|
## API Endpoints
|
|
|
|
### **1. Skip Approver**
|
|
|
|
**Endpoint:**
|
|
```
|
|
POST /api/v1/workflows/:id/approvals/:levelId/skip
|
|
```
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"reason": "Approver on vacation - deadline approaching"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Approver skipped successfully",
|
|
"data": {
|
|
"levelId": "...",
|
|
"levelNumber": 2,
|
|
"status": "SKIPPED",
|
|
"skippedAt": "2025-11-05T10:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Logic:**
|
|
1. ✅ Mark level as `SKIPPED`
|
|
2. ✅ Cancel TAT jobs for skipped level
|
|
3. ✅ Activate next level (move to level+1)
|
|
4. ✅ Schedule TAT jobs for next level
|
|
5. ✅ Notify next approver
|
|
6. ✅ Log activity
|
|
|
|
**Validation:**
|
|
- ❌ Cannot skip already approved/rejected/skipped levels
|
|
- ❌ Cannot skip future levels (only current level)
|
|
- ✅ Only INITIATOR or APPROVER can skip
|
|
|
|
---
|
|
|
|
### **2. Add Approver at Specific Level**
|
|
|
|
**Endpoint:**
|
|
```
|
|
POST /api/v1/workflows/:id/approvers/at-level
|
|
```
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"email": "john@example.com",
|
|
"tatHours": 48,
|
|
"level": 3
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"success": true,
|
|
"message": "Approver added successfully",
|
|
"data": {
|
|
"levelId": "...",
|
|
"levelNumber": 3,
|
|
"approverName": "John Doe",
|
|
"tatHours": 48,
|
|
"status": "PENDING"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Logic:**
|
|
1. ✅ Find user by email
|
|
2. ✅ Validate target level (must be after completed levels)
|
|
3. ✅ Shift existing levels at and after target level (+1)
|
|
4. ✅ Create new approval level at target position
|
|
5. ✅ Add as participant (APPROVER type)
|
|
6. ✅ If new level is current level, schedule TAT jobs
|
|
7. ✅ Notify new approver
|
|
8. ✅ Log activity
|
|
|
|
**Validation:**
|
|
- ❌ User must exist in system
|
|
- ❌ User cannot be existing participant
|
|
- ❌ Level must be after completed levels (approved/rejected/skipped)
|
|
- ✅ Automatic level shifting for existing approvers
|
|
|
|
---
|
|
|
|
## Level Shifting Logic
|
|
|
|
### **Example: Add at Level 3**
|
|
|
|
**Before:**
|
|
```
|
|
Level 1: Sarah (Approved) ✅
|
|
Level 2: Mike (In Review) ⏳
|
|
Level 3: Lisa (Waiting) ⏸️
|
|
Level 4: Tom (Waiting) ⏸️
|
|
```
|
|
|
|
**Action:**
|
|
```
|
|
Add John at Level 3 with 48h TAT
|
|
```
|
|
|
|
**Backend Processing:**
|
|
```typescript
|
|
// Step 1: Get levels to shift (levelNumber >= 3)
|
|
levelsToShift = [Lisa (Level 3), Tom (Level 4)]
|
|
|
|
// Step 2: Shift each level
|
|
Lisa: Level 3 → Level 4
|
|
Tom: Level 4 → Level 5
|
|
|
|
// Step 3: Insert new approver
|
|
John: Create at Level 3
|
|
|
|
// Step 4: Update workflow.totalLevels
|
|
totalLevels: 4 → 5
|
|
```
|
|
|
|
**After:**
|
|
```
|
|
Level 1: Sarah (Approved) ✅
|
|
Level 2: Mike (In Review) ⏳
|
|
Level 3: John (Waiting) ⏸️ ← NEW!
|
|
Level 4: Lisa (Waiting) ⏸️ ← Shifted from 3
|
|
Level 5: Tom (Waiting) ⏸️ ← Shifted from 4
|
|
```
|
|
|
|
---
|
|
|
|
## Frontend Implementation
|
|
|
|
### **AddApproverModal Enhancements:**
|
|
|
|
**New Props:**
|
|
```typescript
|
|
interface AddApproverModalProps {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
onConfirm: (email: string, tatHours: number, level: number) => Promise<void>;
|
|
currentLevels?: ApprovalLevelInfo[]; // ✅ NEW!
|
|
}
|
|
|
|
interface ApprovalLevelInfo {
|
|
levelNumber: number;
|
|
approverName: string;
|
|
status: string;
|
|
tatHours: number;
|
|
}
|
|
```
|
|
|
|
**UI Components:**
|
|
1. **Current Levels Display** - Shows all existing levels with status badges
|
|
2. **Level Selector** - Dropdown with available levels (after completed)
|
|
3. **TAT Hours Input** - Number input for TAT (1-720 hours)
|
|
4. **Email Search** - Existing @ mention search
|
|
|
|
**Example Modal:**
|
|
```
|
|
┌─────────────────────────────────────────────────┐
|
|
│ Add Approver │
|
|
├─────────────────────────────────────────────────┤
|
|
│ Current Approval Levels │
|
|
│ ┌─────────────────────────────────────────────┐ │
|
|
│ │ [1] Sarah 50h TAT [✓] approved │ │
|
|
│ │ [2] Mike 24h TAT [⏳] pending │ │
|
|
│ │ [3] Lisa 36h TAT [⏸] waiting │ │
|
|
│ └─────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ Approval Level * │
|
|
│ [Select: Level 2 (will shift existing Level 2)] │
|
|
│ │
|
|
│ TAT (Turn Around Time) * │
|
|
│ [48] hours │
|
|
│ │
|
|
│ Email Address * │
|
|
│ [@john or john@example.com] │
|
|
│ │
|
|
│ [Cancel] [Add at Level 2] │
|
|
└─────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
### **RequestDetail Skip Button:**
|
|
|
|
Added to Workflow tab for each pending/in-review level:
|
|
|
|
```tsx
|
|
{/* Skip Approver Button - Only for active levels */}
|
|
{(isActive || step.status === 'pending') && !isCompleted && !isRejected && (
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
className="w-full border-orange-300 text-orange-700 hover:bg-orange-50"
|
|
onClick={() => {
|
|
const reason = prompt('Provide reason for skipping:');
|
|
if (reason !== null) {
|
|
handleSkipApprover(step.levelId, reason);
|
|
}
|
|
}}
|
|
>
|
|
<AlertCircle className="w-4 h-4 mr-2" />
|
|
Skip This Approver
|
|
</Button>
|
|
)}
|
|
```
|
|
|
|
---
|
|
|
|
## Validation Rules
|
|
|
|
### **Skip Approver Validation:**
|
|
|
|
| Rule | Validation | Error Message |
|
|
|------|-----------|---------------|
|
|
| Already completed | ❌ Cannot skip APPROVED level | "Cannot skip approver - level is already APPROVED" |
|
|
| Already rejected | ❌ Cannot skip REJECTED level | "Cannot skip approver - level is already REJECTED" |
|
|
| Already skipped | ❌ Cannot skip SKIPPED level | "Cannot skip approver - level is already SKIPPED" |
|
|
| Future level | ❌ Cannot skip level > currentLevel | "Cannot skip future approval levels" |
|
|
| Authorization | ✅ Only INITIATOR or APPROVER | 403 Forbidden |
|
|
|
|
---
|
|
|
|
### **Add Approver Validation:**
|
|
|
|
| Rule | Validation | Error Message |
|
|
|------|-----------|---------------|
|
|
| User exists | ✅ User must exist in system | "User not found with this email" |
|
|
| Already participant | ❌ Cannot add existing participant | "User is already a participant" |
|
|
| Level range | ❌ Level must be ≥ (completed levels + 1) | "Cannot add at level X. Minimum is Y" |
|
|
| TAT hours | ✅ 1 ≤ hours ≤ 720 | "TAT hours must be between 1 and 720" |
|
|
| Email format | ✅ Valid email format | "Please enter a valid email" |
|
|
| Authorization | ✅ Only INITIATOR or APPROVER | 403 Forbidden |
|
|
|
|
---
|
|
|
|
## Examples
|
|
|
|
### **Example 1: Skip Current Approver**
|
|
|
|
**Initial State:**
|
|
```
|
|
Request: REQ-2025-001
|
|
Current Level: 2
|
|
|
|
Level 1: Sarah (APPROVED) ✅
|
|
Level 2: Mike (IN_PROGRESS) ⏳ ← Taking too long
|
|
Level 3: Lisa (PENDING) ⏸️
|
|
```
|
|
|
|
**Action:**
|
|
```bash
|
|
# Initiator skips Mike
|
|
POST /api/v1/workflows/REQ-2025-001/approvals/LEVEL-ID-2/skip
|
|
Body: { "reason": "Approver on extended leave" }
|
|
```
|
|
|
|
**Backend Processing:**
|
|
```typescript
|
|
1. Get Level 2 (Mike) → Status: IN_PROGRESS ✅
|
|
2. Validate: Not already completed ✅
|
|
3. Update Level 2:
|
|
- status: 'SKIPPED'
|
|
- is_skipped: TRUE
|
|
- skipped_at: NOW()
|
|
- skipped_by: initiator userId
|
|
- skip_reason: "Approver on extended leave"
|
|
4. Cancel TAT jobs for Level 2
|
|
5. Get Level 3 (Lisa)
|
|
6. Activate Level 3:
|
|
- status: 'IN_PROGRESS'
|
|
- levelStartTime: NOW()
|
|
- tatStartTime: NOW()
|
|
7. Schedule TAT jobs for Level 3
|
|
8. Update workflow.currentLevel = 3
|
|
9. Notify Lisa
|
|
10. Log activity: "Level 2 approver (Mike) was skipped"
|
|
```
|
|
|
|
**Final State:**
|
|
```
|
|
Request: REQ-2025-001
|
|
Current Level: 3
|
|
|
|
Level 1: Sarah (APPROVED) ✅
|
|
Level 2: Mike (SKIPPED) ⏭️ ← Skipped!
|
|
Level 3: Lisa (IN_PROGRESS) ⏳ ← Now active!
|
|
```
|
|
|
|
---
|
|
|
|
### **Example 2: Add Approver Between Levels**
|
|
|
|
**Initial State:**
|
|
```
|
|
Request: REQ-2025-001
|
|
Current Level: 2
|
|
|
|
Level 1: Sarah (APPROVED) ✅
|
|
Level 2: Mike (IN_PROGRESS) ⏳
|
|
Level 3: Lisa (PENDING) ⏸️
|
|
```
|
|
|
|
**Action:**
|
|
```bash
|
|
# Add John at Level 3 (between Mike and Lisa)
|
|
POST /api/v1/workflows/REQ-2025-001/approvers/at-level
|
|
Body: {
|
|
"email": "john@example.com",
|
|
"tatHours": 48,
|
|
"level": 3
|
|
}
|
|
```
|
|
|
|
**Backend Processing:**
|
|
```typescript
|
|
1. Find user: john@example.com ✅
|
|
2. Validate: Not existing participant ✅
|
|
3. Validate: Level 3 ≥ minLevel (2) ✅
|
|
4. Get levels to shift: [Lisa (Level 3)]
|
|
5. Shift Lisa:
|
|
- Level 3 → Level 4
|
|
- levelName: "Level 4"
|
|
6. Create new Level 3:
|
|
- levelNumber: 3
|
|
- approverId: John's userId
|
|
- approverEmail: john@example.com
|
|
- tatHours: 48
|
|
- status: PENDING (not current level)
|
|
7. Update workflow.totalLevels: 3 → 4
|
|
8. Add John to participants (APPROVER type)
|
|
9. Notify John
|
|
10. Log activity: "John added as approver at Level 3 with TAT of 48 hours"
|
|
```
|
|
|
|
**Final State:**
|
|
```
|
|
Request: REQ-2025-001
|
|
Current Level: 2
|
|
|
|
Level 1: Sarah (APPROVED) ✅
|
|
Level 2: Mike (IN_PROGRESS) ⏳ ← Still working
|
|
Level 3: John (PENDING) ⏸️ ← NEW! Will review after Mike
|
|
Level 4: Lisa (PENDING) ⏸️ ← Shifted from 3 to 4
|
|
```
|
|
|
|
---
|
|
|
|
### **Example 3: Complex Scenario - Skip and Add**
|
|
|
|
**Initial State:**
|
|
```
|
|
Level 1: Sarah (APPROVED) ✅
|
|
Level 2: Mike (APPROVED) ✅
|
|
Level 3: David (IN_PROGRESS) ⏳ ← Taking too long
|
|
Level 4: Lisa (PENDING) ⏸️
|
|
Level 5: Tom (PENDING) ⏸️
|
|
```
|
|
|
|
**Action 1: Skip David**
|
|
```
|
|
Result:
|
|
Level 1: Sarah (APPROVED) ✅
|
|
Level 2: Mike (APPROVED) ✅
|
|
Level 3: David (SKIPPED) ⏭️
|
|
Level 4: Lisa (IN_PROGRESS) ⏳ ← Now active
|
|
Level 5: Tom (PENDING) ⏸️
|
|
```
|
|
|
|
**Action 2: Add John at Level 4 (before Tom)**
|
|
```
|
|
Result:
|
|
Level 1: Sarah (APPROVED) ✅
|
|
Level 2: Mike (APPROVED) ✅
|
|
Level 3: David (SKIPPED) ⏭️
|
|
Level 4: Lisa (IN_PROGRESS) ⏳
|
|
Level 5: John (PENDING) ⏸️ ← NEW!
|
|
Level 6: Tom (PENDING) ⏸️ ← Shifted
|
|
```
|
|
|
|
---
|
|
|
|
## UI/UX
|
|
|
|
### **RequestDetail - Workflow Tab:**
|
|
|
|
**Skip Button Visibility:**
|
|
- ✅ Shows for levels with status: `pending` or `in-review`
|
|
- ❌ Hidden for `approved`, `rejected`, `skipped`, or `waiting`
|
|
- ✅ Orange/amber styling to indicate caution
|
|
- ✅ Requires reason via prompt
|
|
|
|
**Button Appearance:**
|
|
```tsx
|
|
┌───────────────────────────────────────────┐
|
|
│ Level 2: Mike (In Review) │
|
|
│ TAT: 24h • Elapsed: 15h │
|
|
│ │
|
|
│ [⚠ Skip This Approver] │
|
|
│ Skip if approver is unavailable... │
|
|
└───────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
### **AddApproverModal - Enhanced UI:**
|
|
|
|
**Sections:**
|
|
1. **Current Levels** - Scrollable list showing all existing levels with status
|
|
2. **Level Selector** - Dropdown with available levels (grayed out completed levels)
|
|
3. **TAT Input** - Hours input with validation (1-720)
|
|
4. **Email Search** - @ mention search (existing)
|
|
|
|
**Features:**
|
|
- ✅ Auto-selects first available level
|
|
- ✅ Shows which existing level will be shifted
|
|
- ✅ Visual indicators for completed vs pending levels
|
|
- ✅ Prevents selecting invalid levels
|
|
- ✅ Real-time validation
|
|
|
|
---
|
|
|
|
## Activity Log Examples
|
|
|
|
### **Skip Approver Log:**
|
|
```
|
|
Action: Approver Skipped
|
|
Details: Level 2 approver (Mike Johnson) was skipped by Sarah Smith.
|
|
Reason: Approver on extended leave
|
|
Timestamp: 2025-11-05 10:30:00
|
|
User: Sarah Smith (Initiator)
|
|
```
|
|
|
|
### **Add Approver Log:**
|
|
```
|
|
Action: Added new approver
|
|
Details: John Doe (john@example.com) has been added as approver at
|
|
Level 3 with TAT of 48 hours by Sarah Smith
|
|
Timestamp: 2025-11-05 11:15:00
|
|
User: Sarah Smith (Initiator)
|
|
```
|
|
|
|
---
|
|
|
|
## Notifications
|
|
|
|
### **Skip Approver Notifications:**
|
|
|
|
**To Next Approver:**
|
|
```
|
|
Title: Request Escalated
|
|
Body: Previous approver was skipped. Request REQ-2025-001 is now
|
|
awaiting your approval.
|
|
```
|
|
|
|
---
|
|
|
|
### **Add Approver Notifications:**
|
|
|
|
**To New Approver:**
|
|
```
|
|
Title: New Request Assignment
|
|
Body: You have been added as Level 3 approver to request REQ-2025-001:
|
|
New Office Location Approval
|
|
```
|
|
|
|
---
|
|
|
|
## TAT Handling
|
|
|
|
### **Skip Approver:**
|
|
```typescript
|
|
// Skipped level's TAT jobs are cancelled
|
|
await tatSchedulerService.cancelTatJobs(requestId, skippedLevelId);
|
|
|
|
// Next level's TAT jobs are scheduled
|
|
await tatSchedulerService.scheduleTatJobs(
|
|
requestId,
|
|
nextLevelId,
|
|
nextApproverId,
|
|
nextLevelTatHours,
|
|
now,
|
|
workflowPriority
|
|
);
|
|
```
|
|
|
|
### **Add Approver:**
|
|
```typescript
|
|
// If new approver is at current level, schedule TAT immediately
|
|
if (newLevel === currentLevel) {
|
|
await tatSchedulerService.scheduleTatJobs(
|
|
requestId,
|
|
newLevelId,
|
|
newApproverId,
|
|
tatHours,
|
|
now,
|
|
workflowPriority
|
|
);
|
|
}
|
|
// Otherwise, jobs will be scheduled when level becomes active
|
|
```
|
|
|
|
---
|
|
|
|
## Testing Scenarios
|
|
|
|
### **Test 1: Skip Current Approver**
|
|
|
|
```bash
|
|
# 1. Create workflow with 3 approvers
|
|
# 2. Level 1 approves
|
|
# 3. Level 2 receives notification
|
|
# 4. Level 2 doesn't respond for extended time
|
|
# 5. Initiator clicks "Skip This Approver"
|
|
# 6. Provide reason: "On vacation"
|
|
# 7. Verify:
|
|
# ✅ Level 2 status = SKIPPED
|
|
# ✅ Level 3 status = IN_PROGRESS
|
|
# ✅ Level 3 receives notification
|
|
# ✅ TAT jobs scheduled for Level 3
|
|
# ✅ Activity logged
|
|
```
|
|
|
|
### **Test 2: Add Approver at Middle Level**
|
|
|
|
```bash
|
|
# 1. Workflow has 3 levels
|
|
# 2. Level 1 approved
|
|
# 3. Click "Add Approver"
|
|
# 4. Select Level 2 (between current levels)
|
|
# 5. Enter TAT: 48
|
|
# 6. Enter email: new@example.com
|
|
# 7. Submit
|
|
# 8. Verify:
|
|
# ✅ Old Level 2 becomes Level 3
|
|
# ✅ Old Level 3 becomes Level 4
|
|
# ✅ New approver at Level 2
|
|
# ✅ totalLevels increased by 1
|
|
# ✅ New approver receives notification
|
|
```
|
|
|
|
### **Test 3: Cannot Add Before Completed Level**
|
|
|
|
```bash
|
|
# 1. Workflow: Level 1 (Approved), Level 2 (Pending)
|
|
# 2. Try to add at Level 1
|
|
# 3. Modal shows: "Minimum allowed level is 2"
|
|
# 4. Level 1 is grayed out in selector
|
|
# 5. Cannot submit ✅
|
|
```
|
|
|
|
---
|
|
|
|
## Files Modified
|
|
|
|
### **Backend:**
|
|
1. `Re_Backend/src/migrations/add_is_skipped_to_approval_levels.sql` - Database migration
|
|
2. `Re_Backend/src/services/workflow.service.ts` - Skip and add approver logic
|
|
3. `Re_Backend/src/routes/workflow.routes.ts` - API endpoints
|
|
|
|
### **Frontend:**
|
|
4. `Re_Figma_Code/src/services/workflowApi.ts` - API client methods
|
|
5. `Re_Figma_Code/src/components/participant/AddApproverModal/AddApproverModal.tsx` - Enhanced modal
|
|
6. `Re_Figma_Code/src/pages/RequestDetail/RequestDetail.tsx` - Skip button and handlers
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
| Feature | Description | Benefit |
|
|
|---------|-------------|---------|
|
|
| **Skip Approver** | Mark approver as skipped, move to next | Handle unavailable approvers |
|
|
| **Add at Level** | Insert approver at specific position | Flexible workflow modification |
|
|
| **Auto Shifting** | Existing levels automatically renumbered | No manual level management |
|
|
| **Smart Validation** | Cannot modify completed levels | Data integrity |
|
|
| **TAT Management** | Jobs cancelled/scheduled automatically | Accurate time tracking |
|
|
| **Activity Logging** | All actions tracked in audit trail | Full transparency |
|
|
| **Notifications** | Affected users notified automatically | Keep everyone informed |
|
|
|
|
---
|
|
|
|
## Benefits
|
|
|
|
1. ✅ **Flexibility** - Handle real-world workflow changes
|
|
2. ✅ **No Bottlenecks** - Skip unavailable approvers
|
|
3. ✅ **Dynamic Addition** - Add approvers mid-workflow
|
|
4. ✅ **Data Integrity** - Cannot modify completed levels
|
|
5. ✅ **Audit Trail** - Full history of all changes
|
|
6. ✅ **Automatic Notifications** - All affected parties notified
|
|
7. ✅ **TAT Accuracy** - Time tracking updated correctly
|
|
8. ✅ **User-Friendly** - Intuitive UI with clear feedback
|
|
|
|
The approval workflow is now fully dynamic and can adapt to changing business needs! 🚀
|
|
|