> ## Documentation Index
> Fetch the complete documentation index at: https://docs.quinnsambal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Home

<style>
  {`
    [class*="max-w-none"][class*="table"] {
      display: block !important;
      overflow-x: auto !important;
      max-width: 100% !important;
      width: 100% !important;
      flex-grow: 0 !important;
    }
    [class*="max-w-none"][class*="table"] > table {
      width: 100% !important;
      max-width: 100% !important;
      table-layout: fixed !important;
    }
    .mermaid {
      max-width: 100% !important;
      overflow-x: auto !important;
    }
    article svg[role="img"] {
      max-width: 100% !important;
      height: auto !important;
    }
    article img, .prose img {
      max-width: 100% !important;
      height: auto !important;
    }
    img[src*="LOGO"], img[src*="logo"] {
      max-width: 120px !important;
      max-height: 40px !important;
      width: auto !important;
      height: auto !important;
      object-fit: contain !important;
    }
    `}
</style>

***

title: "Home"
description: "Landing page personal setelah login dengan feed aktivitas terbaru, tugas pending, notifikasi real-time, dan shortcut kontekstual ke fitur utama QUINNOFSPICY ERP."
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

# Home

<img src="https://mintcdn.com/quinnofspicy/e4f_upKhVWcjsUmM/docs/mintlify/screenshots/core/home.png?fit=max&auto=format&n=e4f_upKhVWcjsUmM&q=85&s=0e96febc7aecff87a2153acf46435256" alt="Home" width="1920" height="1080" data-path="docs/mintlify/screenshots/core/home.png" />

Halaman **Home** adalah landing page personal yang muncul setelah pengguna berhasil login ke QUINNOFSPICY ERP. Berbeda dengan Dashboard yang berfokus pada metrik bisnis secara keseluruhan, Home dirancang sebagai **pusat aktivitas personal** — menampilkan tugas yang perlu diselesaikan, notifikasi dari tim dan sistem, serta aktivitas terakhir yang relevan dengan peran dan perusahaan aktif pengguna.

Halaman ini mengintegrasikan data dari berbagai entitas inti seperti `User`, `Company`, `CompanyMember`, `Task`, `Notification`, `Workspace`, `ApprovalRequest`, `InternalMessage`, dan `Achievement` untuk memberikan pengalaman yang terpersonalisasi berdasarkan role, subscription plan, dan preferensi masing-masing pengguna.

## Perbedaan Home vs Dashboard

| Aspek | Home | Dashboard |
| - | - | - |
| **Fokus** | Aktivitas personal & tugas | Metrik bisnis keseluruhan |
| **Scope** | Individual user dalam konteks perusahaan aktif | Seluruh perusahaan |
| **Data** | Tugas, notifikasi, feed aktivitas, achievement | Penjualan, stok, keuangan, produksi |
| **Pengguna** | Semua role (owner, admin, supervisor, employee, dll) | Terutama Owner & Manager |
| **Update** | Real-time per aktivitas | Real-time per transaksi |
| **Tujuan** | "Apa yang harus saya kerjakan hari ini?" | "Bagaimana performa bisnis saya?" |
| **Widget Count** | 5 komponen utama | 8+ widget + charts |
| **Interactivity** | Task completion, feed filtering, quick actions | Chart drill-down, export |
| **Personalisasi** | Berdasarkan role, preferensi, dan streak | Berdasarkan modul aktif perusahaan |
| **Konfigurasi** | `HomeSettings` + `User.preferences` | `CustomDashboardConfig` |

## Arsitektur Home Page

```mermaid theme={null}
graph TD
    subgraph "Home Page Components"
        A[Home Page] --> B[Feed Aktivitas]
        A --> C[Panel Tugas]
        A --> D[Kartu Ringkasan]
        A --> E[Kalender Mini]
        A --> F[Shortcut Kontekstual]
        A --> G[Panel Notifikasi]
        A --> H[Gamifikasi & Achievement]
    end

    subgraph "Data Sources"
        B --> S1[(Notification)]
        B --> S2[(InternalMessage)]
        C --> S3[(Task)]
        C --> S4[(RecurringTask)]
        D --> S5[(ApprovalRequest)]
        D --> S6[(CompanyPOSInventory)]
        E --> S7[(Task.due_date)]
        E --> S8[(RecurringTask)]
        F --> S9[(MenuAccessProfile)]
        F --> S10[(CompanyMember.role)]
        G --> S11[(Notification)]
        H --> S12[(Achievement)]
        H --> S13[(User.productivity_score)]
    end

    subgraph "User Context"
        U1[(User)] --> A
        U2[(Company)] --> A
        U3[(CompanyMember)] --> A
        U4[(Workspace)] --> A
    end

    subgraph "Real-Time"
        RT1[BroadcastChannel] --> B
        RT2[WebSocket] --> G
    end
```

## Komponen Utama

### 1. Feed Aktivitas & Notifikasi

Feed aktivitas menampilkan stream notifikasi dan update terbaru dari berbagai modul secara kronologis. Setiap entry dalam feed mencakup informasi dari entitas `Notification` dan `InternalMessage`.

| Kolom | Deskripsi |
| - | - |
| **Ikon Tipe** | Menandakan tipe notifikasi (SYSTEM, TASK, STOCK, INVOICE, ORDER, dll) |
| **Judul** | Ringkasan notifikasi, misal "Stok menipis: Produk ABC" |
| **Pesan** | Detail notifikasi atau konteks tambahan |
| **Prioritas** | Indikator visual berdasarkan level prioritas (low, normal, high) |
| **Timestamp** | Waktu kejadian relatif (5 menit lalu, 1 jam lalu) |
| **Status Baca** | Indikator `is_read` — badge biru untuk belum dibaca |
| **Tombol Aksi** | Aksi kontekstual berdasarkan tipe (Terima/Tolak untuk INVITATION, dll) |

**Filter Feed:**

* **Semua** — tampilkan semua notifikasi dari seluruh modul dan tipe
* **Belum Dibaca** — hanya notifikasi dengan `is_read = false`
* **Prioritas Tinggi** — notifikasi dengan `priority = high`
* **Tugas Saya** — notifikasi bertipe TASK yang melibatkan pengguna langsung
* **Tim** — notifikasi dari anggota tim dalam perusahaan aktif
* **Sistem** — notifikasi otomatis dari sistem (tipe SYSTEM, LOW\_STOCK, EXPIRY, BACKUP)

**Feed Entry Schema** (berdasarkan entitas `Notification`):

| Field | Type | Required | Deskripsi |
| - | - | - | - |
| `user_id` | String | Ya | Email pengguna yang menerima notifikasi |
| `title` | String | Ya | Judul notifikasi |
| `message` | String | Ya | Pesan notifikasi |
| `description` | String | Tidak | Detail tambahan atau konteks (maks 1000 karakter) |
| `url` | String | Tidak | URL tujuan saat notifikasi diklik |
| `type` | Enum | Tidak | Tipe notifikasi: SYSTEM, INVITATION, TASK, STOCK, INVOICE, WORKFLOW, ANNOUNCEMENT, ORDER, PAYMENT, LOW\_STOCK, DISCREPANCY, EXPIRY, BACKUP, BTT\_PENDING, PAYMENT\_DUE, RECALL |
| `metadata` | Object | Tidak | Payload tambahan (invitationId, companyId, companyName) |
| `priority` | Enum | Tidak | Prioritas: low, normal, high (default: normal) |
| `is_read` | Boolean | Tidak | Status apakah sudah dibaca (default: false) |
| `event_id` | String | Tidak | Idempotency key — format `{type}:{entity}:{id}` |
| `company_id` | String | Tidak | ID perusahaan untuk scope filter |
| `location_id` | String | Tidak | ID lokasi untuk scope filter (opsional) |
| `source_entity` | String | Tidak | Nama entity sumber (POSTransaction, Invoice, ProductionBatch, dll) |
| `source_id` | String | Tidak | ID record sumber |
| `correlation_id` | String | Tidak | Correlation ID untuk observability (NFR-04) |

