11 KiB
11 KiB
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 keyname: Nama workflow (e.g., "Standard Approval", "Fast Track")description: Deskripsi workflowis_default: Apakah workflow default untuk clientis_active: Status aktif workflowclient_id: Client yang memiliki workflow
approval_workflow_steps - Workflow Steps Definition
- Purpose: Mendefinisikan step-step dalam workflow
- Key Fields:
id: Primary keyworkflow_id: Foreign key keapproval_workflowsstep_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 iniis_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 keyarticle_id: Foreign key kearticlesworkflow_id: Foreign key keapproval_workflowscurrent_step: Step saat ini yang sedang menunggu approvalstatus_id: Status (1=pending, 2=approved, 3=rejected, 4=revision_requested)submitted_by_id: User yang submit artikelsubmitted_at: Waktu submitcompleted_at: Waktu selesai (jika approved/rejected)
article_approval_step_logs - Step Execution History
- Purpose: Log setiap step yang telah dieksekusi
- Key Fields:
id: Primary keyapproval_flow_id: Foreign key kearticle_approval_flowsstep_order: Urutan step yang dieksekusistep_name: Nama stepapproved_by_id: User yang approve step iniaction: Aksi yang dilakukan (approve, reject, auto_skip)message: Pesan dari approverprocessed_at: Waktu eksekusi
3. Legacy & Configuration Modules
article_approvals - Legacy Approval System
- Purpose: Sistem approval legacy untuk backward compatibility
- Key Fields:
id: Primary keyarticle_id: Foreign key kearticlesapproval_by: User yang approvestatus_id: Status approvalapproval_at_level: Level yang approvemessage: Pesan approval
client_approval_settings - Client Configuration
- Purpose: Konfigurasi approval untuk setiap client
- Key Fields:
id: Primary keyclient_id: Foreign key keclientsworkflow_id: Workflow default untuk clientauto_approve_levels: Level yang auto-approvenotification_settings: Konfigurasi notifikasi
🔄 Approval Workflow Process Flow
Phase 1: Setup & Configuration
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:
- Client Registration: Client baru dibuat di sistem
- Workflow Creation: Admin membuat workflow approval
- Step Definition: Mendefinisikan step-step dengan user level requirement
- Client Configuration: Set workflow default untuk client
Phase 2: Article Submission
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 = 1article_approval_flows: New record dengancurrent_step = 1article_approvals: Legacy record untuk backward compatibility
Phase 3: Step-by-Step Approval
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 recordarticle_approval_flows: Updatecurrent_stepdanstatus_idarticles: Updatecurrent_approval_step
Phase 4: Completion
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
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
// 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
// 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
// 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
-- 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:
getUserLevelIdreturning wrong level - Solution: Fix user level mapping logic
Issue 2: Wrong Approval Level
- Cause:
findNextApprovalLevellogic 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
- Always create step logs for audit trail
- Validate user permissions before approval
- Use transactions for multi-table updates
- Implement proper error handling for edge cases
- Log all approval actions for debugging
- 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.