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

# Goals

<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: "Goals — OKR & Target Bisnis"
description: "Manajemen goal dengan metodologi OKR, 6 kategori, 3 prioritas, key results terukur, localStorage persistence, dan progress tracking di SNISHOP ERP."
------------------------------------------------------------------------------------------------------------------------------------------------------------------

# Goals — OKR & Target Bisnis

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

Halaman Goals mengelola target bisnis menggunakan metodologi **OKR (Objectives and Key Results)**. Dibangun di atas `Goals.jsx` (517 baris) dengan penyimpanan berbasis **localStorage** untuk performa instan dan offline-first experience.

Setiap **Objective** (tujuan kualitatif) dipecah menjadi beberapa **Key Results** (hasil terukur) yang memungkinkan kamu memantau progress secara granular. Sistem ini mendukung 6 kategori bisnis, 3 level prioritas, dan deadline tracking.

## Arsitektur Komponen

```mermaid theme={null}
graph TD
    A[Goals.jsx<br/>517 lines] --> B[Stats Dashboard<br/>4 KPI Cards]
    A --> C[Objective List]
    A --> D[Objective Form<br/>Modal]
    A --> E[Key Results Editor]
    A --> F[Priority Filter]
    A --> G[Category Filter]
    
    B --> B1[Total Objectives]
    B --> B2[On Track]
    B --> B3[At Risk]
    B --> B4[Completed]
    
    C --> H[Objective Card]
    H --> H1[Objective Title]
    H --> H2[Category Badge]
    H --> H3[Priority Indicator]
    H --> H4[Overall Progress Bar]
    H --> H5[Key Results List]
    H --> H6[Deadline Display]
    
    E --> E1[Key Result Item]
    E1 --> E2[Title]
    E1 --> E3[Target Value]
    E1 --> E4[Current Value]
    E1 --> E5[Progress %]
    
    A --> I[localStorage<br/>snishop_goals]
    A --> J[ERPAccessGuard<br/>module=goals]
```

## Gambaran Umum Sistem Goals

Modul Goals dalam SNISHOP ERP merupakan sistem manajemen target yang komprehensif, mencakup beberapa jenis goal yang saling terintegrasi:

| Jenis Goal | Entity | Deskripsi | Skala |
| - | - | - | - |
| **Goal (Umum)** | `Goal` | Goal utama perusahaan/tim/personal dengan milestones | Personal, Tim, Perusahaan |
| **Personal Goal** | `PersonalGoal` | Goal individual dengan metodologi OKR/SMART | Personal |
| **Financial Goal** | `FinancialGoal` | Target keuangan (tabungan, investasi, pengurangan hutang) | Personal, Perusahaan |
| **KPI** | `KPI` | Key Performance Indicator per karyawan per periode | Karyawan |
| **KPI Template** | `KPITemplate` | Template KPI yang dapat digunakan ulang | Departemen/Role |
| **Achievement** | `Achievement` | Badge/pencapaian yang diraih dari aktivitas produktif | Personal |

Setiap jenis goal memiliki karakteristik dan metriknya masing-masing, namun semuanya terhubung dalam satu ekosistem produktivitas yang terpadu.

## Data Model: Objective

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `id` | UUID | Auto | Identifier unik (auto-generated) |
| `title` | string | Ya | Pernyataan tujuan kualitatif |
| `description` | string | Tidak | Deskripsi detail objective |
| `category` | enum | Ya | Kategori bisnis (6 opsi) |
| `priority` | enum | Ya | Level prioritas (3 level) |
| `status` | enum | Ya | Status objective |
| `start_date` | date | Ya | Tanggal mulai |
| `deadline` | date | Ya | Tanggal target tercapai |
| `key_results` | array | Ya | Daftar key results terukur |
| `overall_progress` | number | Auto | Rata-rata progress semua key results |
| `created_at` | datetime | Auto | Timestamp pembuatan |
| `updated_at` | datetime | Auto | Timestamp update terakhir |

## Data Model: Key Result

Setiap Objective memiliki array `key_results` dengan struktur:

| Field | Tipe | Deskripsi |
| - | - | - |
| `id` | UUID | Identifier unik per key result |
| `title` | string | Deskripsi hasil terukur |
| `target_value` | number | Nilai target yang ingin dicapai |
| `current_value` | number | Nilai saat ini |
| `unit` | string | Satuan pengukuran (%, Rp, unit, dll) |
| `progress` | number | `(current_value / target_value) x 100` |

## Entity Schema: Goal

Entity `Goal` merupakan model utama untuk goal berskala personal, tim, maupun perusahaan. Mendukung milestones, recurring patterns, dan notifikasi.

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `company_id` | string | Tidak | ID perusahaan (null untuk personal goal) |
| `goal_type` | enum | Tidak | Jenis goal: `personal`, `team`, `company` (default: `personal`) |
| `title` | string | Ya | Judul goal |
| `description` | string | Tidak | Deskripsi detail goal |
| `category` | enum | Tidak | Kategori: `revenue`, `productivity`, `quality`, `growth`, `efficiency`, `custom` (default: `custom`) |
| `target_type` | enum | Tidak | Tipe target: `number`, `percentage`, `boolean` (default: `number`) |
| `target_value` | number | Ya | Nilai target yang ingin dicapai |
| `current_value` | number | Tidak | Progress saat ini (default: 0) |
| `unit` | string | Tidak | Satuan pengukuran (Rp, unit, %, jam, dll) |
| `start_date` | date | Ya | Tanggal mulai goal |
| `end_date` | date | Ya | Tanggal akhir goal |
| `status` | enum | Tidak | Status: `not_started`, `in_progress`, `completed`, `failed`, `cancelled` (default: `not_started`) |
| `progress_percentage` | number | Tidak | Progress dalam persen 0-100 (default: 0) |
| `owner_id` | string | Tidak | Email pemilik goal |
| `assigned_to` | array\[string] | Tidak | Array email yang di-assign ke goal ini |
| `milestones` | array\[object] | Tidak | Daftar milestone pencapaian |
| `is_recurring` | boolean | Tidak | Apakah goal berulang (default: false) |
| `recurrence_pattern` | enum | Tidak | Pola pengulangan: `daily`, `weekly`, `monthly`, `quarterly`, `yearly` |
| `notification_enabled` | boolean | Tidak | Notifikasi aktif (default: true) |
| `notification_frequency` | enum | Tidak | Frekuensi notifikasi: `daily`, `weekly`, `milestone` (default: `weekly`) |

