qudoco-be/plan/approval-workflow-architect...

348 lines
11 KiB
Markdown

# Approval Workflow Architecture & Module Relationships
## 📋 **Overview**
Sistem approval workflow di MEDOLS menggunakan arsitektur multi-module yang saling terintegrasi untuk mengelola proses persetujuan artikel secara dinamis. Setiap module memiliki peran spesifik dalam alur approval yang kompleks.
## 🏗️ **Module Architecture**
### **1. Core Workflow Modules**
#### **`approval_workflows`** - Master Workflow Definition
- **Purpose**: Mendefinisikan template workflow approval
- **Key Fields**:
- `id`: Primary key
- `name`: Nama workflow (e.g., "Standard Approval", "Fast Track")
- `description`: Deskripsi workflow
- `is_default`: Apakah workflow default untuk client
- `is_active`: Status aktif workflow
- `client_id`: Client yang memiliki workflow
#### **`approval_workflow_steps`** - Workflow Steps Definition
- **Purpose**: Mendefinisikan step-step dalam workflow
- **Key Fields**:
- `id`: Primary key
- `workflow_id`: Foreign key ke `approval_workflows`
- `step_order`: Urutan step (1, 2, 3, dst.)
- `step_name`: Nama step (e.g., "Level 2 Review", "Level 1 Final Approval")
- `required_user_level_id`: User level yang harus approve step ini
- `is_required`: Apakah step wajib atau optional
### **2. Execution Modules**
#### **`article_approval_flows`** - Active Approval Instances
- **Purpose**: Instance aktif dari workflow yang sedang berjalan
- **Key Fields**:
- `id`: Primary key
- `article_id`: Foreign key ke `articles`
- `workflow_id`: Foreign key ke `approval_workflows`
- `current_step`: Step saat ini yang sedang menunggu approval
- `status_id`: Status (1=pending, 2=approved, 3=rejected, 4=revision_requested)
- `submitted_by_id`: User yang submit artikel
- `submitted_at`: Waktu submit
- `completed_at`: Waktu selesai (jika approved/rejected)
#### **`article_approval_step_logs`** - Step Execution History
- **Purpose**: Log setiap step yang telah dieksekusi
- **Key Fields**:
- `id`: Primary key
- `approval_flow_id`: Foreign key ke `article_approval_flows`
- `step_order`: Urutan step yang dieksekusi
- `step_name`: Nama step
- `approved_by_id`: User yang approve step ini
- `action`: Aksi yang dilakukan (approve, reject, auto_skip)
- `message`: Pesan dari approver
- `processed_at`: Waktu eksekusi
### **3. Legacy & Configuration Modules**
#### **`article_approvals`** - Legacy Approval System
- **Purpose**: Sistem approval legacy untuk backward compatibility
- **Key Fields**:
- `id`: Primary key
- `article_id`: Foreign key ke `articles`
- `approval_by`: User yang approve
- `status_id`: Status approval
- `approval_at_level`: Level yang approve
- `message`: Pesan approval
#### **`client_approval_settings`** - Client Configuration
- **Purpose**: Konfigurasi approval untuk setiap client
- **Key Fields**:
- `id`: Primary key
- `client_id`: Foreign key ke `clients`
- `workflow_id`: Workflow default untuk client
- `auto_approve_levels`: Level yang auto-approve
- `notification_settings`: Konfigurasi notifikasi
## 🔄 **Approval Workflow Process Flow**
### **Phase 1: Setup & Configuration**
```mermaid
graph TD
A[Client Setup] --> B[Create Approval Workflow]
B --> C[Define Workflow Steps]
C --> D[Set Required User Levels]
D --> E[Configure Client Settings]
E --> F[Activate Workflow]
```
**Steps:**
1. **Client Registration**: Client baru dibuat di sistem
2. **Workflow Creation**: Admin membuat workflow approval
3. **Step Definition**: Mendefinisikan step-step dengan user level requirement
4. **Client Configuration**: Set workflow default untuk client
### **Phase 2: Article Submission**
```mermaid
graph TD
A[User Creates Article] --> B{User Level Requires Approval?}
B -->|Yes| C[Create Article Approval Flow]
B -->|No| D[Auto Publish]
C --> E[Set Current Step = 1]
E --> F[Status = Pending]
F --> G[Create Legacy Approval Record]
G --> H[Notify Approvers]
```
**Database Changes:**
- `articles`: `workflow_id`, `current_approval_step = 1`, `status_id = 1`
- `article_approval_flows`: New record dengan `current_step = 1`
- `article_approvals`: Legacy record untuk backward compatibility
### **Phase 3: Step-by-Step Approval**
```mermaid
graph TD
A[Approver Reviews Article] --> B{Approve or Reject?}
B -->|Approve| C[Create Step Log]
B -->|Reject| D[Update Status to Rejected]
C --> E{More Steps?}
E -->|Yes| F[Move to Next Step]
E -->|No| G[Complete Approval]
F --> H[Update Current Step]
H --> I[Notify Next Approver]
G --> J[Update Article Status to Approved]
D --> K[Notify Submitter]
```
**Database Changes per Step:**
- `article_approval_step_logs`: New log record
- `article_approval_flows`: Update `current_step` dan `status_id`
- `articles`: Update `current_approval_step`
### **Phase 4: Completion**
```mermaid
graph TD
A[All Steps Approved] --> B[Update Final Status]
B --> C[Set Completed At]
C --> D[Publish Article]
D --> E[Send Notifications]
E --> F[Update Analytics]
```
## 📊 **Module Relationships Diagram**
```mermaid
erDiagram
CLIENTS ||--o{ APPROVAL_WORKFLOWS : "has"
CLIENTS ||--o{ CLIENT_APPROVAL_SETTINGS : "configures"
APPROVAL_WORKFLOWS ||--o{ APPROVAL_WORKFLOW_STEPS : "contains"
APPROVAL_WORKFLOWS ||--o{ ARTICLE_APPROVAL_FLOWS : "instantiates"
ARTICLES ||--o{ ARTICLE_APPROVAL_FLOWS : "has"
ARTICLES ||--o{ ARTICLE_APPROVALS : "has_legacy"
ARTICLE_APPROVAL_FLOWS ||--o{ ARTICLE_APPROVAL_STEP_LOGS : "logs"
ARTICLE_APPROVAL_FLOWS }o--|| APPROVAL_WORKFLOWS : "uses"
USERS ||--o{ ARTICLE_APPROVAL_FLOWS : "submits"
USERS ||--o{ ARTICLE_APPROVAL_STEP_LOGS : "approves"
USER_LEVELS ||--o{ APPROVAL_WORKFLOW_STEPS : "requires"
USER_LEVELS ||--o{ USERS : "defines"
```
## 🔧 **Technical Implementation Details**
### **1. Dynamic Workflow Assignment**
```go
// Ketika artikel dibuat
if userLevel.RequiresApproval {
// 1. Cari workflow default untuk client
workflow := getDefaultWorkflow(clientId)
// 2. Buat approval flow instance
approvalFlow := ArticleApprovalFlows{
ArticleId: articleId,
WorkflowId: workflow.ID,
CurrentStep: 1,
StatusId: 1, // pending
}
// 3. Buat legacy record
legacyApproval := ArticleApprovals{
ArticleId: articleId,
ApprovalAtLevel: nextApprovalLevel,
}
}
```
### **2. Step Progression Logic**
```go
// Ketika step di-approve
func ApproveStep(flowId, approvedById, message) {
// 1. Log step yang di-approve
stepLog := ArticleApprovalStepLogs{
ApprovalFlowId: flowId,
StepOrder: currentStep,
ApprovedById: approvedById,
Action: "approve",
}
// 2. Cek apakah ada next step
nextStep := getNextStep(workflowId, currentStep)
if nextStep != nil {
// 3. Pindah ke step berikutnya
updateCurrentStep(flowId, nextStep.StepOrder)
} else {
// 4. Complete approval
completeApproval(flowId)
}
}
```
### **3. User Level Hierarchy**
```go
// Level hierarchy (level_number field)
Level 1: Highest Authority (POLDAS)
Level 2: Mid Authority (POLDAS)
Level 3: Lower Authority (POLRES)
// Approval flow
Level 3 Level 2 Level 1 Approved
```
## 📈 **Data Flow Examples**
### **Example 1: Standard 3-Step Approval**
```
1. User Level 3 creates article
├── article_approval_flows: {current_step: 1, status: pending}
├── article_approvals: {approval_at_level: 2}
└── articles: {current_approval_step: 1, status: pending}
2. User Level 2 approves
├── article_approval_step_logs: {step_order: 1, action: approve}
├── article_approval_flows: {current_step: 2, status: pending}
└── articles: {current_approval_step: 2}
3. User Level 1 approves
├── article_approval_step_logs: {step_order: 2, action: approve}
├── article_approval_flows: {status: approved, completed_at: now}
└── articles: {status: approved, published: true}
```
### **Example 2: Auto-Skip Logic**
```
1. User Level 1 creates article (highest authority)
├── Check: Can skip all steps?
├── article_approval_flows: {status: approved, completed_at: now}
└── articles: {status: approved, published: true}
```
## 🚀 **API Endpoints Flow**
### **Article Creation**
```
POST /api/articles
├── Check user level
├── Create article
├── Assign workflow (if needed)
├── Create approval flow
└── Return article data
```
### **Approval Process**
```
PUT /api/article-approval-flows/{id}/approve
├── Validate approver permissions
├── Create step log
├── Check for next step
├── Update flow status
└── Send notifications
```
### **Status Checking**
```
GET /api/articles/{id}/approval-status
├── Get current flow
├── Get step logs
├── Get next step info
└── Return status data
```
## 🔍 **Debugging & Monitoring**
### **Key Queries for Monitoring**
```sql
-- Active approval flows
SELECT aaf.*, a.title, ul.name as current_approver_level
FROM article_approval_flows aaf
JOIN articles a ON aaf.article_id = a.id
JOIN approval_workflow_steps aws ON aaf.workflow_id = aws.workflow_id
AND aaf.current_step = aws.step_order
JOIN user_levels ul ON aws.required_user_level_id = ul.id
WHERE aaf.status_id = 1;
-- Approval history
SELECT aasl.*, u.name as approver_name, ul.name as level_name
FROM article_approval_step_logs aasl
JOIN users u ON aasl.approved_by_id = u.id
JOIN user_levels ul ON aasl.user_level_id = ul.id
WHERE aasl.approval_flow_id = ?;
```
## ⚠️ **Common Issues & Solutions**
### **Issue 1: Step Not Progressing**
- **Cause**: `getUserLevelId` returning wrong level
- **Solution**: Fix user level mapping logic
### **Issue 2: Wrong Approval Level**
- **Cause**: `findNextApprovalLevel` logic incorrect
- **Solution**: Fix level hierarchy comparison
### **Issue 3: Missing Step Logs**
- **Cause**: Step log not created during approval
- **Solution**: Ensure step log creation in `ApproveStep`
## 📝 **Best Practices**
1. **Always create step logs** for audit trail
2. **Validate user permissions** before approval
3. **Use transactions** for multi-table updates
4. **Implement proper error handling** for edge cases
5. **Log all approval actions** for debugging
6. **Test with different user level combinations**
## 🎯 **Summary**
Sistem approval workflow MEDOLS menggunakan arsitektur modular yang memisahkan:
- **Configuration** (workflows, steps, settings)
- **Execution** (flows, logs)
- **Legacy Support** (article_approvals)
Setiap module memiliki tanggung jawab spesifik, dan mereka bekerja sama untuk menciptakan sistem approval yang fleksibel dan dapat di-audit.