### 2. Panel Tugas & Reminder

Panel ini menampilkan daftar tugas yang perlu diselesaikan, diurutkan berdasarkan prioritas dan deadline. Data diambil dari entitas `Task` dan `RecurringTask` yang terkait dengan pengguna melalui `assignee_id` atau `workspace_id`.

| Status | Warna | Deskripsi |
| - | - | - |
| **Urgent** | Merah | Deadline hari ini atau sudah overdue |
| **High** | Oranye | Deadline 1-2 hari ke depan |
| **Medium** | Biru | Deadline minggu ini |
| **Low** | Abu-abu | Tidak ada deadline spesifik |

**Fitur Tugas:**

* **Snooze** — tunda tugas untuk muncul lagi nanti (1 jam, besok, atau custom)
* **Quick Complete** — tandai selesai langsung dari Home tanpa buka detail (mengubah `status` ke `completed`)
* **Delegasi** — tugaskan ke anggota tim lain melalui `assignee_id` jika memiliki hak akses `can_edit_tasks`
* **Link ke Sumber** — setiap tugas terhubung ke halaman terkait (invoice, PO, dll)
* **Time Tracking** — catat waktu pengerjaan melalui `time_entries` jika `is_time_tracked = true`
* **Sub-tasks** — tugas dapat memiliki sub-tugas melalui `parent_task_id` dan `sub_tasks`

**Task Entity Schema** (dari entitas `Task`):

| Field | Type | Required | Deskripsi |
| - | - | - | - |
| `workspace_id` | String | Ya | ID workspace tempat tugas berada |
| `company_id` | String | Tidak | ID perusahaan (null untuk personal) |
| `title` | String | Ya | Judul tugas |
| `content` | String | Tidak | Detail/deskripsi tugas |
| `status` | Enum | Tidak | Status: todo, in\_progress, completed, done (default: todo) |
| `priority` | Enum | Tidak | Prioritas: low, medium, high, urgent (default: medium) |
| `due_date` | DateTime | Tidak | Batas waktu penyelesaian |
| `assignee_id` | String | Tidak | ID pengguna yang ditugaskan |
| `tags` | String\[] | Tidak | Label/tag custom untuk kategorisasi |
| `estimated_time` | Number | Tidak | Estimasi waktu dalam menit |
| `actual_time` | Number | Tidak | Waktu aktual yang dihabiskan dalam menit |
| `is_time_tracked` | Boolean | Tidak | Apakah time tracking aktif (default: false) |
| `time_entries` | Array | Tidak | Daftar entri waktu (start, end, duration) |
| `parent_task_id` | String | Tidak | ID parent task untuk sub-tasks |
| `sub_tasks` | String\[] | Tidak | Array of sub-task IDs |
| `recurring_task_id` | String | Tidak | ID recurring task jika dibuat otomatis |
| `completed_at` | DateTime | Tidak | Timestamp saat tugas diselesaikan |
| `reminder_sent` | Boolean | Tidak | Apakah reminder sudah dikirim (default: false) |
| `google_event_id` | String | Tidak | ID event pada Google Calendar |
| `reminder_config` | Object | Tidak | Konfigurasi notifikasi sebelum tugas |

### 3. Kartu Ringkasan

Kartu informasi singkat yang memberikan gambaran kondisi bisnis hari ini berdasarkan data dari perusahaan aktif pengguna (`User.active_company_id`):

| Kartu | Isi | Sumber Data | Aksi Cepat |
| - | - | - | - |
| **Penjualan Hari Ini** | Total transaksi & revenue | `CompanyPOSTransaction` | Klik → buka modul POS |
| **Order Baru** | Jumlah order masuk belum diproses | `MarketplaceOrder`, `ProductOrder` | Klik → buka modul Order |
| **Stok Menipis** | Jumlah produk di bawah minimum | `CompanyPOSInventory` | Klik → buka Inventory Alert |
| **Approval Pending** | Dokumen menunggu approval | `ApprovalRequest` (status: pending) | Klik → buka approval queue |
| **Tugas Hari Ini** | Jumlah tugas dengan deadline hari ini | `Task` (due\_date = today) | Klik → buka Panel Tugas |

### 4. Kalender Mini

Widget kalender yang menampilkan jadwal penting dari berbagai sumber:

* **Deadline Tugas** — tugas dengan `due_date` terdekat dari entitas `Task`
* **Recurring Tasks** — tugas berulang dari entitas `RecurringTask` berdasarkan `frequency` dan `days_of_week`
* **Approval Deadline** — batas waktu persetujuan dari `ApprovalRequest`
* **Event Perusahaan** — jadwal shift dari `CompanyMember.working_hours`

### 5. Shortcut Kontekstual

Shortcut yang ditampilkan berdasarkan peran pengguna (`CompanyMember.role`) dan profil akses menu (`MenuAccessProfile`):

| Role | Shortcut yang Ditampilkan |
| - | - |
| **Owner** | Laporan Keuangan, Dashboard Analytics, Approval, Manajemen Member |
| **Admin** | Dashboard, Manajemen Tugas, Laporan, Pengaturan |
| **Supervisor** | Monitoring Tim, Approval, Laporan Shift |
| **Store Admin** | Transaksi Baru, Buka Kasir, Tutup Kasir, Laporan POS |
| **Stock Admin** | Stock Opname, Terima Barang, Transfer Stok, Inventory Alert |
| **Finance Admin** | Invoice Baru, Catat Expense, Rekonsiliasi, Laporan Keuangan |
| **HR Admin** | Absensi, Leave Approval, Payroll, Manajemen Karyawan |
| **Transaction Admin** | Transaksi Baru, Riwayat Transaksi, Retur |
| **Employee** | Tugas Saya, Notifikasi, Kalender |
| **Production Operator** | Production Order Baru, QC Check, BOM List |
| **QC Inspector** | QC Check, HACCP Verification, Quality Report |
| **Sales Marketing** | Pelanggan Baru, Order Baru, Kirim WhatsApp |
| **Partner Distributor** | Distribution Order, Shipment, Invoice B2B |

### 6. Panel Gamifikasi & Achievement

Panel yang menampilkan progres gamifikasi berdasarkan entitas `Achievement` dan statistik produktivitas pengguna (`User`):

| Metrik | Sumber | Deskripsi |
| - | - | - |
| **Productivity Score** | `User.productivity_score` | Skor produktivitas kumulatif |
| **Current Streak** | `User.current_streak` | Hari berturut-turut menyelesaikan tugas |
| **Longest Streak** | `User.longest_streak` | Rekor hari berturut-turut terbaik |
| **Level** | `User.user_level` | Level berdasarkan achievement points |
| **Achievement Points** | `User.achievement_points` | Total poin pencapaian |
| **Total Tasks Completed** | `User.total_tasks_completed` | Akumulasi tugas yang diselesaikan |
| **Total Notes Created** | `User.total_notes_created` | Akumulasi catatan yang dibuat |