### Sub-Schema: Milestone (Goal)

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `title` | string | Ya | Judul milestone |
| `target_value` | number | Ya | Nilai target milestone |
| `due_date` | date | Tidak | Tanggal jatuh tempo milestone |
| `completed` | boolean | Tidak | Status penyelesaian (default: false) |
| `completed_at` | datetime | Tidak | Timestamp saat milestone selesai |

## Entity Schema: PersonalGoal

Entity `PersonalGoal` dirancang untuk goal individual dengan dukungan metodologi OKR dan SMART goal.

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna pemilik tujuan |
| `title` | string | Ya | Judul tujuan personal |
| `description` | string | Tidak | Deskripsi detail tujuan |
| `goal_type` | enum | Tidak | Metodologi: `okr`, `smart_goal`, `general` (default: `smart_goal`) |
| `category` | enum | Tidak | Kategori: `career`, `health`, `learning`, `personal`, `financial`, `relationship` |
| `target_metric` | string | Ya | Metrik target (misalnya: "menyelesaikan buku", "menambah skill coding") |
| `current_metric` | string | Tidak | Metrik saat ini |
| `target_value` | number | Tidak | Nilai target numerik (opsional) |
| `current_value` | number | Tidak | Nilai saat ini (default: 0) |
| `deadline` | date | Ya | Tanggal target pencapaian |
| `priority` | enum | Tidak | Prioritas: `low`, `medium`, `high` (default: `medium`) |
| `status` | enum | Tidak | Status: `active`, `paused`, `completed`, `abandoned` (default: `active`) |
| `progress_percentage` | number | Tidak | Progress dalam persen (default: 0) |
| `milestones` | array\[object] | Tidak | Daftar milestone pencapaian |
| `related_tasks` | array\[string] | Tidak | Task IDs yang terkait dengan goal ini |
| `notes` | string | Tidak | Catatan tambahan |

### Sub-Schema: Milestone (PersonalGoal)

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `milestone_title` | string | Ya | Judul milestone |
| `target_date` | date | Tidak | Tanggal target penyelesaian |
| `completed` | boolean | Tidak | Status penyelesaian (default: false) |
| `completed_date` | date | Tidak | Tanggal saat milestone selesai |

## Entity Schema: FinancialGoal

Entity `FinancialGoal` mengelola target keuangan seperti tabungan, pelunasan hutang, investasi, dan pengurangan pengeluaran.

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna pemilik tujuan |
| `company_id` | string | Tidak | ID perusahaan (null untuk personal) |
| `title` | string | Ya | Judul tujuan keuangan |
| `description` | string | Tidak | Deskripsi detail tujuan |
| `goal_type` | enum | Ya | Jenis: `savings`, `debt_payoff`, `investment`, `expense_reduction` |
| `target_amount` | number | Ya | Jumlah target yang ingin dicapai |
| `current_amount` | number | Tidak | Jumlah yang sudah terkumpul/terbayar (default: 0) |
| `deadline` | date | Ya | Tanggal target pencapaian |
| `status` | enum | Tidak | Status: `active`, `paused`, `completed`, `failed` (default: `active`) |
| `priority` | enum | Tidak | Prioritas: `low`, `medium`, `high` (default: `medium`) |
| `related_budget_id` | string | Tidak | ID Budget terkait (jika ada) |

## Entity Schema: KPI

Entity `KPI` mencatat Key Performance Indicator per karyawan untuk periode tertentu, dengan metrik berbobot dan sistem rating.

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `employee_id` | string | Ya | ID karyawan yang dinilai |
| `period` | string | Ya | Periode penilaian (contoh: "2024-Q1", "2024-01") |
| `description` | string | Tidak | Penjelasan konteks penilaian KPI dan target pencapaian (maks 1000 karakter) |
| `metrics` | array\[object] | Ya | Daftar metrik KPI dengan bobot |
| `overall_score` | number | Tidak | Skor rata-rata tertimbang (0-100) |
| `rating` | enum | Tidak | Rating: `outstanding`, `exceeds`, `meets`, `needs_improvement`, `unsatisfactory` |
| `reviewer_id` | string | Tidak | ID reviewer/penilai |
| `reviewer_notes` | string | Tidak | Catatan dari reviewer |
| `employee_notes` | string | Tidak | Catatan dari karyawan |
| `status` | enum | Tidak | Status: `draft`, `submitted`, `reviewed`, `finalized` (default: `draft`) |

### Sub-Schema: KPI Metric

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `name` | string | Ya | Nama metrik |
| `description` | string | Tidak | Deskripsi metrik |
| `target` | number | Ya | Nilai target |
| `actual` | number | Tidak | Nilai aktual |
| `unit` | string | Tidak | Satuan pengukuran |
| `weight` | number | Tidak | Bobot persentase (0-100) |

