Re_Figma_Code/DASHBOARD_FORMULAS.md
2025-11-17 11:00:17 +05:30

654 lines
17 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Dashboard Formulas & Calculations Documentation
This document provides a comprehensive breakdown of all formulas and calculations used in the Dashboard for both **Admin/Management** users and **Regular Users**.
---
## 📊 **1. REQUEST VOLUME STATISTICS**
### **Admin/Management View**
**Scope:** All requests across the organization
**Formulas:**
```
Total Requests = COUNT(*)
WHERE submission_date BETWEEN :start AND :end
AND is_draft = false
AND is_deleted = false
AND submission_date IS NOT NULL
Approved Requests = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND is_draft = false
Rejected Requests = COUNT(*)
WHERE status = 'REJECTED'
AND submission_date BETWEEN :start AND :end
AND is_draft = false
Pending Requests = COUNT(*)
WHERE status IN ('PENDING', 'IN_PROGRESS')
AND is_draft = false
(Note: Includes ALL pending requests regardless of creation date)
Draft Requests = COUNT(*)
WHERE is_draft = true
```
### **Regular User View**
**Scope:** Only requests initiated by the user
**Formulas:**
```
Total Requests = COUNT(*)
WHERE submission_date BETWEEN :start AND :end
AND is_draft = false
AND initiator_id = :userId
Approved Requests = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND initiator_id = :userId
AND is_draft = false
Rejected Requests = COUNT(*)
WHERE status = 'REJECTED'
AND submission_date BETWEEN :start AND :end
AND initiator_id = :userId
AND is_draft = false
Pending Requests = COUNT(*)
WHERE status IN ('PENDING', 'IN_PROGRESS')
AND initiator_id = :userId
AND is_draft = false
Draft Requests = COUNT(*)
WHERE is_draft = true
AND initiator_id = :userId
```
---
## ⏱️ **2. TAT EFFICIENCY & SLA COMPLIANCE**
### **Admin/Management View**
**Scope:** All completed requests in date range
**Formulas:**
```
Completed Requests = COUNT(*)
WHERE status IN ('APPROVED', 'REJECTED')
AND is_draft = false
AND submission_date IS NOT NULL
AND (
(closure_date IS NOT NULL AND closure_date BETWEEN :start AND :end)
OR (closure_date IS NULL AND updated_at BETWEEN :start AND :end)
)
Breached Requests = COUNT(DISTINCT request_id)
WHERE EXISTS (
SELECT 1 FROM tat_alerts ta
WHERE ta.request_id = wf.request_id
AND ta.is_breached = true
)
Compliant Requests = Total Completed - Breached Requests
SLA Compliance % = ROUND((Compliant Requests / Total Completed) × 100, 0)
If Total Completed = 0, then Compliance = 0%
Average Cycle Time (Hours) = ROUND(SUM(cycle_times) / COUNT(cycle_times), 1)
Where cycle_time = calculateElapsedWorkingHours(submission_date, completion_date, priority)
(Respects working hours, weekends, holidays based on priority)
Average Cycle Time (Days) = ROUND(Average Cycle Time (Hours) / 8, 1)
(Assumes 8 working hours per day)
```
### **Regular User View**
**Scope:** Only completed requests initiated by the user
**Formulas:**
```
Completed Requests = COUNT(*)
WHERE status IN ('APPROVED', 'REJECTED')
AND is_draft = false
AND submission_date IS NOT NULL
AND initiator_id = :userId
AND (
(closure_date IS NOT NULL AND closure_date BETWEEN :start AND :end)
OR (closure_date IS NULL AND updated_at BETWEEN :start AND :end)
)
Breached Requests = COUNT(DISTINCT request_id)
WHERE initiator_id = :userId
AND EXISTS (
SELECT 1 FROM tat_alerts ta
WHERE ta.request_id = wf.request_id
AND ta.is_breached = true
)
Compliant Requests = Total Completed - Breached Requests
SLA Compliance % = ROUND((Compliant Requests / Total Completed) × 100, 0)
Average Cycle Time (Hours) = Same calculation as Admin
Average Cycle Time (Days) = Same calculation as Admin
```
**Note:** Breaches are tracked at **approver/level level** but counted at **request level** for SLA compliance.
---
## 👤 **3. APPROVER LOAD STATISTICS**
### **Admin/Management View**
**Not Applicable** - This metric is user-specific
### **Regular User View**
**Scope:** User's approval workload
**Formulas:**
```
Pending Actions = COUNT(DISTINCT level_id)
WHERE approver_id = :userId
AND status = 'IN_PROGRESS'
AND request.status IN ('PENDING', 'IN_PROGRESS')
AND is_draft = false
AND level_number = request.current_level
(Only counts requests at user's current active level)
Completed Today = COUNT(*)
WHERE approver_id = :userId
AND status IN ('APPROVED', 'REJECTED')
AND action_date BETWEEN :start AND :end
(Date range start/end for "today")
Completed This Week = COUNT(*)
WHERE approver_id = :userId
AND status IN ('APPROVED', 'REJECTED')
AND action_date >= start_of_week
AND action_date BETWEEN :start AND :end
```
---
## 📝 **4. ENGAGEMENT STATISTICS**
### **Admin/Management View**
**Scope:** All work notes and documents across organization
**Formulas:**
```
Work Notes Added = COUNT(*)
FROM work_notes wn
WHERE wn.created_at BETWEEN :start AND :end
Attachments Uploaded = COUNT(*)
FROM documents d
WHERE d.uploaded_at BETWEEN :start AND :end
```
### **Regular User View**
**Scope:** Only from requests initiated by the user
**Formulas:**
```
Work Notes Added = COUNT(*)
FROM work_notes wn
WHERE wn.created_at BETWEEN :start AND :end
AND EXISTS (
SELECT 1 FROM workflow_requests wf
WHERE wf.request_id = wn.request_id
AND wf.initiator_id = :userId
AND wf.is_draft = false
)
Attachments Uploaded = COUNT(*)
FROM documents d
WHERE d.uploaded_at BETWEEN :start AND :end
AND EXISTS (
SELECT 1 FROM workflow_requests wf
WHERE wf.request_id = d.request_id
AND wf.initiator_id = :userId
AND wf.is_draft = false
)
```
---
## 🤖 **5. AI INSIGHTS**
### **Admin/Management View**
**Scope:** All approved requests with conclusion remarks
**Formulas:**
```
Total with Conclusion = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND conclusion_remark IS NOT NULL
AND is_draft = false
AI Generated Count = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND ai_generated_conclusion IS NOT NULL
AND ai_generated_conclusion != ''
AND is_draft = false
Manual Count = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND (ai_generated_conclusion IS NULL OR ai_generated_conclusion = '')
AND is_draft = false
AI Adoption % = ROUND((AI Generated Count / Total with Conclusion) × 100, 0)
Average Remark Length = ROUND(AVG(LENGTH(conclusion_remark)), 0)
WHERE status = 'APPROVED'
AND conclusion_remark IS NOT NULL
```
### **Regular User View**
**Scope:** Only approved requests initiated by the user
**Formulas:**
```
Total with Conclusion = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND conclusion_remark IS NOT NULL
AND initiator_id = :userId
AND is_draft = false
AI Generated Count = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND ai_generated_conclusion IS NOT NULL
AND ai_generated_conclusion != ''
AND initiator_id = :userId
AND is_draft = false
Manual Count = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND (ai_generated_conclusion IS NULL OR ai_generated_conclusion = '')
AND initiator_id = :userId
AND is_draft = false
AI Adoption % = ROUND((AI Generated Count / Total with Conclusion) × 100, 0)
Average Remark Length = Same calculation as Admin (filtered by initiator_id)
```
---
## 📈 **6. SUCCESS RATE (Regular Users Only)**
**Formula:**
```
Success Rate % = ROUND((Approved Requests / Total Requests) × 100, 0)
If Total Requests = 0, then Success Rate = 0%
Where:
Approved Requests = From Request Volume Statistics
Total Requests = From Request Volume Statistics
```
---
## 🏢 **7. DEPARTMENT STATISTICS (Admin Only)**
**Scope:** All requests grouped by initiator's department
**Formulas:**
```
Department Stats = GROUP BY initiator.department
Total Requests per Dept = COUNT(*)
WHERE submission_date BETWEEN :start AND :end
AND is_draft = false
GROUP BY initiator.department
Approved per Dept = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND is_draft = false
GROUP BY initiator.department
Rejected per Dept = COUNT(*)
WHERE status = 'REJECTED'
AND submission_date BETWEEN :start AND :end
AND is_draft = false
GROUP BY initiator.department
In Progress per Dept = COUNT(*)
WHERE status IN ('PENDING', 'IN_PROGRESS')
AND submission_date BETWEEN :start AND :end
AND is_draft = false
GROUP BY initiator.department
Approval Rate per Dept = ROUND((Approved / Total Requests) × 100, 0)
If Total Requests = 0, then Approval Rate = 0%
```
**Note:** Limited to top 10 departments by total requests.
---
## 🎯 **8. PRIORITY DISTRIBUTION (Admin Only)**
**Scope:** All requests grouped by priority (EXPRESS vs STANDARD)
**Formulas:**
```
Total Count per Priority = COUNT(*)
WHERE submission_date BETWEEN :start AND :end
AND is_draft = false
GROUP BY priority
Approved Count per Priority = COUNT(*)
WHERE status = 'APPROVED'
AND submission_date BETWEEN :start AND :end
AND is_draft = false
GROUP BY priority
Breached Count per Priority = COUNT(DISTINCT request_id)
WHERE EXISTS (
SELECT 1 FROM tat_alerts ta
WHERE ta.request_id = wf.request_id
AND ta.is_breached = true
)
GROUP BY priority
Average Cycle Time per Priority = ROUND(SUM(cycle_times) / COUNT(cycle_times), 1)
Where cycle_time = calculateElapsedWorkingHours(submission_date, completion_date, priority)
Only for COMPLETED requests (status IN ('APPROVED', 'REJECTED'))
GROUP BY priority
Compliance Rate per Priority = ROUND(((Total Count - Breached Count) / Total Count) × 100, 0)
If Total Count = 0, then Compliance Rate = 0%
```
---
## 👥 **9. APPROVER PERFORMANCE (Admin Only)**
**Scope:** All approvers who completed approvals in date range
**Formulas:**
```
Total Approved per Approver = COUNT(DISTINCT level_id)
WHERE approver_id = :approverId
AND action_date BETWEEN :start AND :end
AND status IN ('APPROVED', 'REJECTED')
AND action_date IS NOT NULL
AND level_start_time IS NOT NULL
AND tat_hours > 0
AND elapsed_hours > 0
Within TAT Count = COUNT(DISTINCT level_id)
WHERE approver_id = :approverId
AND action_date BETWEEN :start AND :end
AND status IN ('APPROVED', 'REJECTED')
AND elapsed_hours IS NOT NULL
AND elapsed_hours > 0
AND (
elapsed_hours < tat_hours
OR (elapsed_hours <= tat_hours AND (tat_breached IS NULL OR tat_breached = false))
OR (tat_breached IS NOT NULL AND tat_breached = false)
)
Breached Count = COUNT(DISTINCT level_id)
WHERE approver_id = :approverId
AND action_date BETWEEN :start AND :end
AND status IN ('APPROVED', 'REJECTED')
AND elapsed_hours IS NOT NULL
AND elapsed_hours > 0
AND (
elapsed_hours > tat_hours
OR (tat_breached IS NOT NULL AND tat_breached = true)
)
TAT Compliance % = ROUND((Within TAT Count / Total Approved) × 100, 0)
If Total Approved = 0, then TAT Compliance = 0%
Average Response Hours = ROUND(AVG(elapsed_hours), 1)
WHERE approver_id = :approverId
AND action_date BETWEEN :start AND :end
AND status IN ('APPROVED', 'REJECTED')
AND elapsed_hours IS NOT NULL
AND elapsed_hours > 0
Pending Count = COUNT(DISTINCT level_id)
WHERE approver_id = :approverId
AND status IN ('PENDING', 'IN_PROGRESS')
AND request.status IN ('PENDING', 'IN_PROGRESS')
AND is_draft = false
AND level_number = request.current_level
(Only current active level for each request)
```
**Sorting Order:**
1. TAT Compliance % (DESC - highest first)
2. Average Response Hours (ASC - fastest first)
3. Total Approved (DESC - most approvals first)
---
## 🤖 **10. AI REMARK UTILIZATION (Admin Only)**
**Scope:** All conclusion remarks generated in date range
**Formulas:**
```
Total Usage = COUNT(*)
FROM conclusion_remarks cr
WHERE cr.generated_at BETWEEN :start AND :end
Total Edits = COUNT(*)
FROM conclusion_remarks cr
WHERE cr.generated_at BETWEEN :start AND :end
AND cr.is_edited = true
Edit Rate % = ROUND((Total Edits / Total Usage) × 100, 0)
If Total Usage = 0, then Edit Rate = 0%
Monthly Trends (Last 7 Months):
AI Usage = COUNT(*)
WHERE generated_at >= NOW() - INTERVAL '7 months'
GROUP BY DATE_TRUNC('month', generated_at)
Manual Edits = COUNT(*)
WHERE generated_at >= NOW() - INTERVAL '7 months'
AND is_edited = true
GROUP BY DATE_TRUNC('month', generated_at)
```
---
## 📅 **11. DATE RANGE CALCULATIONS**
**Date Range Parsing:**
```
Today:
start = start_of_day(today)
end = end_of_day(today)
This Week:
start = start_of_week(today)
end = end_of_week(today)
This Month:
start = start_of_month(today)
end = end_of_month(today)
This Quarter:
start = start_of_quarter(today)
end = end_of_quarter(today)
This Year:
start = start_of_year(today)
end = end_of_year(today)
Custom Range:
start = start_of_day(custom_start_date)
end = end_of_day(custom_end_date)
(Capped at current date if future date provided)
Default (if not specified):
start = 30 days ago (start of day)
end = today (end of day)
```
---
## 🔍 **12. CRITICAL ALERTS**
### **Admin/Management View**
**Scope:** All requests with critical TAT status
**Formulas:**
```
Critical Requests = Requests where:
- TAT percentage used >= 80% (approaching deadline)
- OR TAT percentage used >= 100% (breached)
- OR has breach alerts (is_breached = true in tat_alerts)
Breached Count = COUNT(*)
WHERE breachCount > 0
(From critical requests)
Warning Count = COUNT(*)
WHERE breachCount = 0
AND TAT percentage >= 80%
(From critical requests)
```
### **Regular User View**
**Scope:** Only requests initiated by the user
**Formulas:**
```
Critical Requests = Same logic as Admin, filtered by initiator_id = :userId
Breached Count = Same calculation as Admin (filtered by user)
Warning Count = Same calculation as Admin (filtered by user)
```
---
## 📊 **13. UPCOMING DEADLINES**
**Scope:** Requests with active levels approaching TAT deadline
**Formulas:**
```
Upcoming Deadlines = Requests where:
- Current level is active (status IN ('PENDING', 'IN_PROGRESS'))
- remainingHours > 0 (not yet breached)
- tatPercentageUsed < 100 (not yet breached)
TAT Percentage Used = ROUND((elapsedHours / tatHours) × 100, 0)
Where elapsedHours = calculateElapsedWorkingHours(level_start_time, current_time, priority)
Remaining Hours = MAX(0, tatHours - elapsedHours)
Elapsed Hours = calculateElapsedWorkingHours(level_start_time, current_time, priority)
(Respects working hours, weekends, holidays based on priority)
```
**Note:** Only shows requests that are NOT yet breached (remainingHours > 0 and tatPercentage < 100).
---
## 📝 **14. RECENT ACTIVITY**
### **Admin/Management View**
**Scope:** All workflow activities across organization
**Formulas:**
```
Recent Activity = All activities from workflow_requests
ORDER BY activity.created_at DESC
(No user filter)
```
### **Regular User View**
**Scope:** Activities from user's requests or where user is a participant
**Formulas:**
```
Recent Activity = Activities where:
- request.initiator_id = :userId
- OR user is a participant in the request
ORDER BY activity.created_at DESC
```
---
## 🔑 **KEY DIFFERENCES: ADMIN vs REGULAR USER**
| Metric | Admin/Management | Regular User |
|--------|------------------|--------------|
| **Request Volume** | All organization requests | Only user-initiated requests |
| **TAT Efficiency** | All completed requests | Only user-initiated completed requests |
| **Approver Load** | N/A | User's own approval workload |
| **Engagement** | All work notes/documents | Only from user's requests |
| **AI Insights** | All approved requests | Only user's approved requests |
| **Department Stats** | Available | Not available |
| **Priority Distribution** | Available | Not available |
| **Approver Performance** | Available | Not available |
| **AI Remark Utilization** | Available | Not available |
| **Success Rate** | Not shown | Available |
---
## 📌 **IMPORTANT NOTES**
1. **Date Filtering:**
- Most metrics use `submission_date` (when request was submitted), not `created_at`
- Completed requests use `closure_date` or `updated_at` for completion date
- Pending requests are counted regardless of creation date
2. **Working Hours Calculation:**
- Cycle time uses `calculateElapsedWorkingHours()` which respects:
- Working hours (9 AM - 6 PM)
- Weekends (for STANDARD priority)
- Holidays (configured in system)
- Priority type (EXPRESS vs STANDARD)
3. **Breach Tracking:**
- Breaches are tracked at **approver/level level** (each level has its own TAT)
- But SLA compliance counts at **request level** (if any level breaches, entire request is non-compliant)
4. **Rounding:**
- Percentages: Rounded to nearest integer (0 decimal places)
- Hours: Rounded to 1 decimal place
- Days: Rounded to 1 decimal place
5. **Null Handling:**
- All COUNT operations handle NULL values
- Division operations use NULLIF to prevent division by zero
- Default values are 0 if no data exists
---
## 🔄 **DATA REFRESH**
All calculations are performed in real-time when:
- Dashboard is loaded
- Date range filter is changed
- Refresh button is clicked
- Custom date range is applied
Data is fetched in parallel for optimal performance.
---
**Last Updated:** Based on codebase as of current date
**Version:** 1.0