## Feed Aktivitas — Detail Arsitektur

```mermaid theme={null}
flowchart TD
    subgraph "Event Sources"
        POS[POS Transaction] --> Router
        INV[Inventory Change] --> Router
        FIN[Finance Event] --> Router
        CRM[CRM Update] --> Router
        HR[HR Check-in] --> Router
        MFG[Production Update] --> Router
        APPROVAL[Approval Request] --> Router
        MESSAGE[Internal Message] --> Router
    end

    subgraph "Activity Router"
        Router[Event Router] --> Filter[User Scope Filter]
        Filter --> CompanyFilter[Company Scope Filter]
        CompanyFilter --> Formatter[Entry Formatter]
        Formatter --> Dedup[Idempotency Check via event_id]
        Dedup --> Store[(Notification Store)]
    end

    subgraph "Home Feed"
        Store --> Feed[Feed Component]
        Feed --> FilterUI[Filter Tabs]
        FilterUI --> All[Semua]
        FilterUI --> Unread[Belum Dibaca]
        FilterUI --> HighPriority[Prioritas Tinggi]
        FilterUI --> MyTasks[Tugas Saya]
        FilterUI --> Team[Tim]
        FilterUI --> System[Sistem]
    end
```

## Flow Penggunaan Harian

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant H as Home Page
    participant API as Backend API
    participant DB as Database
    participant M as Modul Terkait

    U->>H: Login ke QUINNOFSPICY ERP
    H->>API: GET /user/profile (ambil User, CompanyMember, Company)
    API->>DB: Query User + active_company_id
    DB-->>API: Return user data
    API-->>H: Return profile + company context

    H->>API: GET /notifications?user_id=X&is_read=false&limit=20
    API->>DB: Query Notification (filtered)
    DB-->>API: Return notifications
    API-->>H: Return notification list

    H->>API: GET /tasks?assignee_id=X&status=todo,in_progress
    API->>DB: Query Task (filtered by assignee)
    DB-->>API: Return tasks
    API-->>H: Return task list

    H->>API: GET /approval-requests?approver=X&status=pending
    API->>DB: Query ApprovalRequest
    DB-->>API: Return pending approvals
    API-->>H: Return approval summary

    H-->>U: Tampilkan feed, tugas, notifikasi, ringkasan

    U->>H: Cek tugas urgent hari ini
    U->>H: Review notifikasi baru
    U->>H: Klik tugas untuk detail
    H->>M: Redirect ke halaman terkait
    M-->>U: Kerjakan tugas di modul
    U->>H: Kembali ke Home, tandai selesai
    H->>API: PATCH /tasks/{id} (status = completed)
    API->>DB: Update Task
    H->>API: Update User.productivity_score + streak
```

## Notifikasi & Alert

Sistem notifikasi di Home menggunakan entitas `Notification` yang terbagi menjadi beberapa tipe dan prioritas. Setiap notifikasi memiliki mekanisme idempotency melalui `event_id` untuk mencegah duplikasi.

| Kategori | Tipe Notifikasi | Contoh | Prioritas Default |
| - | - | - | - |
| **Transaksi** | ORDER, PAYMENT | Order baru, pembayaran diterima | Normal |
| **Inventori** | STOCK, LOW\_STOCK | Stok menipis, barang masuk | High |
| **Produksi** | SYSTEM | Batch selesai, QC failed, EXPIRY | High |
| **Keuangan** | INVOICE, PAYMENT\_DUE | Invoice overdue, BTT pending | High |
| **Tim** | TASK, ANNOUNCEMENT | Tugas baru, mention di komentar | Normal |
| **Workflow** | WORKFLOW | Approval request, workflow alert | Normal |
| **Undangan** | INVITATION | Undangan bergabung perusahaan | Normal |
| **Sistem** | SYSTEM, BACKUP, RECALL | Maintenance, backup selesai, product recall | Low |
| **Discrepancy** | DISCREPANCY | Selisih stock opname | High |

### Notifikasi vs Tugas

```mermaid theme={null}
flowchart LR
    subgraph "Notifikasi (Inform)"
        N1[Stok menipis - LOW_STOCK]
        N2[Transaksi baru - ORDER]
        N3[Update sistem - SYSTEM]
        N4[Invoice overdue - INVOICE]
        N5[Undangan - INVITATION]
    end

    subgraph "Tugas (Action Required)"
        T1[Approval invoice - TASK]
        T2[QC check - TASK]
        T3[Follow-up customer - TASK]
        T4[Stock opname - TASK]
    end

    subgraph "Home Panel"
        N1 & N2 & N3 & N4 & N5 --> Feed[Feed Aktivitas / Notifikasi]
        T1 & T2 & T3 & T4 --> TaskPanel[Panel Tugas]
    end

    Feed --> MarkRead[Tandai Dibaca - is_read = true]
    TaskPanel --> Complete[Tandai Selesai - status = completed]