## Entity Schema: KPITemplate

Entity `KPITemplate` menyediakan template KPI yang dapat digunakan ulang untuk berbagai role dan departemen.

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `company_id` | string | Ya | ID perusahaan |
| `template_name` | string | Ya | Nama template KPI |
| `description` | string | Tidak | Penjelasan template KPI (maks 1000 karakter) |
| `applicable_roles` | array\[string] | Tidak | Role yang menggunakan template (Sales, Engineer, Manager, dll) |
| `applicable_departments` | array\[string] | Tidak | Departemen yang menggunakan template |
| `default_metrics` | array\[object] | Ya | Daftar metrik default template |
| `is_active` | boolean | Tidak | Status aktif template (default: true) |
| `auto_calculate` | boolean | Tidak | Otomatis hitung KPI setiap hari (default: true) |
| `calculation_frequency` | enum | Tidak | Frekuensi hitung: `daily`, `weekly`, `monthly` (default: `daily`) |

### Sub-Schema: Default Metric (KPITemplate)

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `metric_name` | string | Ya | Nama metrik |
| `description` | string | Tidak | Deskripsi metrik |
| `default_target` | number | Tidak | Target default |
| `unit` | string | Tidak | Satuan pengukuran |
| `weight` | number | Tidak | Bobot persentase default (0-100) |
| `calculation_method` | enum | Tidak | Metode hitung: `manual`, `auto_from_attendance`, `auto_from_sales`, `auto_from_projects` (default: `manual`) |
| `auto_source` | object | Tidak | Konfigurasi sumber data otomatis |

### Sub-Schema: Auto Source

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `entity` | string | Ya | Entity sumber data |
| `field` | string | Ya | Field yang di-aggregate |
| `aggregation` | enum | Tidak | Metode agregasi: `sum`, `count`, `average`, `percentage` |

## Entity Schema: Achievement

Entity `Achievement` mencatat badge dan pencapaian yang diraih pengguna dari aktivitas produktif mereka.

| Field | Tipe | Wajib | Deskripsi |
| - | - | - | - |
| `user_id` | string | Ya | ID pengguna yang meraih pencapaian |
| `achievement_type` | enum | Ya | Jenis pencapaian (lihat tabel enum di bawah) |
| `title` | string | Ya | Judul pencapaian |
| `description` | string | Tidak | Deskripsi pencapaian |
| `icon` | string | Tidak | Emoji atau icon pencapaian |
| `earned_at` | datetime | Tidak | Timestamp saat pencapaian diraih |
| `points` | number | Tidak | Poin yang diperoleh (default: 0) |

## Entity Relationship Diagram

```mermaid theme={null}
erDiagram
    Goal ||--o{ Milestone : "memiliki"
    Goal }o--|| User : "dimiliki oleh (owner_id)"
    Goal }o--o| Company : "berafiliasi dengan"
    Goal }o--o{ Task : "didelegasikan ke"

    PersonalGoal ||--o{ PersonalMilestone : "memiliki"
    PersonalGoal }o--|| User : "dimiliki oleh"
    PersonalGoal }o--o{ Task : "terkait melalui related_tasks"

    FinancialGoal }o--|| User : "dimiliki oleh"
    FinancialGoal }o--o| Company : "berafiliasi dengan"
    FinancialGoal }o--o| Budget : "terkait melalui related_budget_id"

    KPI }o--|| Employee : "dinilai untuk"
    KPI }o--|| Company : "berafiliasi dengan"
    KPI }o--|| Reviewer : "direview oleh"
    KPI ||--o{ KPIMetric : "memiliki"

    KPITemplate ||--o{ DefaultMetric : "memiliki"
    KPITemplate }o--|| Company : "berafiliasi dengan"

    Achievement }o--|| User : "diraih oleh"

    Goal {
        string company_id
        string goal_type "personal|team|company"
        string title
        string category "revenue|productivity|quality|growth|efficiency|custom"
        string target_type "number|percentage|boolean"
        number target_value
        number current_value
        string unit
        date start_date
        date end_date
        string status "not_started|in_progress|completed|failed|cancelled"
        number progress_percentage
        string owner_id
        array assigned_to
        boolean is_recurring
        string recurrence_pattern
    }

    PersonalGoal {
        string user_id
        string title
        string goal_type "okr|smart_goal|general"
        string category "career|health|learning|personal|financial|relationship"
        string target_metric
        number target_value
        number current_value
        date deadline
        string priority "low|medium|high"
        string status "active|paused|completed|abandoned"
        number progress_percentage
    }

    FinancialGoal {
        string user_id
        string company_id
        string title
        string goal_type "savings|debt_payoff|investment|expense_reduction"
        number target_amount
        number current_amount
        date deadline
        string status "active|paused|completed|failed"
        string priority "low|medium|high"
        string related_budget_id
    }

    KPI {
        string company_id
        string employee_id
        string period
        string description
        number overall_score
        string rating "outstanding|exceeds|meets|needs_improvement|unsatisfactory"
        string reviewer_id
        string status "draft|submitted|reviewed|finalized"
    }

    KPITemplate {
        string company_id
        string template_name
        string description
        array applicable_roles
        array applicable_departments
        boolean is_active
        boolean auto_calculate
        string calculation_frequency
    }

    Achievement {
        string user_id
        string achievement_type
        string title
        string description
        string icon
        datetime earned_at
        number points
    }
```

## Metodologi OKR

