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

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

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

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

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

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