```

## Cara Akses

| Metode | Cara |
| - | - |
| **Setelah Login** | Otomatis diarahkan ke Home |
| **Sidebar** | Klik ikon **Rumah** di pojok kiri atas sidebar |
| **Keyboard** | Tekan tombol `Home` di keyboard |
| **Breadcrumb** | Klik "Home" di breadcrumb navigation |

## Tips

* **Jadikan Home sebagai starting point** setiap hari kerja untuk melihat apa yang perlu ditindaklanjuti sebelum mulai aktivitas lain
* **Selesaikan tugas urgent di Home** sebelum pindah ke modul lain supaya tidak ada yang terlewat
* **Gunakan fitur snooze** untuk tugas yang belum bisa dikerjakan sekarang — tugas akan muncul lagi sebagai reminder
* **Filter feed berdasarkan "Tugas Saya"** jika kamu hanya ingin fokus pada tugas personal tanpa terganggu aktivitas tim
* **Kustomisasi shortcut** dengan frequently used actions supaya akses ke fitur favorit lebih cepat

***

## Entity Relationship Diagram

```mermaid theme={null}
erDiagram
    Workspace ||--o{ Task : "memiliki"
    Workspace ||--o{ WorkspaceMember : "memiliki"
    Workspace ||--o{ RecurringTask : "memiliki"
    WorkspaceMember }o--|| User : "anggota"
    Task }o--o| Task : "parent_task"
    Task }o--o| RecurringTask : "dibuat_oleh"
    Task ||--o{ Comment : "memiliki"
    Task }o--|| User : "ditugaskan_ke"

    Company ||--o{ HomeSettings : "mengkonfigurasi"
    Company ||--o{ Notification : "menghasilkan"
    Company ||--o{ StockAlert : "menghasilkan"
    Company ||--o{ CustomDashboardConfig : "memiliki"
    Company ||--o{ ApprovalRequest : "memiliki"
    Company ||--o{ AuditLog : "mencatat"
    Company ||--o{ Task : "memiliki"

    Notification }o--|| User : "dikirim_ke"
    Notification }o--o| Company : "berlaku_untuk"

    StockAlert }o--|| Company : "milik"
    StockAlert }o--o| Inventory : "terkait"
    StockAlert }o--o| Product : "terkait"

    CustomDashboardConfig }o--|| User : "dimilik_oleh"
    CustomDashboardConfig }o--|| Company : "milik"

    ApprovalRequest }o--|| ApprovalWorkflow : "mengikuti"
    ApprovalRequest }o--|| User : "diajukan_oleh"

    RecurringTask }o--|| Task : "membuat"
    RecurringTask }o--|| User : "ditugaskan_ke"

    AuditLog }o--|| User : "dicatat_untuk"

    Comment }o--|| User : "dibuat_oleh"

    Workspace {
        string company_id "ID perusahaan"
        string name "Nama workspace"
        string description "Deskripsi workspace"
        string icon "Icon workspace"
        string color "Warna tema workspace"
        string owner_id "ID pemilik workspace"
        boolean is_personal "Apakah workspace pribadi"
        object settings "Pengaturan workspace"
    }

    WorkspaceMember {
        string workspace_id "ID workspace"
        string user_id "Email pengguna"
        string role "Peran dalam workspace"
        string invited_by "Email pengundang"
        datetime joined_at "Waktu bergabung"
        string description "Catatan tambahan"
        object permissions "Hak akses anggota"
    }

    Task {
        string workspace_id "ID workspace"
        string company_id "ID perusahaan"
        string title "Judul tugas"
        string content "Isi tugas"
        string status "Status tugas"
        string priority "Prioritas tugas"
        datetime due_date "Batas waktu"
        string assignee_id "ID penugasan"
        array tags "Label tugas"
        number estimated_time "Estimasi waktu (menit)"
        number actual_time "Waktu aktual (menit)"
        boolean is_time_tracked "Apakah waktu dilacak"
        array time_entries "Catatan waktu"
        string parent_task_id "ID parent task"
        array sub_tasks "Array ID sub-task"
        string recurring_task_id "ID recurring task"
        datetime completed_at "Waktu selesai"
        boolean reminder_sent "Apakah reminder terkirim"
        string google_event_id "ID Google Calendar"
        object reminder_config "Konfigurasi reminder"
    }

    Notification {
        string user_id "Email penerima"
        string title "Judul notifikasi"
        string message "Pesan notifikasi"
        string description "Detail tambahan"
        string url "URL tujuan"
        string type "Tipe notifikasi"
        object metadata "Payload tambahan"
        string priority "Prioritas notifikasi"
        boolean is_read "Status sudah dibaca"
        string event_id "Idempotency key"
        string company_id "ID perusahaan"
        string location_id "ID lokasi"
        string source_entity "Nama entity sumber"
        string source_id "ID record sumber"
        string correlation_id "Correlation ID"
    }

    HomeSettings {
        string setting_key "Kunci pengaturan unik"
        string description "Penjelasan konfigurasi"
        string hero_title "Judul hero section"
        string hero_subtitle "Subtitle hero"
        string hero_cta_text "Teks tombol CTA"
        string hero_image_url "URL gambar hero"
        array features "Daftar fitur utama"
        array testimonials "Testimoni pengguna"
        object stats "Statistik aplikasi"
        string contact_email "Email kontak"
        string contact_whatsapp "Nomor WhatsApp"
        object social_links "Tautan sosial media"
    }

    CustomDashboardConfig {
        string company_id "ID perusahaan"
        string user_id "ID pengguna"
        string dashboard_name "Nama dashboard"
        string description "Deskripsi dashboard"
        string role "Role akses"
        boolean is_public "Akses publik"
        array widgets "Daftar widget"
        string layout "Tata letak dashboard"
        datetime created_date "Tanggal dibuat"
        datetime last_modified_date "Terakhir dimodifikasi"
    }

    StockAlert {
        string company_id "ID perusahaan"
        string inventory_id "ID inventori"
        string product_id "ID produk"
        string product_name "Nama produk"
        string location_id "ID lokasi"
        string location_name "Nama lokasi"
        string alert_type "Tipe alert"
        number current_quantity "Jumlah saat ini"
        number threshold_quantity "Jumlah ambang batas"
        string severity "Tingkat keparahan"
        string status "Status alert"
        string title "Ringkasan alert"
        string description "Penjelasan detail"
        string recommended_action "Tindakan disarankan"
        string fingerprint "Key anti-duplikat"
        string source "Asal deteksi"
        string entity_ref_id "ID entitas terkait"
        array movement_ids "ID StockMovement"
        datetime detected_at "Waktu terdeteksi"
        string acknowledged_by "Diakui oleh"
        datetime acknowledged_at "Waktu diakui"
        datetime resolved_at "Waktu diselesaikan"
        boolean auto_reorder_triggered "Auto reorder aktif"
        string notes "Catatan"
    }

    ApprovalRequest {
        string company_id "ID perusahaan"
        string workflow_id "ID ApprovalWorkflow"
        string document_type "Tipe dokumen"
        string document_id "ID dokumen"
        string requester_id "ID pemohon"
        datetime submission_date "Tanggal pengajuan"
        number amount "Jumlah"
        string description "Deskripsi"
        number current_approval_level "Level approval saat ini"
        array approval_history "Riwayat approval"
        string overall_status "Status keseluruhan"
        datetime final_approval_date "Tanggal approval final"
    }

    RecurringTask {
        string task_id "ID tugas template"
        string workspace_id "ID workspace"
        string title "Judul tugas"
        string content "Isi tugas"
        string frequency "Frekuensi pengulangan"
        number interval "Interval pengulangan"
        array days_of_week "Hari dalam seminggu"
        number day_of_month "Hari dalam sebulan"
        datetime start_date "Tanggal mulai"
        datetime end_date "Tanggal berakhir"
        boolean is_active "Apakah aktif"
        datetime last_generated "Terakhir dibuat"
        string priority "Prioritas tugas"
        string assignee_id "ID penugasan"
    }

    AuditLog {
        string company_id "ID perusahaan"
        string user_id "ID pengguna"
        string user_email "Email pengguna"
        string action "Aksi yang dilakukan"
        string entity_type "Tipe entitas"
        string entity_id "ID entitas"
        object old_value "Nilai lama"
        object new_value "Nilai baru"
        datetime timestamp "Waktu kejadian"
        string ip_address "Alamat IP"
        string device_info "Info device"
        string description "Deskripsi aksi"
        string status "Status aksi"
    }

    Comment {
        string entity_type "Jenis entitas"
        string entity_id "ID entitas"
        string workspace_id "ID workspace"
        string content "Isi komentar"
        string user_id "ID pengguna"
        string user_name "Nama pengguna"
        string user_email "Email pengguna"
        array mentions "Array user yang di-mention"
        string parent_comment_id "ID parent comment"
        datetime edited_at "Waktu diedit"
    }
