# 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.