```mermaid theme={null}
flowchart TD
    subgraph "Objective (Kualitatif)"
        O["Meningkatkan Penjualan Online"]
    end
    
    subgraph "Key Results (Terukur)"
        KR1["Revenue online naik 50%<br/>Current: 250Jt - Target: 375Jt"]
        KR2["Jumlah order/hari naik 2x<br/>Current: 50 - Target: 100"]
        KR3["Customer repeat order > 40%<br/>Current: 25% - Target: 40%"]
    end
    
    O --> KR1 & KR2 & KR3
    
    subgraph "Progress Calculation"
        P1[KR1: 66.7%]
        P2[KR2: 50%]
        P3[KR3: 62.5%]
        P1 & P2 & P3 --> AVG["Overall: 59.7%"]
    end
```

### Prinsip OKR

| Prinsip | Deskripsi |
| - | - |
| **Objective = Kualitatif** | Pernyataan inspirasional, tidak berisi angka |
| **Key Results = Kuantitatif** | Setiap KR harus terukur dengan angka |
| **3-5 Key Results per Objective** | Terlalu sedikit = tidak terukur, terlalu banyak = tidak fokus |
| **60-70% = Ideal** | Jika semua 100%, target terlalu mudah. Jika \< 40%, target terlalu ambisius |

### Perbandingan Jenis Goal

| Aspek | Goal | PersonalGoal | FinancialGoal | KPI |
| - | - | - | - | - |
| **Skala** | Personal/Tim/Perusahaan | Personal | Personal/Perusahaan | Karyawan |
| **Metodologi** | Custom | OKR/SMART | Keuangan | Weighted Metrics |
| **Milestone** | Ya (dengan target\_value & due\_date) | Ya (dengan target\_date) | Tidak | Tidak |
| **Recurring** | Ya (daily/yearly) | Tidak | Tidak | Per periode |
| **Notifikasi** | Ya (daily/weekly/milestone) | Tidak | Tidak | Tidak |
| **Relasi ke Task** | Tidak langsung | Ya (related\_tasks) | Tidak | Tidak |
| **Relasi ke Budget** | Tidak | Tidak | Ya (related\_budget\_id) | Tidak |
| **Progress Tracking** | progress\_percentage | progress\_percentage | current\_amount vs target\_amount | overall\_score + rating |

## 6 Kategori Bisnis (Goal)

| Kategori | Ikon | Kegunaan | Contoh Objective |
| - | - | - | - |
| `revenue` | 💰 | Target pendapatan | "Mencapai revenue Rp 1M di 2026" |
| `customers` | 👥 | Target pelanggan | "Membangun basis customer yang loyal" |
| `product` | 📦 | Target produk | "Meluncurkan 5 produk baru" |
| `marketing` | 📣 | Target marketing | "Meningkatkan brand awareness" |
| `operations` | ⚙️ | Target operasional | "Mengoptimasi proses produksi" |
| `team` | 👤 | Target tim | "Membangun tim yang solid" |

### Kategori PersonalGoal

| Kategori | Deskripsi | Contoh Goal |
| - | - | - |
| `career` | Pengembangan karir | "Mendapat promosi ke Senior Developer dalam 6 bulan" |
| `health` | Kesehatan & kebugaran | "Menurunkan berat badan 10 kg dalam 3 bulan" |
| `learning` | Pembelajaran & skill | "Menyelesaikan kursus Machine Learning" |
| `personal` | Tujuan personal | "Membaca 12 buku dalam setahun" |
| `financial` | Keuangan personal | "Menabung Rp 50 juta untuk dana darurat" |
| `relationship` | Hubungan & networking | "Membangun jaringan profesional di 3 industri" |

### Kategori FinancialGoal

| Kategori | Deskripsi | Contoh Goal |
| - | - | - |
| `savings` | Tabungan | "Mengumpulkan dana darurat Rp 100 juta" |
| `debt_payoff` | Pelunasan hutang | "Melunasi KPR dalam 5 tahun" |
| `investment` | Investasi | "Portfolio investasi mencapai Rp 500 juta" |
| `expense_reduction` | Pengurangan pengeluaran | "Mengurangi pengeluaran operasional 20%" |

## 3 Level Prioritas

| Prioritas | Warna | Deskripsi | Kapan Gunakan |
| - | - | - | - |
| `high` | 🔴 Merah | Target kritis, harus dicapai | Deadline dekat, target utama perusahaan |
| `medium` | 🟡 Kuning | Target penting, perlu perhatian | Target reguler, improvement berkelanjutan |
| `low` | 🟢 Hijau | Target pendukung, nice to have | Eksperimen, long-term goals |

## Enum Reference: Status Fields

### Goal Status

| Nilai | Deskripsi | Kondisi Masuk | Kondisi Keluar |
| - | - | - | - |
| `not_started` | Goal belum dimulai | Baru dibuat | Mulai dikerjakan |
| `in_progress` | Goal sedang dikerjakan | Owner memulai | Selesai/gagal/dibatalkan |
| `completed` | Goal berhasil dicapai | Target tercapai | - (terminal state) |
| `failed` | Goal gagal dicapai | Deadline lewat tanpa target tercapai | - (terminal state) |
| `cancelled` | Goal dibatalkan | Owner membatalkan | - (terminal state) |

### PersonalGoal Status

| Nilai | Deskripsi | Kondisi Masuk | Kondisi Keluar |
| - | - | - | - |
| `active` | Goal sedang aktif dikerjakan | Baru dibuat / di-resume | Selesai/dibatalkan/di-pause |
| `paused` | Goal dihentikan sementara | Owner menunda | Di-resume ke active |
| `completed` | Goal berhasil dicapai | Target tercapai | - (terminal state) |
| `abandoned` | Goal ditinggalkan | Owner meninggalkan | - (terminal state) |