```

## Entity Schema Tables

### HomeSettings

| Field | Type | Required | Description |
| - | - | - | - |
| `setting_key` | string | Ya | Kunci pengaturan unik, gunakan nilai `'main'` untuk konfigurasi utama |
| `description` | string | Tidak | Penjelasan mengenai konfigurasi halaman utama ini (maks. 1000 karakter) |
| `hero_title` | string | Tidak | Judul utama yang ditampilkan pada hero section halaman Home |
| `hero_subtitle` | string | Tidak | Subtitle yang ditampilkan di bawah judul hero |
| `hero_cta_text` | string | Tidak | Teks pada tombol call-to-action di hero section |
| `hero_image_url` | string | Tidak | URL gambar yang ditampilkan pada hero section |
| `features` | array\[object] | Tidak | Daftar fitur utama yang ditampilkan, masing-masing memiliki `title`, `description`, dan `icon` |
| `testimonials` | array\[object] | Tidak | Testimoni pengguna yang ditampilkan, masing-masing memiliki `name`, `role`, `content`, dan `avatar_url` |
| `stats` | object | Tidak | Statistik aplikasi berisi `users`, `tasks`, dan `workspaces` dalam tipe number |
| `contact_email` | string | Tidak | Alamat email kontak, default: `snishopsolusinetwork@gmail.com` |
| `contact_whatsapp` | string | Tidak | Nomor WhatsApp kontak, default: `081532168812` |
| `social_links` | object | Tidak | Tautan media sosial dengan key `facebook`, `instagram`, `twitter`, dan `linkedin` |

### Notification

| Field | Type | Required | Description |
| - | - | - | - |
| `user_id` | string | Ya | Email pengguna yang menerima notifikasi |
| `title` | string | Ya | Judul notifikasi yang ditampilkan kepada pengguna |
| `message` | string | Ya | Pesan utama notifikasi |
| `description` | string | Tidak | Detail tambahan atau konteks dari notifikasi (maks. 1000 karakter) |
| `url` | string | Tidak | URL tujuan saat notifikasi diklik oleh pengguna |
| `type` | enum | Tidak | Tipe notifikasi untuk menentukan render aksi, default: `SYSTEM` |
| `metadata` | object | Tidak | Payload tambahan berisi `invitationId`, `companyId`, `companyName` untuk konteks notifikasi |
| `priority` | enum | Tidak | Prioritas notifikasi: `low`, `normal`, atau `high`, default: `normal` |
| `is_read` | boolean | Tidak | Status apakah notifikasi sudah dibaca, default: `false` |
| `event_id` | string | Tidak | Idempotency key dengan format `{type}:{entity}:{id}` untuk mencegah notifikasi duplikat |
| `company_id` | string | Tidak | ID perusahaan untuk filter scope notifikasi |
| `location_id` | string | Tidak | ID lokasi untuk filter scope notifikasi (opsional) |
| `source_entity` | string | Tidak | Nama entity sumber seperti POSTransaction, Invoice, ProductionBatch |
| `source_id` | string | Tidak | ID record sumber yang memicu notifikasi |
| `correlation_id` | string | Tidak | Correlation ID dari request kritis untuk keperluan observability (NFR-04) |

### Task

| Field | Type | Required | Description |
| - | - | - | - |
| `workspace_id` | string | Ya | ID workspace tempat tugas ini berada |
| `company_id` | string | Tidak | ID perusahaan, null untuk tugas personal |
| `title` | string | Ya | Judul tugas yang ditampilkan |
| `content` | string | Tidak | Isi atau deskripsi detail tugas |
| `status` | enum | Tidak | Status tugas: `todo`, `in_progress`, `completed`, atau `done`, default: `todo` |
| `priority` | enum | Tidak | Tingkat prioritas: `low`, `medium`, `high`, atau `urgent`, default: `medium` |
| `due_date` | datetime | Tidak | Batas waktu penyelesaian tugas |
| `assignee_id` | string | Tidak | ID pengguna yang ditugaskan mengerjakan tugas ini |
| `tags` | array\[string] | Tidak | Label atau tag untuk kategorisasi tugas |
| `estimated_time` | number | Tidak | Estimasi waktu penyelesaian dalam satuan menit |
| `actual_time` | number | Tidak | Waktu aktual yang dihabiskan dalam satuan menit |
| `is_time_tracked` | boolean | Tidak | Penanda apakah waktu pengerjaan dilacak, default: `false` |
| `time_entries` | array\[object] | Tidak | Daftar catatan waktu, masing-masing berisi `start`, `end`, dan `duration` |
| `parent_task_id` | string | Tidak | ID parent task untuk relasi sub-tugas hierarkis |
| `sub_tasks` | array\[string] | Tidak | Array berisi ID dari sub-task yang terkait |
| `recurring_task_id` | string | Tidak | ID RecurringTask jika tugas ini dibuat secara otomatis oleh jadwal berulang |
| `completed_at` | datetime | Tidak | Timestamp saat tugas ditandai selesai |
| `reminder_sent` | boolean | Tidak | Penanda apakah reminder sudah dikirimkan, default: `false` |
| `google_event_id` | string | Tidak | ID event pada Google Calendar untuk sinkronisasi kalender |
| `reminder_config` | object | Tidak | Konfigurasi notifikasi reminder sebelum tugas jatuh tempo |

### CustomDashboardConfig

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan pemilik dashboard |
| `user_id` | string | Ya | ID pengguna yang membuat konfigurasi dashboard |
| `dashboard_name` | string | Ya | Nama dashboard yang ditampilkan |
| `description` | string | Tidak | Deskripsi singkat mengenai dashboard |
| `role` | string | Tidak | Role yang diizinkan mengakses dashboard ini (opsional) |
| `is_public` | boolean | Tidak | Apakah dashboard dapat diakses oleh anggota lain, default: `false` |
| `widgets` | array\[object] | Ya | Daftar widget yang ditampilkan pada dashboard |
| `layout` | enum | Tidak | Tata letak dashboard: `grid` atau `list`, default: `grid` |
| `created_date` | datetime | Tidak | Timestamp kapan dashboard pertama kali dibuat |
| `last_modified_date` | datetime | Tidak | Timestamp terakhir kali dashboard dimodifikasi |

**Struktur Widget (dalam array `widgets`):**

| Field | Type | Description |
| - | - | - |
| `widget_id` | string | Identifier unik untuk widget |
| `widget_type` | enum | Tipe widget: `chart`, `table`, `metric`, `list`, `calendar`, atau `forecast` |
| `title` | string | Judul widget yang ditampilkan |
| `data_source` | string | Tipe entity sumber data (Invoice, FinancialRecord, dll) |
| `filters` | object | Konfigurasi filter data untuk widget |
| `chart_type` | enum | Tipe visualisasi chart: `line`, `bar`, `pie`, atau `area` |
| `position` | object | Posisi widget berisi `row`, `column`, `width`, dan `height` |
| `refresh_interval` | number | Interval auto-refresh dalam satuan detik |

### StockAlert

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan tempat alert ini berlaku |
| `inventory_id` | string | Tidak | ID record inventori yang terkait |
| `product_id` | string | Tidak | ID produk yang memicu alert |
| `product_name` | string | Tidak | Nama produk yang terkait |
| `location_id` | string | Tidak | ID lokasi gudang tempat alert terdeteksi |
| `location_name` | string | Tidak | Nama lokasi gudang |
| `alert_type` | enum | Ya | Tipe alert stok, menentukan kategori anomali yang terdeteksi |
| `current_quantity` | number | Tidak | Jumlah stok saat ini |
| `threshold_quantity` | number | Tidak | Jumlah ambang batas yang memicu alert |
| `severity` | enum | Tidak | Tingkat keparahan: `low`, `medium`, `high`, atau `critical`, default: `medium` |
| `status` | enum | Tidak | Status penanganan: `active`, `acknowledged`, `dismissed`, atau `resolved`, default: `active` |
| `title` | string | Tidak | Ringkasan singkat alert untuk tampilan daftar |
| `description` | string | Tidak | Penjelasan detail mengenai anomali atau kondisi yang terdeteksi |
| `recommended_action` | string | Tidak | Tindakan yang disarankan oleh sistem untuk menangani alert |
| `fingerprint` | string | Tidak | Key stabil per anomali untuk mencegah notifikasi duplikat antar perangkat |
| `source` | string | Tidak | Asal deteksi alert, misalnya `stock_anomaly_detector` |
| `entity_ref_id` | string | Tidak | ID entitas terkait seperti LotBatch atau StockMovement |
| `movement_ids` | array\[string] | Tidak | Array ID StockMovement yang memicu anomali |
| `detected_at` | datetime | Tidak | Timestamp kapan anomali terdeteksi oleh scanner |
| `acknowledged_by` | string | Tidak | ID pengguna yang mengakui alert |
| `acknowledged_at` | datetime | Tidak | Timestamp kapan alert diakui |
| `resolved_at` | datetime | Tidak | Timestamp kapan alert diselesaikan |
| `auto_reorder_triggered` | boolean | Tidak | Penanda apakah proses reorder otomatis sudah dipicu, default: `false` |
| `notes` | string | Tidak | Catatan tambahan dari pengguna terkait penanganan alert |

### ApprovalRequest

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan tempat approval diajukan |
| `workflow_id` | string | Ya | ID ApprovalWorkflow yang mengatur alur persetujuan |
| `document_type` | string | Ya | Tipe dokumen yang memerlukan persetujuan |
| `document_id` | string | Ya | ID dokumen yang diminta persetujuan |
| `requester_id` | string | Ya | ID pengguna yang mengajukan persetujuan |
| `submission_date` | datetime | Tidak | Tanggal dan waktu pengajuan |
| `amount` | number | Tidak | Jumlah nilai dokumen (jika ada) |
| `description` | string | Tidak | Deskripsi atau catatan pengajuan |
| `current_approval_level` | number | Tidak | Level approval yang sedang aktif, default: `1` |
| `approval_history` | array\[object] | Tidak | Riwayat approval per level, berisi `level`, `approver_id`, `approval_date`, `status`, dan `comments` |
| `overall_status` | enum | Tidak | Status keseluruhan: `pending`, `approved`, `rejected`, atau `on_hold`, default: `pending` |
| `final_approval_date` | datetime | Tidak | Timestamp saat approval final diberikan |

### RecurringTask

| Field | Type | Required | Description |
| - | - | - | - |
| `task_id` | string | Tidak | ID tugas template yang menjadi acuan |
| `workspace_id` | string | Ya | ID workspace tempat tugas berulang dibuat |
| `title` | string | Ya | Judul tugas yang akan dibuat berulang |
| `content` | string | Tidak | Isi atau deskripsi tugas |
| `frequency` | enum | Ya | Frekuensi pengulangan: `daily`, `weekly`, `monthly`, atau `yearly` |
| `interval` | number | Tidak | Interval pengulangan, default: `1` (setiap 1 periode) |
| `days_of_week` | array\[number] | Tidak | Array hari dalam seminggu (0-6) untuk jadwal weekly |
| `day_of_month` | number | Tidak | Hari dalam sebulan untuk jadwal monthly |
| `start_date` | datetime | Ya | Tanggal mulai berlakunya tugas berulang |
| `end_date` | datetime | Tidak | Tanggal berakhirnya tugas berulang (opsional) |
| `is_active` | boolean | Tidak | Penanda apakah jadwal berulang masih aktif, default: `true` |
| `last_generated` | datetime | Tidak | Timestamp terakhir kali tugas baru dibuat dari jadwal |
| `priority` | enum | Tidak | Prioritas tugas: `low`, `medium`, `high`, atau `urgent`, default: `medium` |
| `assignee_id` | string | Tidak | ID pengguna yang ditugaskan secara default |

### AuditLog

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan tempat aksi dilakukan |
| `user_id` | string | Ya | ID pengguna yang melakukan aksi |
| `user_email` | string | Tidak | Email pengguna yang melakukan aksi |
| `action` | enum | Ya | Aksi yang dilakukan terhadap entitas |
| `entity_type` | string | Ya | Tipe entitas yang diakses (Task, Invoice, Product, dll) |
| `entity_id` | string | Tidak | ID entitas yang diakses |
| `old_value` | object | Tidak | Nilai lama sebelum perubahan (khusus aksi update) |
| `new_value` | object | Tidak | Nilai baru setelah perubahan (khusus aksi update) |
| `timestamp` | datetime | Ya | Waktu kejadian aksi dicatat |
| `ip_address` | string | Tidak | Alamat IP dari mana aksi dilakukan |
| `device_info` | string | Tidak | User Agent atau informasi device pengguna |
| `description` | string | Tidak | Deskripsi detail mengenai aksi yang dilakukan |
| `status` | enum | Tidak | Status eksekusi: `success` atau `failed`, default: `success` |

### Comment

| Field | Type | Required | Description |
| - | - | - | - |
| `entity_type` | enum | Ya | Jenis entitas yang dikomentari: `task` atau `note` |
| `entity_id` | string | Ya | ID dari task atau note yang dikomentari |
| `workspace_id` | string | Tidak | ID workspace tempat komentar dibuat |
| `content` | string | Ya | Isi teks komentar |
| `user_id` | string | Ya | ID pengguna yang menulis komentar |
| `user_name` | string | Tidak | Nama lengkap pengguna saat komentar ditulis |
| `user_email` | string | Tidak | Email pengguna saat komentar ditulis |
| `mentions` | array\[string] | Tidak | Array ID pengguna yang di-mention dalam komentar |
| `parent_comment_id` | string | Tidak | ID parent comment untuk membalas komentar lain (threaded) |
| `edited_at` | datetime | Tidak | Timestamp terakhir kali komentar diedit |

### Workspace

| Field | Type | Required | Description |
| - | - | - | - |
| `company_id` | string | Tidak | ID perusahaan, null untuk workspace personal |
| `name` | string | Ya | Nama workspace yang ditampilkan |
| `description` | string | Tidak | Deskripsi singkat mengenai workspace |
| `icon` | string | Tidak | Icon atau emoji yang mewakili workspace |
| `color` | string | Tidak | Warna tema workspace dalam format hex, default: `#2563eb` |
| `owner_id` | string | Ya | ID pengguna pemilik workspace |
| `is_personal` | boolean | Tidak | Penanda apakah workspace bersifat pribadi, default: `false` |
| `settings` | object | Tidak | Pengaturan workspace berisi `allow_public_sharing` dan `default_task_priority` |

### WorkspaceMember

| Field | Type | Required | Description |
| - | - | - | - |
| `workspace_id` | string | Ya | ID workspace yang diikuti |
| `user_id` | string | Ya | Email pengguna anggota workspace |
| `role` | enum | Tidak | Peran dalam workspace: `owner`, `admin`, `member`, atau `viewer`, default: `member` |
| `invited_by` | string | Tidak | Email pengguna yang mengundang anggota ini |
| `joined_at` | datetime | Tidak | Timestamp kapan anggota bergabung |
| `description` | string | Tidak | Catatan atau keterangan tambahan mengenai anggota (maks. 1000 karakter) |
| `permissions` | object | Tidak | Hak akses anggota berisi `can_create_tasks`, `can_edit_tasks`, `can_delete_tasks`, `can_invite_members`, `can_access_all_tasks` |

## Status Lifecycle — State Diagrams

### Task Status Lifecycle

```mermaid theme={null}
stateDiagram-v2
    [*] --> todo: Tugas dibuat
    todo --> in_progress: Pengerjaan dimulai
    in_progress --> completed: Pekerjaan selesai
    completed --> done: Diverifikasi/disetujui
    done --> [*]

    todo --> todo: Prioritas diubah
    in_progress --> todo: Dikembalikan ke antrian
    completed --> in_progress: Perlu revisi
    done --> in_progress: Re-open tugas
```