### FinancialGoal Status

| Nilai | Deskripsi | Kondisi Masuk | Kondisi Keluar |
| - | - | - | - |
| `active` | Tujuan keuangan aktif | Baru dibuat / di-resume | Selesai/gagal/di-pause |
| `paused` | Ditunda sementara | Owner menunda | Di-resume ke active |
| `completed` | Target tercapai | current\_amount >= target\_amount | - (terminal state) |
| `failed` | Target gagal dicapai | Deadline lewat tanpa target tercapai | - (terminal state) |

### KPI Status

| Nilai | Deskripsi | Kondisi Masuk | Kondisi Keluar |
| - | - | - | - |
| `draft` | KPI masih dalam penyusunan | Baru dibuat | Submit untuk review |
| `submitted` | KPI sudah diajukan | Karyawan submit | Reviewer mulai mereview |
| `reviewed` | KPI sudah direview | Reviewer selesai menilai | Finalisasi |
| `finalized` | KPI disahkan | Reviewer menyetujui | - (terminal state) |

### KPI Rating

| Rating | Skor | Deskripsi |
| - | - | - |
| `outstanding` | 90-100 | Kinerja luar biasa, melampaui semua ekspektasi |
| `exceeds` | 75-89 | Kinerja melebihi target yang ditetapkan |
| `meets` | 60-74 | Kinerja sesuai target yang ditetapkan |
| `needs_improvement` | 40-59 | Kinerja di bawah target, perlu perbaikan |
| `unsatisfactory` | 0-39 | Kinerja sangat di bawah ekspektasi |

### Achievement Types

| Tipe | Deskripsi | Contoh Pemicu |
| - | - | - |
| `task_streak` | Menyelesaikan task berturut-turut | 7 hari berturut-turut menyelesaikan task |
| `first_task` | Menyelesaikan task pertama | Menyelesaikan task pertama kali |
| `task_master` | Menyelesaikan banyak task | Menyelesaikan 100 task |
| `note_taker` | Aktif mencatat | Membuat 50 catatan |
| `financial_tracker` | Aktif melacak keuangan | Mencatat 30 transaksi |
| `collaborator` | Aktif berkolaborasi | Berbagi workspace ke 5 tim |
| `early_bird` | Produktif di pagi hari | Menyelesaikan task sebelum jam 8 |
| `night_owl` | Produktif di malam hari | Menyelesaikan task setelah jam 10 malam |
| `team_player` | Aktif dalam tim | Bergabung di 3 workspace tim |
| `productivity_champion` | Produktivitas tinggi | Konsisten menyelesaikan semua task weekly |

### Recurrence Pattern (Goal)

| Pola | Deskripsi | Contoh Penggunaan |
| - | - | - |
| `daily` | Berulang setiap hari | "Check email inbox zero" |
| `weekly` | Berulang setiap minggu | "Submit weekly report" |
| `monthly` | Berulang setiap bulan | "Capai target penjualan bulanan" |
| `quarterly` | Berulang setiap kuartal | "Review OKR quarterly" |
| `yearly` | Berulang setiap tahun | "Revenue target tahunan" |

### Notification Frequency (Goal)

| Frekuensi | Deskripsi | Kapan Gunakan |
| - | - | - |
| `daily` | Notifikasi setiap hari | Goal kritis dengan deadline dekat |
| `weekly` | Notifikasi setiap minggu (default) | Goal reguler dengan timeline normal |
| `milestone` | Notifikasi saat milestone tercapai | Goal dengan milestone penting |

### KPI Calculation Method

| Metode | Deskripsi | Sumber Data |
| - | - | - |
| `manual` | Input manual oleh karyawan/reviewer | Input langsung |
| `auto_from_attendance` | Otomatis dari data absensi | Entity Attendance |
| `auto_from_sales` | Otomatis dari data penjualan | Entity Sales/Order |
| `auto_from_projects` | Otomatis dari data proyek | Entity Project |

### Aggregation Methods (KPITemplate Auto Source)

| Agregasi | Deskripsi | Contoh Penggunaan |
| - | - | - |
| `sum` | Menjumlahkan seluruh nilai | Total revenue, total unit terjual |
| `count` | Menghitung jumlah entri | Jumlah order, jumlah task selesai |
| `average` | Rata-rata nilai | Rata-rata rating pelanggan |
| `percentage` | Persentase terhadap target | Persentase pencapaian target |

## Goal Lifecycle State Diagram

```mermaid theme={null}
stateDiagram-v2
    [*] --> not_started: Goal dibuat

    state "Goal (Umum)" as GoalLifecycle {
        not_started --> in_progress: Owner memulai\natau current_value > 0
        not_started --> cancelled: Owner membatalkan\nsebelum dimulai
        
        in_progress --> completed: progress_percentage >= 100\natau semua milestones selesai
        in_progress --> failed: end_date terlewati\ndan target tidak tercapai
        in_progress --> cancelled: Owner membatalkan
        
        completed --> [*]
        failed --> [*]
        cancelled --> [*]
    }

    state "PersonalGoal" as PersonalGoalLifecycle {
        active --> paused: Owner menunda
        active --> completed: target tercapai
        active --> abandoned: Owner meninggalkan
        
        paused --> active: Owner melanjutkan
        paused --> abandoned: Owner meninggalkan
        
        completed --> [*]
        abandoned --> [*]
    }

    state "FinancialGoal" as FinancialGoalLifecycle {
        active_fg --> paused_fg: Owner menunda
        active_fg --> completed_fg: current_amount >= target_amount
        active_fg --> failed_fg: deadline terlewati
        
        paused_fg --> active_fg: Owner melanjutkan
        paused_fg --> failed_fg: deadline terlewati
        
        completed_fg --> [*]
        failed_fg --> [*]
    }

    state "KPI" as KPILifecycle {
        draft --> submitted: Karyawan mengajukan
        submitted --> reviewed: Reviewer selesai menilai
        reviewed --> finalized: Reviewer mengesahkan
        
        finalized --> [*]
    }
```