### Notification Read State

```mermaid theme={null}
stateDiagram-v2
    [*] --> unread: Notifikasi diterima
    unread --> read: Pengguna membuka notifikasi
    read --> [*]

    note right of unread
        is_read = false
    end note

    note right of read
        is_read = true
    end note
```

### StockAlert Status Lifecycle

```mermaid theme={null}
stateDiagram-v2
    [*] --> active: Anomali terdeteksi
    active --> acknowledged: Pengguna mengakui alert
    acknowledged --> resolved: Masalah diselesaikan
    active --> dismissed: Alert diabaikan
    active --> resolved: Masalah langsung diselesaikan
    resolved --> [*]
    dismissed --> [*]

    state active {
        [*] --> waiting_review
        waiting_review --> auto_reorder: Stok di bawah threshold
        auto_reorder --> [*]
    }
```

### ApprovalRequest Status Lifecycle

```mermaid theme={null}
stateDiagram-v2
    [*] --> pending: Dokumen diajukan
    pending --> pending: Level approval berikutnya
    pending --> approved: Semua level menyetujui
    pending --> rejected: Salah satu level menolak
    pending --> on_hold: Ditunda untuk review ulang
    on_hold --> pending: Dilanjutkan kembali
    on_hold --> rejected: Ditolak setelah review
    approved --> [*]
    rejected --> [*]
```

## Sequence Diagrams — Alur Data Utama

### 1. Pemuatan Halaman Home

```mermaid theme={null}
sequenceDiagram
    participant U as Pengguna
    participant HP as Home Page
    participant API as API Layer
    participant WS as Workspace
    participant TK as Task Store
    participant NT as Notification Store
    participant SA as StockAlert Store
    participant AR as ApprovalRequest Store

    U->>HP: Navigasi ke halaman Home
    HP->>API: Request data Home (user context)
    
    par Parallel Data Fetching
        API->>WS: GET /workspace?user_id={id}
        WS-->>API: Workspace & member data
    and
        API->>TK: GET /task?assignee_id={id}&status=todo,in_progress
        TK-->>API: Daftar tugas aktif
    and
        API->>NT: GET /notification?user_id={id}&is_read=false
        NT-->>API: Notifikasi belum dibaca
    and
        API->>SA: GET /stock-alert?company_id={id}&status=active
        SA-->>API: Alert stok aktif
    and
        API->>AR: GET /approval-request?company_id={id}&overall_status=pending
        AR-->>API: Approval menunggu
    end

    API-->>HP: Agregasi data Home
    HP->>HP: Render komponen (feed, tugas, ringkasan, kalender)
    HP-->>U: Tampilkan halaman Home lengkap
```

### 2. Widget Refresh pada CustomDashboardConfig

```mermaid theme={null}
sequenceDiagram
    participant U as Pengguna
    participant DC as Dashboard Config
    participant WD as Widget Component
    participant DS as Data Source
    participant Cache as Cache Layer

    U->>DC: Buka custom dashboard
    DC->>DC: Load konfigurasi widget dari DB
    
    loop Setiap widget dengan refresh_interval
        DC->>WD: Inisialisasi widget (widget_type, data_source)
        WD->>Cache: Cek cache data (key: widget_id)
        
        alt Cache valid
            Cache-->>WD: Return cached data
        else Cache expired
            WD->>DS: Fetch data baru (entity: data_source, filters)
            DS-->>WD: Return data terbaru
            WD->>Cache: Update cache dengan TTL = refresh_interval
        end
        
        WD->>WD: Render visualisasi (chart_type: line/bar/pie/area)
        WD-->>DC: Widget updated
    end
    
    DC-->>U: Dashboard tampil dengan data terbaru
```

### 3. Pengiriman Notifikasi

```mermaid theme={null}
sequenceDiagram
    participant Src as Event Source
    participant Router as Notification Router
    participant Dedup as Deduplication (event_id)
    participant Store as Notification Store
    participant Push as Push Service
    participant U as Pengguna

    Src->>Router: Event terjadi (transaksi, stok, approval)
    Router->>Router: Tentukan type, priority, & recipient
    Router->>Dedup: Cek event_id = {type}:{entity}:{id}
    
    alt event_id sudah ada
        Dedup-->>Router: Duplikat — skip
    else event_id baru
        Dedup-->>Router: Valid — lanjutkan
        Router->>Store: INSERT Notification (user_id, title, message, type, metadata)
        Store-->>Push: Trigger push notification
        
        alt priority = high
            Push->>U: Push notification real-time
        else priority = normal atau low
            Push->>U: Badge update di Home
        end
        
        U->>Store: GET /notification (polling / WebSocket)
        Store-->>U: Daftar notifikasi terbaru
        U->>Store: PATCH /notification/{id} (is_read = true)
    end
```

### 4. Penanganan StockAlert dari Deteksi hingga Resolusi

```mermaid theme={null}
sequenceDiagram
    participant Scanner as Stock Anomaly Detector
    participant SA as StockAlert Store
    participant NT as Notification Service
    participant U as Pengguna (Inventory)
    participant INV as Inventory Module

    Scanner->>Scanner: Scan stok periodik
    Scanner->>SA: Deteksi anomali (low_stock, negative_stock, dll)
    SA->>SA: Generate fingerprint untuk deduplikasi
    
    alt fingerprint baru
        SA->>SA: CREATE StockAlert (status=active, severity berdasarkan level)
        SA->>NT: Trigger notifikasi (type=LOW_STOCK atau DISCREPANCY)
        NT-->>U: Kirim notifikasi ke pengguna terkait
    else fingerprint sudah ada
        SA->>SA: Skip — alert sudah ada
    end

    U->>SA: Lihat daftar alert aktif di Home
    U->>SA: PATCH /stock-alert/{id} (status=acknowledged, acknowledged_by=user_id)
    U->>INV: Tindaklanjuti (restock, koreksi stok, transfer)
    INV-->>SA: Konfirmasi tindakan selesai
    U->>SA: PATCH /stock-alert/{id} (status=resolved, resolved_at=now)
    SA->>SA: Update status → resolved
```

## Referensi Enum

### Notification Type