### Status Objective (OKR View)

```mermaid theme={null}
stateDiagram-v2
    [*] --> OnTrack: Objective dibuat<br/>progress >= 60%
    [*] --> AtRisk: Objective dibuat<br/>progress < 60%
    OnTrack --> AtRisk: Progress turun < 60%
    AtRisk --> OnTrack: Progress naik >= 60%
    OnTrack --> Completed: Semua KR tercapai
    AtRisk --> Completed: Semua KR tercapai
    OnTrack --> Paused: Owner pause
    AtRisk --> Paused: Owner pause
    Paused --> OnTrack: Resume
    Paused --> AtRisk: Resume
    Completed --> [*]
```

| Status | Warna | Kondisi |
| - | - | - |
| `on_track` | Hijau | Progress >= 60% dan on schedule |
| `at_risk` | Kuning | Progress \< 60% atau mendekati deadline |
| `completed` | Biru | Semua key results tercapai |
| `paused` | Abu-abu | Dihentikan sementara |

## Perhitungan Progress

```mermaid theme={null}
flowchart TD
    A[For each Key Result] --> B["kr_progress = current_value / target_value x 100"]
    B --> C[Collect all KR progress values]
    C --> D["overall_progress = SUM kr_progress / key_results.length"]
    D --> E{overall_progress >= 60?}
    E -->|Ya| F[Status: On Track]
    E -->|Tidak| G{Semua KR completed?}
    G -->|Ya| H[Status: Completed]
    G -->|Tidak| I[Status: At Risk]
```

### Perhitungan KPI Overall Score

```mermaid theme={null}
flowchart TD
    A[For each KPI Metric] --> B["metric_score = actual / target x 100"]
    B --> C["weighted_score = metric_score x weight / 100"]
    C --> D[Collect all weighted scores]
    D --> E["overall_score = SUM weighted_score"]
    E --> F{Determine Rating}
    F --> G["90-100: Outstanding"]
    F --> H["75-89: Exceeds"]
    F --> I["60-74: Meets"]
    F --> J["40-59: Needs Improvement"]
    F --> K["0-39: Unsatisfactory"]
```

### Contoh Perhitungan OKR

**Objective**: "Meningkatkan Penjualan Online"

| Key Result | Target | Current | Progress |
| - | - | - | - |
| Revenue online | Rp 375Jt | Rp 250Jt | 66.7% |
| Order per hari | 100 | 50 | 50.0% |
| Repeat order rate | 40% | 25% | 62.5% |
| **Overall Progress** | | | **59.7%** |

Status: At Risk (overall \< 60%)

### Contoh Perhitungan KPI

**KPI Periode**: "2024-Q1" — Karyawan: Sales Manager

| Metrik | Target | Aktual | Bobot | Skor |
| - | - | - | - | - |
| Revenue | Rp 500Jt | Rp 450Jt | 40% | 36.0 |
| New Customers | 50 | 45 | 30% | 27.0 |
| Customer Satisfaction | 90% | 88% | 20% | 19.6 |
| Report Timeliness | 100% | 95% | 10% | 9.5 |
| **Overall Score** | | | **100%** | **92.1** |

Rating: Outstanding (92.1 >= 90)

## Sequence Diagrams

### Flow: Membuat Goal Baru

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant G as Goals.jsx
    participant V as Validation
    participant LS as localStorage

    U->>G: Klik "Tambah Objective"
    G->>G: Open modal form
    U->>G: Isi title, description, category, priority
    U->>G: Tambahkan Key Results (3-5 items)
    Note over G: Setiap KR: title, target, current, unit
    U->>G: Set start_date dan deadline
    U->>G: Klik Simpan
    G->>V: Validasi required fields
    V-->>G: Validasi berhasil
    G->>G: Hitung overall_progress
    G->>G: Determine initial status
    G->>LS: localStorage.setItem("snishop_goals", data)
    LS-->>G: Confirmed
    G->>G: Refresh objective list
    G-->>U: Tampilkan objective baru
```

### Flow: Tracking Progress

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant G as Goals.jsx
    participant C as Progress Calculator
    participant LS as localStorage

    U->>G: Pilih objective dari daftar
    G->>LS: Load objective data
    LS-->>G: Return objective + key_results
    G-->>U: Tampilkan detail objective
    
    U->>G: Update current_value pada Key Result
    G->>C: Recalculate kr_progress
    C-->>G: kr_progress = (current / target) x 100
    G->>C: Recalculate overall_progress
    C-->>G: overall = average of all kr_progress
    G->>G: Determine new status based on progress
    G->>LS: Save updated objective
    LS-->>G: Confirmed
    G-->>U: Update progress bar & status badge
    
    alt overall_progress >= 60%
        G-->>U: Status: On Track (Hijau)
    else overall_progress < 60%
        G-->>U: Status: At Risk (Kuning)
    end
    
    alt Semua KR completed
        G-->>U: Status: Completed (Biru)
    end
```

### Flow: Goal Completion

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant G as Goals.jsx
    participant A as Achievement System
    participant LS as localStorage

    U->>G: Update KR terakhir ke target
    G->>G: overall_progress = 100%
    G->>G: Set status = "completed"
    G->>LS: Save completed objective
    LS-->>G: Confirmed
    
    G->>A: Check achievement triggers
    A->>A: Evaluate: first goal completed?
    A->>A: Evaluate: goal streak?
    A->>A: Evaluate: productivity champion?
    A-->>G: Award new achievements (if any)
    
    G->>G: Update stats dashboard
    G-->>U: Tampilkan celebrasi completion
    G-->>U: Tampilkan achievement baru (jika ada)
```

### Flow: KPI Review Process

```mermaid theme={null}
sequenceDiagram
    participant E as Employee
    participant K as KPI Module
    participant R as Reviewer/Manager
    participant DB as Database

    Note over E: Periode penilaian tiba
    
    E->>K: Buat KPI draft untuk periode ini
    K->>DB: Save KPI (status: draft)
    
    loop Per setiap metrik
        E->>K: Input metrik (name, target, weight)
        alt calculation_method = manual
            E->>K: Input actual value
        else calculation_method = auto
            K->>K: Fetch data dari auto_source
            K->>K: Calculate actual value
        end
    end
    
    E->>K: Submit KPI
    K->>DB: Update status = "submitted"
    K->>R: Notifikasi: KPI baru untuk direview
    
    R->>K: Review KPI
    K->>DB: Load KPI data
    DB-->>K: Return KPI + metrics
    K->>K: Calculate overall_score (weighted avg)
    K->>K: Determine rating
    
    R->>K: Input reviewer_notes & approve
    K->>DB: Update status = "reviewed"
    K->>E: Notifikasi: KPI sudah direview
    
    R->>K: Finalize KPI
    K->>DB: Update status = "finalized"
    K->>E: Notifikasi: KPI sudah disahkan
```

### Flow: Financial Goal Tracking

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant FG as FinancialGoal Module
    participant B as Budget Module
    participant LS as Storage

    U->>FG: Buat Financial Goal baru
    FG->>FG: Set goal_type (savings/investment/dll)
    FG->>FG: Set target_amount & deadline
    FG->>FG: Set priority
    FG->>LS: Save goal (status: active)
    
    loop Periodik
        U->>FG: Update current_amount
        FG->>FG: Hitung progress = current / target x 100
        
        alt goal_type = savings
            FG->>B: Cek related_budget_id (jika ada)
            B-->>FG: Return budget data
        end
        
        FG->>LS: Save updated goal
        
        alt current_amount >= target_amount
            FG->>FG: Set status = "completed"
            FG-->>U: Notifikasi: Target tercapai!
        else deadline terlewati
            FG->>FG: Set status = "failed"
            FG-->>U: Notifikasi: Deadline terlewati
        end
    end
```

## localStorage Persistence

```mermaid theme={null}
flowchart LR
    subgraph "Client-Side Storage"
        A[Goals.jsx] --> B[useState<br/>goals state]
        B --> C[localStorage.setItem<br/>snishop_goals]
        C --> D[JSON.stringify]
    end
    
    subgraph "Load Sequence"
        E[Component Mount] --> F[localStorage.getItem]
        F --> G[JSON.parse]
        G --> H[setState goals]
    end
```

| Aspek | Detail |
| - | - |
| **Storage Key** | `snishop_goals` |
| **Format** | JSON array of Objective objects |
| **Load** | Saat komponen mount (useEffect) |
| **Save** | Setiap kali ada perubahan (add/edit/delete/update progress) |
| **Keuntungan** | Instant load, offline-first, tidak perlu API call |
| **Keterbatasan** | Data per-browser, tidak sync antar device |

## Stats Dashboard

| Metrik | Perhitungan | Deskripsi |
| - | - | - |
| **Total Objectives** | `objectives.length` | Jumlah seluruh objective |
| **On Track** | `filter(status === 'on_track')` | Objective yang progressnya baik |
| **At Risk** | `filter(status === 'at_risk')` | Objective yang perlu perhatian |
| **Completed** | `filter(status === 'completed')` | Objective yang sudah tercapai |

## Filter & Pencarian

| Filter | Opsi | Deskripsi |
| - | - | - |
| **Kategori** | All, Revenue, Customers, Product, Marketing, Operations, Team | Filter berdasarkan kategori bisnis |
| **Prioritas** | All, High, Medium, Low | Filter berdasarkan level prioritas |
| **Status** | All, On Track, At Risk, Completed, Paused | Filter berdasarkan status |
| **Search** | Text input | Pencarian berdasarkan judul objective |

## RBAC Permission Matrix

Berikut adalah matriks hak akses berdasarkan role untuk modul Goals dan entitas terkait:

| Operasi | Admin | Manager | Employee | Viewer |
| - | - | - | - | - |
| **Goal — Create** | Ya | Ya | Ya (personal only) | Tidak |
| **Goal — Read (own)** | Ya | Ya | Ya | Ya |
| **Goal — Read (all)** | Ya | Ya (company) | Tidak | Tidak |
| **Goal — Update (own)** | Ya | Ya | Ya | Tidak |
| **Goal — Update (any)** | Ya | Ya (company) | Tidak | Tidak |
| **Goal — Delete** | Ya | Ya (company) | Ya (own only) | Tidak |
| **Goal — Assign to others** | Ya | Ya | Tidak | Tidak |
| **PersonalGoal — Create** | Ya | Ya | Ya | Tidak |
| **PersonalGoal — Read** | Ya | Ya | Ya (own) | Ya (own) |
| **PersonalGoal — Update** | Ya | Ya | Ya (own) | Tidak |
| **PersonalGoal — Delete** | Ya | Ya | Ya (own) | Tidak |
| **FinancialGoal — Create** | Ya | Ya | Ya | Tidak |
| **FinancialGoal — Read** | Ya | Ya (company) | Ya (own) | Ya (own) |
| **FinancialGoal — Update** | Ya | Ya | Ya (own) | Tidak |
| **FinancialGoal — Delete** | Ya | Ya | Ya (own) | Tidak |
| **KPI — Create (draft)** | Ya | Ya | Ya (own) | Tidak |
| **KPI — Read (own)** | Ya | Ya | Ya | Ya |
| **KPI — Read (all)** | Ya | Ya | Tidak | Tidak |
| **KPI — Submit** | Ya | Ya | Ya (own) | Tidak |
| **KPI — Review** | Ya | Ya | Tidak | Tidak |
| **KPI — Finalize** | Ya | Ya | Tidak | Tidak |
| **KPITemplate — Create** | Ya | Ya | Tidak | Tidak |
| **KPITemplate — Read** | Ya | Ya | Ya | Ya |
| **KPITemplate — Update** | Ya | Ya | Tidak | Tidak |
| **KPITemplate — Delete** | Ya | Tidak | Tidak | Tidak |
| **Achievement — Read** | Ya | Ya | Ya | Ya |
| **Achievement — Awarded (auto)** | Ya | Ya | Ya | Ya |

### Catatan RBAC

* **ERPAccessGuard** dengan `module=goals` digunakan untuk memproteksi akses ke halaman Goals
* Role-based filtering diterapkan di level query untuk memastikan user hanya melihat data yang diizinkan
* Goal dengan `company_id` hanya dapat dibuat dan dikelola oleh Admin dan Manager
* Goal tanpa `company_id` (personal) dapat dikelola oleh pemiliknya selama memiliki akses ke modul

## Integrasi dengan Entitas Lain

```mermaid theme={null}
flowchart LR
    subgraph "Goals Ecosystem"
        G[Goal]
        PG[PersonalGoal]
        FG[FinancialGoal]
        KPI[KPI]
        KT[KPITemplate]
        A[Achievement]
    end
    
    subgraph "Related Entities"
        T[Task]
        B[Budget]
        P[Project]
        H[Habit]
    end
    
    PG -->|"related_tasks"| T
    FG -->|"related_budget_id"| B
    KT -->|"template untuk"| KPI
    G -->|"milestones"| G
    H -->|"streak & XP"| A
    T -->|"completion triggers"| A
    P -->|"milestones"| P
    
    style G fill:#e1f5fe
    style PG fill:#f3e5f5
    style FG fill:#e8f5e9
    style KPI fill:#fff3e0
    style KT fill:#fff3e0
    style A fill:#fce4ec
```

### Deskripsi Integrasi

| Dari | Ke | Hubungan | Deskripsi |
| - | - | - | - |
| PersonalGoal | Task | `related_tasks` | Task IDs yang mendukung pencapaian goal |
| FinancialGoal | Budget | `related_budget_id` | Budget yang terkait dengan tujuan keuangan |
| KPITemplate | KPI | Template instance | Template menghasilkan KPI instance per periode |
| Goal | Goal | `milestones` | Milestone sebagai sub-target dalam goal |
| Habit | Achievement | XP & streak | Konsistensi habit memicu achievement |
| Task | Achievement | Completion | Penyelesaian task memicu achievement |

## Cara Akses

Dari sidebar, klik menu **Productivity** > **Goals**.

## Flow Penggunaan Detail

1. Buka halaman Goals dari sidebar — lihat stats dashboard di atas
2. Klik **"Tambah Objective"** untuk membuat tujuan baru
3. Isi **judul objective** — buat inspirasional dan kualitatif (contoh: "Meningkatkan Kepuasan Pelanggan")
4. Pilih **kategori** bisnis dan **prioritas**
5. Set **tanggal mulai** dan **deadline**
6. Tambahkan **3-5 Key Results** — masing-masing harus terukur:
   * Isi judul KR (contoh: "Customer satisfaction score > 90%")
   * Set target value dan current value
   * Pilih satuan (unit)
7. Klik **Simpan** — objective muncul di daftar dengan overall progress
8. Update **current\_value** key results secara berkala untuk memantau progress
9. Review status objective: hijau (on track), kuning (at risk), biru (completed)

## Tips

* **Objective harus inspirasional** — "Menjadi brand sambal #1 di Indonesia" lebih baik daripada "Jual lebih banyak sambal"
* **Key Results harus SMART** — Specific, Measurable, Achievable, Relevant, Time-bound
* **Jangan terlalu banyak objective** — 3-5 per quarter sudah ideal. Lebih dari itu = kehilangan fokus
* **Review mingguan** — luangkan 15 menit setiap minggu untuk update current\_value dan cek status
* **Gunakan prioritas high hanya untuk 1-2 objective** — jika semua high priority, tidak ada yang benar-benar prioritas
* **Rayakan completed objectives** — ini memotivasi tim dan memberikan sense of accomplishment
* **Retroactive di akhir quarter** — evaluasi objective mana yang tercapai, mana yang tidak, dan pelajari alasannya
* **Manfaatkan KPITemplate** — buat template untuk role yang sama agar penilaian konsisten antar karyawan
* **Hubungkan PersonalGoal dengan Task** — pastikan setiap goal memiliki task konkret yang mendukung pencapaiannya
* **Gunakan FinancialGoal bersama Budget** — link ke Budget terkait untuk memantau apakah pengeluaran sesuai dengan target keuangan
* **Set notification\_frequency sesuai urgensi** — goal kritis gunakan `daily`, goal reguler gunakan `weekly`, goal dengan milestone penting gunakan `milestone`


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