| Nilai | Deskripsi |
| - | - |
| `SYSTEM` | Notifikasi sistem umum dari platform |
| `INVITATION` | Undangan bergabung ke workspace atau perusahaan |
| `TASK` | Notifikasi terkait tugas baru atau pembaruan tugas |
| `STOCK` | Notifikasi perubahan stok umum |
| `INVOICE` | Notifikasi terkait invoice (baru, jatuh tempo, dibayar) |
| `WORKFLOW` | Notifikasi alur kerja atau approval |
| `ANNOUNCEMENT` | Pengumuman dari admin atau sistem |
| `ORDER` | Notifikasi order baru atau pembaruan status order |
| `PAYMENT` | Notifikasi terkait pembayaran diterima atau gagal |
| `LOW_STOCK` | Peringatan stok produk menipis di bawah threshold |
| `DISCREPANCY` | Peringatan ketidaksesuaian stok (anomali) |
| `EXPIRY` | Peringatan produk mendekati tanggal kedaluwarsa |
| `BACKUP` | Notifikasi status backup data perusahaan |
| `BTT_PENDING` | Peringatan transaksi BTT (Buyer Take Take) yang menggantung |
| `PAYMENT_DUE` | Peringatan tagihan atau pembayaran yang jatuh tempo |
| `RECALL` | Notifikasi penarikan produk (recall) |

### Notification Priority

| Nilai | Deskripsi |
| - | - |
| `low` | Prioritas rendah, tidak mendesak — ditampilkan tanpa badge khusus |
| `normal` | Prioritas standar — ditampilkan sebagai notifikasi biasa |
| `high` | Prioritas tinggi — ditampilkan dengan badge merah dan push notification |

### Task Status

| Nilai | Deskripsi |
| - | - |
| `todo` | Tugas baru yang belum dimulai pengerjaannya |
| `in_progress` | Tugas sedang dalam proses pengerjaan |
| `completed` | Tugas telah selesai dikerjakan, menunggu verifikasi |
| `done` | Tugas telah diverifikasi dan sepenuhnya selesai |

### Task Priority

| Nilai | Deskripsi |
| - | - |
| `low` | Prioritas rendah — dapat dikerjakan setelah tugas lain selesai |
| `medium` | Prioritas sedang — prioritas default untuk tugas baru |
| `high` | Prioritas tinggi — perlu diselesaikan dalam 1-2 hari |
| `urgent` | Prioritas mendesak — harus diselesaikan hari ini atau sudah overdue |

### StockAlert — Alert Type

| Nilai | Deskripsi |
| - | - |
| `low_stock` | Stok produk berada di bawah threshold minimum |
| `out_of_stock` | Stok produk habis (jumlah = 0) |
| `overstock` | Stok produk melebihi kapasitas atau batas maksimum |
| `expiring_soon` | Produk mendekati tanggal kedaluwarsa |
| `reconciliation_needed` | Diperlukan rekonsiliasi stok antara sistem dan fisik |
| `negative_stock` | Stok menunjukkan nilai negatif (anomali) |
| `rapid_depletion` | Stok berkurang secara tidak wajar dalam periode singkat |
| `orphaned_movement` | Pergerakan stok tanpa referensi dokumen yang valid |
| `duplicate_movement` | Pergerakan stok terdeteksi duplikat |
| `futuristic_date` | Tanggal pergerakan stok berada di masa depan (anomali) |
| `lot_negative` | Nomor lot menunjukkan kuantitas negatif |

### StockAlert — Severity

| Nilai | Deskripsi |
| - | - |
| `low` | Keparahan rendah — informasi, tidak perlu tindakan segera |
| `medium` | Keparahan sedang — perlu perhatian dalam waktu dekat |
| `high` | Keparahan tinggi — perlu tindakan segera |
| `critical` | Keparahan kritis — harus ditangani sekarang, bisa mengganggu operasional |

### StockAlert — Status

| Nilai | Deskripsi |
| - | - |
| `active` | Alert baru terdeteksi dan belum ditindaklanjuti |
| `acknowledged` | Alert sudah diakui oleh pengguna namun belum diselesaikan |
| `dismissed` | Alert diabaikan karena dianggap tidak relevan |
| `resolved` | Alert telah diselesaikan dan masalah ditangani |

### ApprovalRequest — Overall Status

| Nilai | Deskripsi |
| - | - |
| `pending` | Approval sedang menunggu keputusan dari approver |
| `approved` | Semua level approval telah menyetujui dokumen |
| `rejected` | Salah satu level approval menolak dokumen |
| `on_hold` | Approval ditunda sementara untuk review tambahan |

### ApprovalRequest — Approval History Status

| Nilai | Deskripsi |
| - | - |
| `approved` | Approver menyetujui dokumen pada level ini |
| `rejected` | Approver menolak dokumen pada level ini |
| `pending` | Approver belum memberikan keputusan pada level ini |

### RecurringTask — Frequency

| Nilai | Deskripsi |
| - | - |
| `daily` | Tugas diulang setiap hari (dengan interval) |
| `weekly` | Tugas diulang setiap minggu pada hari tertentu |
| `monthly` | Tugas diulang setiap bulan pada tanggal tertentu |
| `yearly` | Tugas diulang setiap tahun pada tanggal tertentu |

### AuditLog — Action

| Nilai | Deskripsi |
| - | - |
| `create` | Pengguna membuat record baru |
| `read` | Pengguna mengakses atau melihat record |
| `update` | Pengguna memperbarui data pada record |
| `delete` | Pengguna menghapus record |
| `approve` | Pengguna menyetujui dokumen atau request |
| `reject` | Pengguna menolak dokumen atau request |
| `lock` | Pengguna mengunci record agar tidak dapat diubah |
| `unlock` | Pengguna membuka kunci record |
| `unlock_request` | Pengguna mengajukan permintaan untuk membuka kunci record |

### AuditLog — Status

| Nilai | Deskripsi |
| - | - |
| `success` | Aksi berhasil dieksekusi tanpa error |
| `failed` | Aksi gagal dieksekusi (misalnya karena validasi atau permission) |

### CustomDashboardConfig — Widget Type

| Nilai | Deskripsi |
| - | - |
| `chart` | Widget visualisasi grafik (line, bar, pie, area) |
| `table` | Widget tampilan data dalam format tabel |
| `metric` | Widget angka metrik tunggal (KPI card) |
| `list` | Widget daftar item (feed aktivitas, tugas, dll) |
| `calendar` | Widget tampilan kalender dengan event |
| `forecast` | Widget prediksi atau proyeksi data |

### CustomDashboardConfig — Chart Type

| Nilai | Deskripsi |
| - | - |
| `line` | Grafik garis — cocok untuk tren data dari waktu ke waktu |
| `bar` | Grafik batang — cocok untuk perbandingan antar kategori |
| `pie` | Grafik lingkaran — cocok untuk proporsi atau distribusi |
| `area` | Grafik area — cocok untuk volume data kumulatif |

### CustomDashboardConfig — Layout

| Nilai | Deskripsi |
| - | - |
| `grid` | Tata letak grid — widget disusun dalam grid yang dapat dikustomisasi |
| `list` | Tata letak daftar — widget disusun secara vertikal berurutan |

### WorkspaceMember — Role

| Nilai | Deskripsi |
| - | - |
| `owner` | Pemilik workspace dengan akses penuh, bisa ada multiple owners |
| `admin` | Administrator workspace dengan hak kelola anggota dan pengaturan |
| `member` | Anggota biasa yang dapat membuat dan mengedit tugas sendiri |
| `viewer` | Hanya dapat melihat tugas, tidak dapat membuat atau mengubah |

### Comment — Entity Type

| Nilai | Deskripsi |
| - | - |
| `task` | Komentar ditujukan untuk entitas Task |
| `note` | Komentar ditujukan untuk entitas Note |

***

**Related Documentation**:

* [Dashboard](/docs/core/dashboard)
* [Workspace](/docs/core/workspace)
* [Settings](/docs/core/settings)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.