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

# Settings

<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: "Settings"
description: "Pengaturan personal user untuk profil, preferensi notifikasi, tampilan, keamanan, dan lokalitas di SNISHOP ERP."
------------------------------------------------------------------------------------------------------------------------------

# Settings

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

Halaman **Settings** adalah pusat konfigurasi personal kamu di SNISHOP ERP. Di sini kamu mengelola informasi profil, preferensi notifikasi, tampilan aplikasi, keamanan akun, dan pengaturan lokalitas seperti bahasa, zona waktu, dan format angka.

Semua pengaturan di halaman ini bersifat **personal** — hanya berlaku untuk akun kamu sendiri dan tidak mempengaruhi user lain di perusahaan.

## Arsitektur Settings

```mermaid theme={null}
graph TD
    A[Settings Page] --> B[Tab Navigation]
    
    B --> T1[Profil]
    B --> T2[Notifikasi]
    B --> T3[Tampilan]
    B --> T4[Keamanan]
    B --> T5[Lokalitas]
    B --> T6[Privasi]
    
    T1 --> F1[Avatar Upload]
    T1 --> F2[Name/Email/Phone]
    T1 --> F3[Department/Position]
    T1 --> F4[Bio]
    
    T2 --> N1[Channel: Email/Push/In-App]
    T2 --> N2[Category toggles]
    T2 --> N3[DND Schedule]
    
    T3 --> D1[Theme: Light/Dark/Auto]
    T3 --> D2[Language: ID/EN]
    T3 --> D3[Density: Compact/Normal/Comfortable]
    T3 --> D4[Font Size]
    
    T4 --> S1[Password Change]
    T4 --> S2[2FA TOTP]
    T4 --> S3[Active Sessions]
    T4 --> S4[API Keys]
    
    T5 --> L1[Timezone]
    T5 --> L2[Date/Time Format]
    T5 --> L3[Currency]
    T5 --> L4[Number Format]
    
    T6 --> P1[Profile Visibility]
    T6 --> P2[Online Status]
    T6 --> P3[Data Export]
    T6 --> P4[Account Deletion]
```

## Struktur Pengaturan

```mermaid theme={null}
graph TD
    A[Settings] --> B[Profil]
    A --> C[Notifikasi]
    A --> D[Tampilan]
    A --> E[Keamanan]
    A --> F[Lokalitas]
    A --> G[Privasi]
    
    B --> B1[Nama & foto]
    B --> B2[Email & telepon]
    B --> B3[Bio & jabatan]
    
    C --> C1[Email notification]
    C --> C2[Push notification]
    C --> C3[In-app notification]
    
    D --> D1[Tema terang/gelap]
    D --> D2[Bahasa]
    D --> D3[Densitas tampilan]
    
    E --> E1[Password]
    E --> E2[2FA]
    E --> E3[Sesi aktif]
    
    F --> F1[Zona waktu]
    F --> F2[Format tanggal]
    F --> F3[Mata uang & angka]
```

## Tab Pengaturan

### 1. Tab Profil

Mengelola informasi personal kamu yang ditampilkan di sistem:

| Field | Deskripsi | Ditampilkan Di |
| - | - | - |
| **Foto Profil** | Upload foto (JPG/PNG, max 5MB) | Sidebar, komentar, laporan aktivitas |
| **Nama Lengkap** | Nama yang ditampilkan di sistem | Seluruh aplikasi |
| **Email** | Alamat email untuk login & notifikasi | Login, reset password |
| **Nomor Telepon** | Nomor WhatsApp/telepon aktif | Login OTP, notifikasi WhatsApp |
| **Jabatan** | Posisi kamu di perusahaan | Profil tim, direktori |
| **Bio** | Deskripsi singkat tentang kamu | Profil publik |
| **Departemen** | Divisi/departemen tempat kamu bekerja | Direktori tim |

**User Entity Fields (Profil)**:

| Field | Type | Required | Validasi |
| - | - | - | - |
| `full_name` | String | Ya | Min 2 karakter |
| `email` | String | Ya | Valid email format, unique |
| `phone` | String | Tidak | E.164 format |
| `avatar_url` | URL | Tidak | JPG/PNG, max 5MB |
| `position` | String | Tidak | Max 100 karakter |
| `department` | String | Tidak | Reference ke Department entity |
| `bio` | Text | Tidak | Max 500 karakter |

### 2. Tab Notifikasi

Kontrol granular untuk setiap jenis notifikasi:

| Kategori Notifikasi | Email | Push | In-App | Deskripsi |
| - | - | - | - | - |
| **Transaksi Baru** | ✅ | ✅ | ✅ | Ada order atau transaksi baru |
| **Stok Menipis** | ✅ | ❌ | ✅ | Produk di bawah minimum stock |
| **Approval Request** | ✅ | ✅ | ✅ | Dokumen menunggu approval kamu |
| **Tugas Baru** | ✅ | ✅ | ✅ | Tugas ditugaskan ke kamu |
| **Mention** | ❌ | ✅ | ✅ | Someone mentioned kamu di komentar |
| **Laporan Harian** | ✅ | ❌ | ❌ | Ringkasan bisnis harian via email |
| **Maintenance** | ✅ | ❌ | ✅ | Pemberitahuan maintenance sistem |
| **Update Fitur** | ✅ | ❌ | ❌ | Informasi fitur baru |

**Do Not Disturb:**

* Atur jadwal DND supaya notifikasi tidak masuk di luar jam kerja
* Contoh: DND aktif setiap hari jam 22:00 - 07:00

**Notification Preference Schema**:

```mermaid theme={null}
flowchart LR
    subgraph "Preference Matrix"
        Cat[Kategori] --> Ch1[Email Channel]
        Cat --> Ch2[Push Channel]
        Cat --> Ch3[In-App Channel]
    end

    subgraph "DND Engine"
        Ch1 & Ch2 & Ch3 --> DND{DND Active?}
        DND -->|Yes| Queue[Queue for later]
        DND -->|No| Deliver[Deliver now]
    end

    subgraph "Schedule"
        Sched[DND Schedule] --> DND
        Sched -->|Example| Time[22:00 - 07:00]
    end
```

### 3. Tab Tampilan

Kustomisasi tampilan aplikasi sesuai kenyamanan. Pengaturan ini disimpan pada field `preferences` di dalam entitas `User`.

| Pengaturan | Opsi | Deskripsi |
| - | - | - |
| **Tema** | Light / Dark / Auto | Light untuk siang, Dark untuk malam, Auto mengikuti sistem |
| **Warna Utama** | Hex color picker | Warna aksen utama antarmuka (disimpan di `preferences.primary_color`) |
| **Wallpaper** | Upload URL | Gambar latar belakang dashboard (disimpan di `preferences.wallpaper_url`) |
| **Bahasa** | Bahasa Indonesia / English | Mengubah seluruh teks di aplikasi |
| **Densitas** | Compact / Normal / Comfortable | Mengatur jarak antar elemen (padding & margin) |
| **Sidebar** | Expanded / Collapsed / Auto | Lebar sidebar default |
| **Font Size** | Small / Medium / Large | Ukuran teks global |
| **Animasi** | On / Reduced | Mengurangi animasi untuk aksesibilitas |

**Theme Application Flow**:

```mermaid theme={null}
flowchart TD
    A[User selects theme] --> B{Theme choice?}
    B -->|Light| C[Set CSS: --color-mode: light]
    B -->|Dark| D[Set CSS: --color-mode: dark]
    B -->|Auto| E{System preference?}
    E -->|Light| C
    E -->|Dark| D
    
    C & D --> F[Apply to all components]
    F --> G[Persist to localStorage]
    G --> H[Sync to server profile]
```

### 4. Tab Keamanan

Pengaturan keamanan akun kamu:

| Pengaturan | Deskripsi | Status |
| - | - | - |
| **Ganti Password** | Ubah password secara berkala | Disarankan setiap 90 hari |
| **Two-Factor Auth (2FA)** | Lapisan keamanan kedua via OTP | Sangat disarankan |
| **Sesi Aktif** | Lihat perangkat yang sedang login | Review berkala |
| **Login History** | Riwayat login terakhir | Cek untuk anomali |
| **API Key** | Key untuk integrasi eksternal | Jaga kerahasiaan |

**Kebijakan Password:**

* Minimum 8 karakter
* Kombinasi huruf besar, huruf kecil, dan angka
* Tidak boleh sama dengan 3 password terakhir

**2FA Enrollment Flow**:

```mermaid theme={null}
sequenceDiagram
    participant U as User
    participant S as Settings Page
    participant Auth as Auth Service
    participant App as Authenticator App

    U->>S: Click "Enable 2FA"
    S->>Auth: Request TOTP secret
    Auth-->>S: Return secret + QR code
    S-->>U: Display QR code
    U->>App: Scan QR code
    App-->>U: Show 6-digit TOTP code
    U->>S: Enter TOTP code for verification
    S->>Auth: Verify TOTP code
    Auth-->>S: Verification success
    S->>S: Save recovery codes
    S-->>U: Display recovery codes (save these!)
    U->>S: Confirm saved recovery codes
    S->>Auth: Activate 2FA
```

**Active Session Management**:

| Field | Deskripsi |
| - | - |
| **Device** | Jenis perangkat (Chrome on Windows, Safari on iPhone) |
| **IP Address** | Alamat IP dari mana login |
| **Location** | Lokasi perkiraan (kota, negara) |
| **Last Active** | Kapan terakhir aktif |
| **Action** | "Revoke" untuk logout dari perangkat tersebut |

### 5. Tab Lokalitas

Pengaturan format data berdasarkan preferensi regional:

| Pengaturan | Opsi | Mempengaruhi |
| - | - | - |
| **Zona Waktu** | WIB / WITA / WIT / Custom | Timestamp di seluruh aplikasi |
| **Format Tanggal** | DD/MM/YYYY / MM/DD/YYYY / YYYY-MM-DD | Tampilan tanggal |
| **Format Waktu** | 12 jam (AM/PM) / 24 jam | Tampilan waktu |
| **Mata Uang** | IDR / USD / Custom | Format currency display |
| **Format Angka** | 1.000,00 / 1,000.00 | Pemisah ribuan dan desimal |
| **Hari Pertama** | Senin / Minggu | Tampilan kalender |

**Locale Impact on Data Display**:

```mermaid theme={null}
flowchart LR
    subgraph "User Locale Settings"
        TZ[Timezone: WIB]
        DF[Date Format: DD/MM/YYYY]
        TF[Time Format: 24h]
        CUR[Currency: IDR]
        NF[Number: 1.000,00]
    end

    subgraph "Affected Displays"
        TZ --> T1[Transaction timestamps]
        TZ --> T2[Report date ranges]
        DF --> T3[Invoice dates]
        DF --> T4[Calendar views]
        CUR --> T5[Revenue display]
        CUR --> T6[Expense amounts]
        NF --> T7[Quantity fields]
        NF --> T8[Percentage values]
    end
```

### 6. Tab Privasi

Kontrol data personal dan visibilitas:

| Pengaturan | Deskripsi |
| - | - |
| **Profil Publik** | Apakah profil kamu terlihat oleh seluruh anggota perusahaan |
| **Status Online** | Tampilkan status online/offline ke tim |
| **Activity Feed** | Apakah aktivitas kamu muncul di feed tim |
| **Data Export** | Download salinan data personal kamu |
| **Account Deletion** | Hapus akun dan semua data personal |

**Data Export Package**:

| Data Category | Format | Included |
| - | - | - |
| Profile Info | JSON | Name, email, phone, avatar |
| Activity Log | CSV | All personal activity entries |
| Notes | Markdown | All personal notes |
| Tasks | JSON | All assigned tasks (completed + pending) |
| Settings | JSON | All preference values |

## Pengaturan Perusahaan (Company-Level Settings)

Selain pengaturan personal, SNISHOP ERP juga menyediakan pengaturan tingkat perusahaan yang dikelola oleh **Owner** atau **Admin**. Pengaturan ini mempengaruhi seluruh anggota perusahaan dan terbagi ke dalam beberapa entitas terpisah.

### CompanyPOSSettings — Konfigurasi Sistem Kasir (POS)

Entitas ini menyimpan konfigurasi sistem kasir (Point of Sale) perusahaan, termasuk pengaturan struk yang sebelumnya tergabung dalam satu objek `receipt_settings`.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `company_id` | String | **Ya** | — | ID perusahaan pemilik konfigurasi |
| `description` | String | Tidak | — | Catatan mengenai konfigurasi POS (max 1000 karakter) |
| `receipt_settings.logo_url` | String | Tidak | — | URL logo perusahaan untuk struk |
| `receipt_settings.business_name` | String | Tidak | — | Nama bisnis yang ditampilkan di struk |
| `receipt_settings.business_address` | String | Tidak | — | Alamat lengkap bisnis |
| `receipt_settings.business_phone` | String | Tidak | — | Nomor telepon bisnis |
| `receipt_settings.business_email` | String | Tidak | — | Email bisnis |
| `receipt_settings.tax_id` | String | Tidak | — | NPWP / Tax ID perusahaan |
| `receipt_settings.receipt_width` | Enum | Tidak | `80mm` | Lebar kertas struk: `58mm` atau `80mm` |
| `receipt_settings.show_logo` | Boolean | Tidak | `true` | Tampilkan logo di struk |
| `receipt_settings.show_tax_id` | Boolean | Tidak | `false` | Tampilkan NPWP di struk |
| `receipt_settings.show_cashier_name` | Boolean | Tidak | `true` | Tampilkan nama kasir |
| `receipt_settings.show_customer_info` | Boolean | Tidak | `true` | Tampilkan informasi pelanggan |
| `receipt_settings.show_item_image` | Boolean | Tidak | `false` | Tampilkan gambar produk di struk |
| `receipt_settings.header_text` | String | Tidak | `STRUK PEMBELIAN` | Teks header struk |
| `receipt_settings.footer_message` | String | Tidak | *Lihat deskripsi* | Pesan footer struk |
| `receipt_settings.print_auto_after_transaction` | Boolean | Tidak | `true` | Otomatis cetak struk setelah transaksi |
| `receipt_settings.font_size` | Enum | Tidak | `medium` | Ukuran font struk: `small`, `medium`, `large` |

### CompanyReceiptSettings — Konfigurasi Tampilan Struk

Entitas terpisah untuk pengaturan detail tampilan struk pembelian, termasuk opsi poin pelanggan dan pesan promo.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `company_id` | String | **Ya** | — | ID perusahaan |
| `description` | String | Tidak | — | Catatan konfigurasi struk (max 1000 karakter) |
| `show_company_logo` | Boolean | Tidak | `true` | Tampilkan logo perusahaan di struk |
| `show_company_address` | Boolean | Tidak | `true` | Tampilkan alamat perusahaan |
| `show_customer_name` | Boolean | Tidak | `true` | Tampilkan nama pelanggan |
| `show_customer_points` | Boolean | Tidak | `true` | Tampilkan total poin pelanggan saat ini |
| `show_points_earned` | Boolean | Tidak | `true` | Tampilkan poin yang didapat dari transaksi ini |
| `show_payment_details` | Boolean | Tidak | `true` | Tampilkan detail pembayaran |
| `show_change` | Boolean | Tidak | `true` | Tampilkan uang kembalian |
| `custom_header_text` | String | Tidak | — | Teks kustom di header struk |
| `custom_footer_text` | String | Tidak | `Terima kasih sudah berbelanja!` | Teks kustom di footer struk |
| `show_promo_message` | Boolean | Tidak | `false` | Aktifkan pesan promo di struk |
| `promo_message` | String | Tidak | — | Isi pesan promo/marketing |

### CompanyAttendanceSettings — Konfigurasi Absensi & Jam Kerja

Mengatur kebijakan absensi perusahaan termasuk lokasi geofence, jam kerja, shift, dan lembur.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `company_id` | String | **Ya** | — | ID perusahaan |
| `description` | String | Tidak | — | Penjelasan kebijakan absensi (max 1000 karakter) |
| `office_location.latitude` | Number | Tidak | — | Garis lintang kantor utama |
| `office_location.longitude` | Number | Tidak | — | Garis bujur kantor utama |
| `office_location.address` | String | Tidak | — | Alamat fisik kantor utama |
| `office_radius_meters` | Number | Tidak | `100` | Radius geofence kantor lama (fallback) |
| `require_office_location` | Boolean | Tidak | `false` | Wajib absen dari lokasi kantor |
| `default_accuracy_tolerance_meters` | Number | Tidak | `150` | Batas toleransi akurasi GPS (meter) |
| `locations` | Array\[Object] | Tidak | `[]` | Daftar multi-lokasi geofence absensi |
| `working_hours.start_time` | String | Tidak | `09:00` | Jam mulai kerja (HH:MM) |
| `working_hours.end_time` | String | Tidak | `17:00` | Jam selesai kerja (HH:MM) |
| `working_hours.break_duration_minutes` | Number | Tidak | `60` | Durasi istirahat (menit) |
| `shifts` | Array\[Object] | Tidak | `[]` | Daftar shift kerja |
| `overtime_settings.enabled` | Boolean | Tidak | `true` | Aktifkan fitur lembur |
| `overtime_settings.start_after_hours` | Number | Tidak | `8` | Lembur dimulai setelah X jam kerja |
| `overtime_settings.max_overtime_hours_per_day` | Number | Tidak | `4` | Maksimal jam lembur per hari |
| `late_tolerance_minutes` | Number | Tidak | `15` | Toleransi keterlambatan (menit) |
| `working_days` | Array\[Number] | Tidak | `[1,2,3,4,5]` | Hari kerja (1=Senin, 7=Minggu) |
| `auto_clock_out_enabled` | Boolean | Tidak | `false` | Otomatis clock out jika karyawan lupa |
| `auto_clock_out_time` | String | Tidak | `18:00` | Jam auto clock out |
| `require_photo` | Boolean | Tidak | `true` | Wajib foto selfie saat absen |
| `require_notes` | Boolean | Tidak | `false` | Wajib catatan saat absen |

**Struktur Lokasi Geofence (locations\[])**:

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `location_id` | String | **Ya** | — | ID unik area/lokasi absensi |
| `name` | String | **Ya** | — | Nama lokasi (misal: Head Office, Outlet 2) |
| `address` | String | Tidak | — | Alamat fisik lokasi |
| `latitude` | Number | **Ya** | — | Garis lintang pusat geofence |
| `longitude` | Number | **Ya** | — | Garis bujur pusat geofence |
| `radius_meters` | Number | Tidak | `100` | Radius lingkaran geofence (meter) |
| `accuracy_tolerance_meters` | Number | Tidak | `150` | Toleransi akurasi GPS maksimum |
| `assigned_employee_ids` | Array\[String] | Tidak | `[]` | Daftar ID karyawan (kosong = semua) |
| `is_active` | Boolean | Tidak | `true` | Status aktif lokasi geofence |

**Struktur Shift (shifts\[])**:

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `shift_id` | String | **Ya** | — | ID unik shift |
| `shift_name` | String | **Ya** | — | Nama shift (misal: Shift Pagi) |
| `start_time` | String | **Ya** | — | Jam mulai shift (HH:MM) |
| `end_time` | String | **Ya** | — | Jam selesai shift (HH:MM) |
| `break_duration_minutes` | Number | Tidak | `60` | Durasi istirahat shift (menit) |

### CompanyModuleSettings — Aktivasi & Konfigurasi Modul

Mengontrol modul mana saja yang diaktifkan untuk perusahaan, beserta fitur-fitur lanjutan dan aturan otomasi.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `company_id` | String | **Ya** | — | ID perusahaan |
| `description` | String | Tidak | — | Catatan konfigurasi modul (max 1000 karakter) |
| `business_type` | Enum | Tidak | `retail` | Tipe bisnis perusahaan |
| `inventory_method` | Enum | Tidak | `Average` | Metode penilaian persediaan |
| `multi_warehouse_enabled` | Boolean | Tidak | `false` | Aktifkan multi-gudang |
| `lot_tracking_enabled` | Boolean | Tidak | `false` | Aktifkan pelacakan lot/batch |
| `serial_tracking_enabled` | Boolean | Tidak | `false` | Aktifkan pelacakan serial number |
| `barcode_enabled` | Boolean | Tidak | `false` | Aktifkan fitur barcode |
| `auto_reorder_enabled` | Boolean | Tidak | `false` | Aktifkan reorder otomatis |
| `production_planning_enabled` | Boolean | Tidak | `false` | Aktifkan perencanaan produksi |
| `quality_control_enabled` | Boolean | Tidak | `false` | Aktifkan quality control |
| `attendance_integration` | Boolean | Tidak | `true` | Integrasi otomatis absensi ke payroll |
| `invoice_auto_create` | Boolean | Tidak | `false` | Otomatis buat invoice dari sales order |
| `pos_inventory_sync` | Boolean | Tidak | `true` | Sinkronisasi otomatis POS ke inventory |
| `finance_auto_record` | Boolean | Tidak | `false` | Otomatis catat transaksi ke finance |

**Modul yang Dapat Diaktifkan (`modules_enabled`)**:

| Key | Tipe | Default | Deskripsi |
| - | - | - | - |
| `manufacturing` | Boolean | `false` | Modul manufaktur & produksi |
| `inventory_advanced` | Boolean | `false` | Inventori lanjutan (lot, serial, multi-gudang) |
| `pos` | Boolean | `false` | Sistem kasir (Point of Sale) |
| `crm` | Boolean | `false` | Manajemen pelanggan (CRM) |
| `hr_payroll` | Boolean | `false` | HR & Penggajian |
| `projects` | Boolean | `false` | Manajemen proyek |
| `assets` | Boolean | `false` | Manajemen aset tetap |
| `documents` | Boolean | `false` | Manajemen dokumen |
| `email_marketing` | Boolean | `false` | Pemasaran email |
| `appointments` | Boolean | `false` | Jadwal janji temu |
| `team_chat` | Boolean | `false` | Obrolan tim internal |

**Pengaturan Notifikasi Modul (`notification_settings`)**:

| Key | Tipe | Default | Deskripsi |
| - | - | - | - |
| `low_stock_alert` | Boolean | `true` | Alert saat stok menipis |
| `order_approval_required` | Boolean | `false` | Persyaratan approval untuk order |
| `production_complete` | Boolean | `true` | Notifikasi produksi selesai |
| `invoice_overdue` | Boolean | `true` | Notifikasi invoice jatuh tempo |
| `leave_approval` | Boolean | `true` | Notifikasi persetujuan cuti |

### CompanyWablasSettings — Integrasi WhatsApp (Wablas)

Mengatur integrasi gateway WhatsApp Wablas untuk pengiriman struk dan notifikasi otomatis ke pelanggan.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `company_id` | String | **Ya** | — | ID perusahaan |
| `description` | String | Tidak | — | Catatan konfigurasi integrasi (max 1000 karakter) |
| `use_system_api` | Boolean | Tidak | `true` | Gunakan API Wablas default sistem |
| `wablas_api_key` | String | Tidak | — | API Key Wablas sendiri (jika `use_system_api = false`) |
| `wablas_secret_key` | String | Tidak | — | Secret Key Wablas sendiri |
| `wablas_domain` | String | Tidak | `solo.wablas.com` | Domain server Wablas |
| `is_active` | Boolean | Tidak | `true` | Status aktif integrasi |
| `auto_send_receipt` | Boolean | Tidak | `false` | Otomatis kirim struk via WhatsApp |
| `receipt_message_template` | String | Tidak | *Lihat deskripsi* | Template pesan struk WhatsApp |

**Variabel Template Pesan WhatsApp**:

| Variabel | Deskripsi |
| - | - |
| `{company_name}` | Nama perusahaan |
| `{transaction_id}` | Nomor transaksi |
| `{date}` | Tanggal transaksi |
| `{total}` | Total pembayaran |

### PrinterSettings — Konfigurasi Printer Thermal

Mengatur printer thermal Bluetooth yang digunakan untuk mencetak struk. Dapat bersifat personal (per-user) atau tingkat perusahaan.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `company_id` | String | Tidak | — | ID perusahaan (null untuk personal) |
| `user_id` | String | **Ya** | — | ID user pemilik konfigurasi |
| `printer_name` | String | Tidak | — | Nama printer yang tersimpan |
| `description` | String | Tidak | — | Catatan konfigurasi printer (max 1000 karakter) |
| `device_id` | String | Tidak | — | Bluetooth device ID |
| `device_name` | String | Tidak | — | Nama device dari Bluetooth |
| `paper_width` | Enum | Tidak | `80mm` | Lebar kertas thermal: `58mm` atau `80mm` |
| `encoding` | Enum | Tidak | `UTF-8` | Character encoding printer |
| `auto_cut` | Boolean | Tidak | `true` | Otomatis potong kertas setelah print |
| `beep_on_print` | Boolean | Tidak | `false` | Bunyi beep saat print |
| `auto_reconnect` | Boolean | Tidak | `true` | Otomatis reconnect jika disconnect |
| `print_logo` | Boolean | Tidak | `true` | Print logo di struk |
| `logo_url` | String | Tidak | — | URL logo untuk di-print |
| `header_text` | String | Tidak | `STRUK PEMBELIAN` | Teks header struk |
| `footer_text` | String | Tidak | `Terima kasih atas kunjungan Anda` | Teks footer struk |
| `font_size` | Enum | Tidak | `normal` | Ukuran font: `small`, `normal`, `large` |
| `last_connected` | DateTime | Tidak | — | Terakhir kali terhubung |
| `connection_count` | Number | Tidak | `0` | Jumlah koneksi berhasil |
| `is_default` | Boolean | Tidak | `false` | Jadikan printer default |

### Company.settings — Pengaturan Umum Perusahaan

Entitas `Company` memiliki objek `settings` embedded yang menyimpan konfigurasi global perusahaan.

| Field | Type | Default | Deskripsi |
| - | - | - | - |
| `settings.working_hours_start` | String | `09:00` | Jam mulai kerja |
| `settings.working_hours_end` | String | `17:00` | Jam selesai kerja |
| `settings.working_days` | Array\[Number] | `[1,2,3,4,5]` | Hari kerja (1=Senin, 7=Minggu) |
| `settings.leave_policy` | Object | — | Kebijakan cuti perusahaan |
| `settings.expiry_thresholds.critical` | Number | `7` | Ambang batas hari kedaluwarsa kritis |
| `settings.expiry_thresholds.warning` | Number | `30` | Ambang batas hari kedaluwarsa peringatan |
| `settings.expiry_thresholds.info` | Number | `90` | Ambang batas hari kedaluwarsa informasi |
| `settings.batch_allocation_strategy` | Enum | `fifo` | Strategi alokasi batch: `fifo` atau `fefo` |
| `settings.spoilage_default_treatment` | Enum | `absorbed_normal` | Perlakuan spoilage: `absorbed_normal` atau `expense_abnormal` |
| `settings.tax.enabled` | Boolean | `false` | Aktifkan perhitungan pajak |
| `settings.tax.rate` | Number | `11` | Tarif PPN dalam persen |
| `settings.tax.mode` | Enum | `inclusive` | Mode pajak: `inclusive` atau `exclusive` |
| `settings.tax.rounding` | Enum | `per_transaction` | Pembulatan: `per_line` atau `per_transaction` |

### User.preferences — Preferensi Personal User

Objek `preferences` di dalam entitas `User` menyimpan preferensi tampilan personal.

| Field | Type | Default | Deskripsi |
| - | - | - | - |
| `preferences.theme` | String | — | Tema tampilan (light/dark/auto) |
| `preferences.primary_color` | String | — | Warna aksen utama (hex color) |
| `preferences.wallpaper_url` | String | — | URL gambar latar belakang dashboard |
| `preferences.referral_modal_dismissed` | Boolean | `false` | Status modal referral sudah ditutup |

## Cara Akses

| Metode | Cara |
| - | - |
| **Avatar Menu** | Klik foto profil di pojok kanan atas → **Settings** |
| **Sidebar** | Scroll ke paling bawah sidebar → klik **Pengaturan** |
| **Keyboard** | Tekan `Ctrl+,` (shortcut default) |

## Flow Penggunaan

```mermaid theme={null}
flowchart TD
    A[Buka Settings] --> B{Apa yang ingin diubah?}
    B -->|Info personal| C[Tab Profil]
    B -->|Notifikasi| D[Tab Notifikasi]
    B -->|Tampilan| E[Tab Tampilan]
    B -->|Keamanan| F[Tab Keamanan]
    B -->|Format data| G[Tab Lokalitas]
    
    C --> C1[Update informasi]
    D --> D1[Atur preferensi notifikasi]
    E --> E1[Pilih tema & bahasa]
    F --> F1[Aktifkan 2FA / ganti password]
    G --> G1[Set zona waktu & format]
    
    C1 --> H[Simpan ke server]
    D1 --> H
    E1 --> H
    F1 --> H
    G1 --> H

    H --> I[Persist ke localStorage]
    I --> J[Apply changes globally]
```

## Settings Persistence

```mermaid theme={null}
flowchart LR
    subgraph "User Action"
        A[Change setting] --> B[Validate input]
    end

    subgraph "Client-Side"
        B --> C[Update React state]
        C --> D[Write to localStorage]
    end

    subgraph "Server-Side"
        D --> E[API: Update user preferences]
        E --> F[(UserPreferences entity)]
    end

    subgraph "Cross-Device"
        F --> G[Other devices sync on login]
    end
```

## Entity Relationship Diagram

```mermaid theme={null}
erDiagram
    User ||--o| User : "memiliki preferences"
    User ||--o{ Company : "owner / member"
    Company ||--o| CompanyPOSSettings : "memiliki konfigurasi POS"
    Company ||--o| CompanyReceiptSettings : "memiliki konfigurasi struk"
    Company ||--o| CompanyAttendanceSettings : "memiliki konfigurasi absensi"
    Company ||--o| CompanyModuleSettings : "memiliki konfigurasi modul"
    Company ||--o| CompanyWablasSettings : "memiliki integrasi Wablas"
    Company ||--o{ PrinterSettings : "memiliki printer (opsional)"
    User ||--o{ PrinterSettings : "memiliki printer personal"

    User {
        string email PK
        string full_name
        string role "admin | user"
        string subscription_plan "free | pro | business | advanced | enterprise"
        string active_company_id FK
        object preferences "theme, primary_color, wallpaper_url"
    }

    Company {
        string name
        string owner_id FK
        string industry "retail | manufacturing | services | ..."
        object settings "working_hours, tax, expiry_thresholds"
    }

    CompanyPOSSettings {
        string company_id FK
        string description
        object receipt_settings "nested: logo, width, font, header/footer"
    }

    CompanyReceiptSettings {
        string company_id FK
        boolean show_company_logo
        boolean show_customer_points
        boolean show_promo_message
        string custom_footer_text
    }

    CompanyAttendanceSettings {
        string company_id FK
        object office_location "lat, lng, address"
        array locations "multi-geofence"
        object working_hours "start, end, break"
        array shifts "shift definitions"
        object overtime_settings "enabled, max hours"
        boolean require_photo
        boolean auto_clock_out_enabled
    }

    CompanyModuleSettings {
        string company_id FK
        string business_type "retail | manufacturing | ..."
        string inventory_method "FIFO | LIFO | Average"
        object modules_enabled "11 modul boolean flags"
        object notification_settings "alert flags"
    }

    CompanyWablasSettings {
        string company_id FK
        boolean use_system_api
        string wablas_domain
        boolean auto_send_receipt
        string receipt_message_template
    }

    PrinterSettings {
        string user_id FK
        string company_id FK
        string paper_width "58mm | 80mm"
        string encoding "UTF-8 | GB18030 | ..."
        boolean is_default
        boolean auto_reconnect
    }
```

## Entity Schema Tables

### User

| Field | Type | Required | Deskripsi |
| - | - | - | - |
| `email` | String | **Ya** | Email pengguna (unique) |
| `full_name` | String | **Ya** | Nama lengkap pengguna |
| `role` | Enum | Tidak | Role: `admin` atau `user` |
| `subscription_plan` | Enum | Tidak | Plan membership: `free`, `pro`, `business`, `advanced`, `enterprise` |
| `subscription_start` | DateTime | Tidak | Tanggal mulai subscription |
| `subscription_end` | DateTime | Tidak | Tanggal berakhir subscription |
| `membership_duration_type` | Enum | Tidak | Durasi membership: `monthly`, `yearly`, `custom`, `lifetime` |
| `membership_start_date` | Date | Tidak | Tanggal mulai membership |
| `membership_end_date` | Date | Tidak | Tanggal berakhir membership |
| `is_readonly_mode` | Boolean | Tidak | Mode read-only saat expired (grace 3 hari) |
| `active_company_id` | String | Tidak | ID perusahaan yang sedang aktif |
| `company_slots_purchased` | Number | Tidak | Slot perusahaan tambahan di luar batas plan |
| `ai_monthly_usage` | Number | Tidak | Penggunaan AI bulan ini |
| `ai_credits` | Number | Tidak | Kredit AI tersedia (default: 10) |
| `balance` | Number | Tidak | Saldo deposit untuk membership/addon |
| `commission_balance` | Number | Tidak | Saldo komisi referral yang dapat ditarik |
| `admin_type` | Enum | Tidak | Tipe admin: `owner` atau `basic` |
| `admin_tier` | Enum | Tidak | Tier admin: `none`, `business`, `advanced`, `enterprise` |
| `productivity_score` | Number | Tidak | Skor produktivitas pengguna |
| `user_level` | Number | Tidak | Level berdasarkan achievement points |
| `preferences` | Object | Tidak | Preferensi tampilan (theme, warna, wallpaper) |

### Company

| Field | Type | Required | Deskripsi |
| - | - | - | - |
| `name` | String | **Ya** | Nama perusahaan |
| `owner_id` | String | **Ya** | ID owner perusahaan |
| `owner_email` | String | **Ya** | Email owner |
| `owner_subscription_plan` | Enum | Tidak | Plan membership owner |
| `description` | String | Tidak | Deskripsi perusahaan |
| `industry` | Enum | Tidak | Industri: `retail`, `manufacturing`, `services`, `technology`, `food_beverage`, `healthcare`, `education`, `other` |
| `address` | String | Tidak | Alamat perusahaan |
| `phone` | String | Tidak | Nomor telepon |
| `email` | String | Tidak | Email perusahaan |
| `website` | String | Tidak | Website perusahaan |
| `logo_url` | String | Tidak | URL logo perusahaan |
| `tax_id` | String | Tidak | NPWP perusahaan |
| `employee_count` | Number | Tidak | Jumlah karyawan (default: 0) |
| `business_type` | String | Tidak | Kategori bisnis dari onboarding |
| `active_modules` | String | Tidak | JSON string array ID modul aktif |
| `settings` | Object | Tidak | Pengaturan global perusahaan |
| `landing_page_config` | Object | Tidak | Konfigurasi landing page perusahaan |

### CompanyAttendanceSettings — Sub-Objects

**office\_location**:

| Field | Type | Deskripsi |
| - | - | - |
| `latitude` | Number | Garis lintang kantor |
| `longitude` | Number | Garis bujur kantor |
| `address` | String | Alamat fisik kantor |

**overtime\_settings**:

| Field | Type | Default | Deskripsi |
| - | - | - | - |
| `enabled` | Boolean | `true` | Aktifkan fitur lembur |
| `start_after_hours` | Number | `8` | Lembur dimulai setelah X jam |
| `max_overtime_hours_per_day` | Number | `4` | Maksimal lembur per hari |

### CompanyModuleSettings — Sub-Objects

**custom\_fields\[]**:

| Field | Type | Deskripsi |
| - | - | - |
| `module` | String | Nama modul target |
| `field_name` | String | Nama field kustom |
| `field_type` | String | Tipe data field |
| `required` | Boolean | Apakah field wajib diisi |
| `options` | Array\[String] | Opsi untuk field tipe pilihan |

**workflow\_rules\[]**:

| Field | Type | Deskripsi |
| - | - | - |
| `module` | String | Modul pemicu workflow |
| `trigger` | String | Event pemicu |
| `condition` | Object | Kondisi yang harus terpenuhi |
| `action` | String | Aksi yang dijalankan |
| `is_active` | Boolean | Status aktif rule |

## Settings Lifecycle — State Diagram

```mermaid theme={null}
stateDiagram-v2
    [*] --> DefaultValues: Entitas dibuat
    DefaultValues --> Active: Owner/Admin mengonfigurasi
    Active --> Active: Update pengaturan
    Active --> Suspended: Membership expired
    Suspended --> Active: Membership diperpanjang
    Suspended --> Archived: Perusahaan dinonaktifkan
    Archived --> Active: Perusahaan diaktifkan kembali
    Active --> [*]: Perusahaan dihapus

    state Active {
        [*] --> Validating
        Validating --> Saving: Input valid
        Validating --> Error: Input tidak valid
        Error --> Validating: Perbaiki input
        Saving --> Syncing: Data tersimpan
        Syncing --> Applied: Sinkron ke semua client
        Applied --> [*]
    }

    state Suspended {
        [*] --> ReadOnly
        ReadOnly --> ReadOnly: Hanya bisa lihat data
        ReadOnly --> [*]
    }
```

## Sequence Diagrams

### Flow Memperbarui Pengaturan Perusahaan

```mermaid theme={null}
sequenceDiagram
    participant Admin as Admin/Owner
    participant UI as Settings Page
    participant API as Backend API
    participant DB as Database
    participant Cache as Cache Layer

    Admin->>UI: Buka halaman Company Settings
    UI->>API: GET /api/company/settings
    API->>DB: Query CompanyPOSSettings, CompanyReceiptSettings, dll.
    DB-->>API: Return settings data
    API-->>UI: Render current settings

    Admin->>UI: Ubah konfigurasi (misal: receipt_width = 58mm)
    Admin->>UI: Klik "Simpan"
    UI->>UI: Validasi input client-side
    UI->>API: PUT /api/company/pos-settings
    API->>API: Validasi permission (role check)
    API->>DB: UPDATE CompanyPOSSettings
    DB-->>API: Update success
    API->>Cache: Invalidate cache
    API-->>UI: Response 200 OK
    UI-->>Admin: Toast "Pengaturan berhasil disimpan"
```

### Flow Sinkronisasi Pengaturan Lintas Perangkat

```mermaid theme={null}
sequenceDiagram
    participant D1 as Device 1 (Desktop)
    participant Server as Backend Server
    participant DB as Database
    participant D2 as Device 2 (Mobile)

    D1->>Server: PUT /api/user/preferences {theme: "dark"}
    Server->>DB: UPDATE User.preferences
    DB-->>Server: Success
    Server-->>D1: 200 OK + updated preferences

    Note over D2: User membuka aplikasi di Device 2
    D2->>Server: GET /api/user/me
    Server->>DB: SELECT User with preferences
    DB-->>Server: User data + preferences
    Server-->>D2: User data {theme: "dark"}
    D2->>D2: Apply theme dark ke UI
    D2->>D2: Persist ke localStorage
```

### Flow Konfigurasi Absensi Multi-Lokasi

```mermaid theme={null}
sequenceDiagram
    participant HR as HR Admin
    participant UI as Attendance Settings
    participant API as Backend API
    participant DB as Database

    HR->>UI: Buka tab Attendance Settings
    UI->>API: GET /api/company/attendance-settings
    API-->>UI: Return current settings

    HR->>UI: Tambah lokasi baru (Outlet 2)
    HR->>UI: Set koordinat GPS & radius 150m
    HR->>UI: Assign karyawan ke lokasi
    HR->>UI: Klik "Simpan"

    UI->>API: PUT /api/company/attendance-settings
    Note right of API: Validasi: coordinates valid,<br/>radius > 0, employee IDs exist
    API->>DB: UPDATE CompanyAttendanceSettings
    DB-->>API: Success
    API-->>UI: 200 OK

    Note over UI: Karyawan di Outlet 2<br/>sekarang bisa absen<br/>di lokasi baru
```

### Flow Integrasi WhatsApp Wablas

```mermaid theme={null}
sequenceDiagram
    participant Admin as Admin
    participant UI as Wablas Settings
    participant API as Backend API
    participant Wablas as Wablas API
    participant Customer as Customer WhatsApp

    Admin->>UI: Buka Wablas Settings
    Admin->>UI: Masukkan API Key & Domain
    Admin->>UI: Aktifkan auto_send_receipt
    Admin->>UI: Edit template pesan struk
    Admin->>UI: Klik "Simpan & Test"

    UI->>API: PUT /api/company/wablas-settings
    API->>DB: UPDATE CompanyWablasSettings
    API->>Wablas: POST /send-message (test)
    Wablas-->>API: Message sent
    API-->>UI: Success + preview

    Note over Wablas,Customer: Setelah transaksi berikutnya:
    Wablas->>Customer: Kirim struk otomatis via WhatsApp
```

## Enum Reference Tables

### User.role

| Nilai | Deskripsi |
| - | - |
| `admin` | Administrator dengan akses penuh ke manajemen perusahaan |
| `user` | User biasa dengan akses terbatas sesuai permission |

### User.subscription\_plan

| Nilai | Deskripsi |
| - | - |
| `free` | Plan gratis dengan fitur dasar |
| `pro` | Plan profesional dengan fitur lanjutan |
| `business` | Plan bisnis untuk tim kecil-menengah |
| `advanced` | Plan advanced untuk perusahaan besar |
| `enterprise` | Plan enterprise dengan fitur tanpa batas |

### User.admin\_type

| Nilai | Deskripsi |
| - | - |
| `owner` | Full access ke seluruh aplikasi |
| `basic` | Hanya akses transaksi produk digital |

### User.admin\_tier

| Nilai | Deskripsi |
| - | - |
| `none` | Bukan admin perusahaan |
| `business` | Tier business untuk company management |
| `advanced` | Tier advanced untuk company management |
| `enterprise` | Tier enterprise untuk company management |

### User.membership\_duration\_type

| Nilai | Deskripsi |
| - | - |
| `monthly` | Membership bulanan |
| `yearly` | Membership tahunan |
| `custom` | Durasi kustom |
| `lifetime` | Membership seumur hidup |

### Company.industry

| Nilai | Deskripsi |
| - | - |
| `retail` | Perdagangan eceran |
| `manufacturing` | Manufaktur & produksi |
| `services` | Jasa & layanan |
| `technology` | Teknologi & perangkat lunak |
| `food_beverage` | Makanan & minuman |
| `healthcare` | Kesehatan |
| `education` | Pendidikan |
| `other` | Lainnya |

### CompanyModuleSettings.business\_type

| Nilai | Deskripsi |
| - | - |
| `retail` | Perdagangan eceran |
| `manufacturing` | Manufaktur & produksi |
| `services` | Jasa & layanan |
| `digital_products` | Produk digital |
| `food_beverage` | Makanan & minuman |
| `healthcare` | Kesehatan |
| `education` | Pendidikan |
| `consulting` | Konsultasi |
| `hybrid` | Kombinasi beberapa tipe |

### CompanyModuleSettings.inventory\_method

| Nilai | Deskripsi |
| - | - |
| `FIFO` | First In, First Out — barang pertama masuk, pertama keluar |
| `LIFO` | Last In, First Out — barang terakhir masuk, pertama keluar |
| `Average` | Rata-rata tertimbang dari semua biaya persediaan |
| `Specific_Identification` | Identifikasi spesifik per unit barang |

### CompanyPOSSettings.receipt\_settings.receipt\_width

| Nilai | Deskripsi |
| - | - |
| `58mm` | Kertas thermal kecil (58mm) |
| `80mm` | Kertas thermal standar (80mm) |

### CompanyPOSSettings.receipt\_settings.font\_size

| Nilai | Deskripsi |
| - | - |
| `small` | Font kecil — lebih banyak isi per struk |
| `medium` | Font sedang (default) |
| `large` | Font besar — mudah dibaca |

### PrinterSettings.paper\_width

| Nilai | Deskripsi |
| - | - |
| `58mm` | Kertas thermal kecil (58mm) |
| `80mm` | Kertas thermal standar (80mm) |

### PrinterSettings.encoding

| Nilai | Deskripsi |
| - | - |
| `UTF-8` | Unicode standar — mendukung semua karakter (default) |
| `GB18030` | Chinese Simplified |
| `Big5` | Chinese Traditional |
| `Shift_JIS` | Japanese |
| `EUC-KR` | Korean |

### PrinterSettings.font\_size

| Nilai | Deskripsi |
| - | - |
| `small` | Font kecil |
| `normal` | Font normal (default) |
| `large` | Font besar |

### Company.settings.batch\_allocation\_strategy

| Nilai | Deskripsi |
| - | - |
| `fifo` | First In, First Out — alokasi batch berdasarkan tanggal terima |
| `fefo` | First Expiry, First Out — alokasi batch berdasarkan tanggal kedaluwarsa |

### Company.settings.spoilage\_default\_treatment

| Nilai | Deskripsi |
| - | - |
| `absorbed_normal` | Spoilage diserap ke HPP unit baik |
| `expense_abnormal` | Spoilage dipisah sebagai beban periode |

### Company.settings.tax.mode

| Nilai | Deskripsi |
| - | - |
| `inclusive` | Pajak sudah termasuk dalam harga |
| `exclusive` | Pajak ditambahkan ke harga |

### Company.settings.tax.rounding

| Nilai | Deskripsi |
| - | - |
| `per_line` | Pembulatan per baris item |
| `per_transaction` | Pembulatan per total transaksi |

### CompanyAttendanceSettings.working\_days

| Nilai | Hari |
| - | - |
| `1` | Senin |
| `2` | Selasa |
| `3` | Rabu |
| `4` | Kamis |
| `5` | Jumat |
| `6` | Sabtu |
| `7` | Minggu |

## RBAC Permission Table

Berikut adalah hak akses berdasarkan role untuk setiap entitas pengaturan:

### Pengaturan Personal (User)

| Operasi | `user` | `admin` | Deskripsi |
| - | - | - | - |
| **Read** | ✅ Own | ✅ All | User hanya bisa lihat preferensi sendiri |
| **Update** | ✅ Own | ✅ All | User hanya bisa ubah preferensi sendiri |

### CompanyPOSSettings / CompanyReceiptSettings

| Operasi | `user` | `admin` (same company) | `admin` (other company) |
| - | - | - | - |
| **Create** | ❌ | ✅ | ❌ |
| **Read** | ✅ (company member) | ✅ | ❌ |
| **Update** | ❌ | ✅ | ❌ |
| **Delete** | ❌ | ✅ | ❌ |

### CompanyAttendanceSettings

| Operasi | `user` | `admin` (same company) | `admin` (other company) |
| - | - | - | - |
| **Create** | ❌ | ✅ | ❌ |
| **Read** | ✅ (company member) | ✅ | ❌ |
| **Update** | ❌ | ✅ | ❌ |
| **Delete** | ❌ | ✅ | ❌ |

### CompanyModuleSettings

| Operasi | `user` | `admin` (same company) | `admin` (other company) |
| - | - | - | - |
| **Create** | ❌ | ✅ | ❌ |
| **Read** | ✅ (company member) | ✅ | ❌ |
| **Update** | ❌ | ✅ | ❌ |
| **Delete** | ❌ | ✅ | ❌ |

### CompanyWablasSettings

| Operasi | `user` | `admin` (same company) | Deskripsi |
| - | - | - | - |
| **Create** | ❌ | ✅ | Hanya admin perusahaan yang aktif |
| **Read** | ✅ (company member) | ✅ | RLS: `company_id = active_company_id` OR `created_by_id = user.id` OR `role = admin` |
| **Update** | ❌ | ✅ | Hanya admin perusahaan yang aktif |
| **Delete** | ❌ | ✅ | Hanya admin perusahaan yang aktif |

### PrinterSettings

| Operasi | `user` | `admin` | Deskripsi |
| - | - | - | - |
| **Create** | ✅ Own | ✅ All | User bisa tambah printer personal |
| **Read** | ✅ Own | ✅ All | User hanya lihat printer sendiri + company |
| **Update** | ✅ Own | ✅ All | User hanya ubah printer sendiri |
| **Delete** | ✅ Own | ✅ All | User hanya hapus printer sendiri |

## Tips

* **Aktifkan Two-Factor Authentication** di tab Keamanan untuk melindungi akun kamu dari akses tidak sah
* **Review preferensi notifikasi** secara berkala — jika kamu sering mendapat notifikasi yang tidak relevan, matikan yang tidak perlu supaya tidak terganggu
* **Pengaturan bahasa dan zona waktu** mempengaruhi format tanggal, waktu, dan angka di seluruh aplikasi — pastikan sudah benar
* **Foto profil yang kamu upload** akan muncul di sidebar, komentar, dan laporan aktivitas — gunakan foto yang profesional
* **Ganti password secara berkala** (setiap 90 hari) untuk menjaga keamanan akun
* **Export data personal** sebelum menghapus akun jika kamu ingin menyimpan salinan data kamu
* **Konfigurasi PrinterSettings** sebelum memulai transaksi POS — pastikan `paper_width` sesuai dengan kertas thermal yang digunakan
* **CompanyModuleSettings** hanya bisa diubah oleh Owner/Admin — pastikan modul yang diaktifkan sesuai kebutuhan bisnis
* **CompanyAttendanceSettings** mendukung multi-lokasi geofence — gunakan fitur `locations[]` untuk perusahaan dengan banyak cabang
* **CompanyWablasSettings** memungkinkan pengiriman struk otomatis via WhatsApp — gunakan `receipt_message_template` untuk kustomisasi pesan

## Entitas Settings Tambahan

Selain entitas pengaturan utama yang telah diuraikan di atas, SNISHOP ERP juga memiliki beberapa entitas settings tambahan yang mengelola navigasi menu, toko, landing page, AI agent, referral, marketplace, dan dashboard kustom.

### MenuSettings — Konfigurasi Navigasi Menu

Entitas ini mendefinisikan setiap item menu yang tampil di sidebar aplikasi, termasuk visibilitas per tier subscription dan pengurutan tampilan.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `menu_id` | String | **Ya** | — | ID unik menu (misal: `tasks`, `notes`, `workspace`) |
| `menu_name` | String | **Ya** | — | Nama menu yang ditampilkan di sidebar |
| `menu_icon` | String | Tidak | — | Nama ikon dari library lucide-react |
| `menu_url` | String | Tidak | — | URL tujuan saat menu diklik |
| `parent_menu` | String | Tidak | — | ID parent menu jika ini adalah submenu |
| `description` | String | Tidak | — | Penjelasan fungsi dan tujuan menu (max 1000 karakter) |
| `is_visible_free` | Boolean | Tidak | `true` | Tampil untuk pengguna plan Free |
| `is_visible_pro` | Boolean | Tidak | `true` | Tampil untuk pengguna plan Pro |
| `is_visible_business` | Boolean | Tidak | `true` | Tampil untuk pengguna plan Business |
| `is_visible_advanced` | Boolean | Tidak | `true` | Tampil untuk pengguna plan Advanced |
| `is_visible_enterprise` | Boolean | Tidak | `true` | Tampil untuk pengguna plan Enterprise |
| `is_visible_admin` | Boolean | Tidak | `true` | Tampil untuk role admin |
| `order` | Number | Tidak | `0` | Urutan tampilan menu (ascending) |
| `is_active` | Boolean | Tidak | `true` | Status aktif menu |
| `requires_subscription` | Array\[String] | Tidak | — | Daftar subscription yang diperlukan untuk akses |
| `badge_text` | String | Tidak | — | Teks badge (misal: `NEW`, `BETA`) |
| `badge_color` | String | Tidak | — | Warna badge (hex color) |

### MenuAccessProfile — Profil Akses Menu per Role

Entitas ini menyimpan profil hak akses menu yang ditetapkan per role dalam suatu perusahaan. Setiap profil menentukan menu mana saja yang boleh diakses oleh role tertentu.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `company_id` | String | **Ya** | — | ID perusahaan pemilik profil |
| `role` | Enum | **Ya** | — | Role yang menggunakan profil akses ini |
| `profile_name` | String | **Ya** | — | Nama profil akses menu |
| `description` | String | Tidak | — | Penjelasan hak akses menu untuk role ini (max 1000 karakter) |
| `allowed_menus` | Array\[String] | **Ya** | — | Daftar ID menu yang diizinkan untuk role ini |
| `dashboard_type` | Enum | Tidak | `employee` | Tipe tampilan dashboard untuk role ini |
| `is_default` | Boolean | Tidak | `true` | Apakah ini profil default untuk role tersebut |
| `created_by` | String | Tidak | — | Email owner yang membuat profil |

### ShopSettings — Konfigurasi Toko / Storefront

Mengatur tampilan storefront toko, termasuk banner, kategori unggulan, promo, dan diskon reseller per tier.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `setting_key` | String | **Ya** | — | Kunci pengaturan unik |
| `description` | String | Tidak | — | Penjelasan konfigurasi toko ini (max 1000 karakter) |
| `banner_image_url` | String | Tidak | — | URL gambar banner toko |
| `banner_title` | String | Tidak | — | Judul banner toko |
| `banner_subtitle` | String | Tidak | — | Subtitle banner toko |
| `featured_categories` | Array\[String] | Tidak | — | Daftar ID kategori yang ditampilkan |
| `promo_banner` | Object | Tidak | — | Konfigurasi banner promo aktif |
| `reseller_discounts` | Object | Tidak | — | Diskon reseller per tier membership |

**Sub-Object `promo_banner`**:

| Field | Type | Default | Deskripsi |
| - | - | - | - |
| `active` | Boolean | — | Status aktif banner promo |
| `title` | String | — | Judul banner promo |
| `description` | String | — | Deskripsi promo |
| `discount_percentage` | Number | — | Persentase diskon promo |
| `valid_until` | DateTime | — | Berlaku hingga tanggal |

**Sub-Object `reseller_discounts`**:

| Field | Type | Default | Deskripsi |
| - | - | - | - |
| `free` | Number | `0` | Diskon untuk tier Free (0%) |
| `pro` | Number | `0.05` | Diskon untuk tier Pro (5%) |
| `business` | Number | `0.10` | Diskon untuk tier Business (10%) |
| `advanced` | Number | `0.15` | Diskon untuk tier Advanced (15%) |
| `enterprise` | Number | `0.20` | Diskon untuk tier Enterprise (20%) |

### HomeSettings — Konfigurasi Landing Page

Mengatur konten halaman utama (landing page) aplikasi, termasuk hero section, fitur unggulan, testimoni, dan informasi kontak.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `setting_key` | String | **Ya** | — | Kunci pengaturan unik (gunakan `main`) |
| `description` | String | Tidak | — | Penjelasan konfigurasi halaman utama (max 1000 karakter) |
| `hero_title` | String | Tidak | — | Judul utama hero section |
| `hero_subtitle` | String | Tidak | — | Subtitle hero section |
| `hero_cta_text` | String | Tidak | — | Teks tombol call-to-action |
| `hero_image_url` | String | Tidak | — | URL gambar hero |
| `features` | Array\[Object] | Tidak | — | Daftar fitur utama yang ditampilkan |
| `testimonials` | Array\[Object] | Tidak | — | Testimoni dari pengguna |
| `stats` | Object | Tidak | — | Statistik aplikasi (users, tasks, workspaces) |
| `contact_email` | String | Tidak | `snishopsolusinetwork@gmail.com` | Email kontak |
| `contact_whatsapp` | String | Tidak | `081532168812` | Nomor WhatsApp kontak |
| `social_links` | Object | Tidak | — | Tautan media sosial |

**Sub-Object `features[]`**:

| Field | Type | Deskripsi |
| - | - | - |
| `title` | String | Judul fitur |
| `description` | String | Deskripsi fitur |
| `icon` | String | Nama ikon fitur |

**Sub-Object `testimonials[]`**:

| Field | Type | Deskripsi |
| - | - | - |
| `name` | String | Nama pemberi testimoni |
| `role` | String | Jabatan/peran pemberi testimoni |
| `content` | String | Isi testimoni |
| `avatar_url` | String | URL foto avatar |

**Sub-Object `social_links`**:

| Field | Type | Deskripsi |
| - | - | - |
| `facebook` | String | URL profil Facebook |
| `instagram` | String | URL profil Instagram |
| `twitter` | String | URL profil Twitter |
| `linkedin` | String | URL profil LinkedIn |

### AIAgentSettings — Konfigurasi AI Agent

Mengatur parameter pricing dan metode pembayaran untuk penggunaan AI Agent di seluruh platform.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `setting_key` | String | **Ya** | `global` | Kunci pengaturan (selalu `global` untuk pengaturan utama) |
| `description` | String | Tidak | — | Catatan pengaturan AI Agent (max 1000 karakter) |
| `credit_to_rupiah_rate` | Number | Tidak | `10` | Nilai 1 kredit dalam Rupiah (misal: 10 = 1 kredit bernilai Rp10) |
| `base_price_per_run` | Number | Tidak | `1000` | Harga dasar default per penggunaan AI (Rupiah) bila agent tidak menetapkan harga sendiri |
| `allow_credit_payment` | Boolean | Tidak | `true` | Izinkan pengguna membayar dengan kredit AI |
| `allow_balance_payment` | Boolean | Tidak | `true` | Izinkan pengguna membayar dengan saldo Rupiah |

### ReferralSetting — Konfigurasi Komisi Referral

Menentukan persentase komisi referral untuk setiap paket langganan, baik untuk pembelian pertama maupun perpanjangan.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `plan_key` | String | **Ya** | — | Kunci paket langganan terkait (misal: `free`, `pro`, `business`) |
| `description` | String | Tidak | — | Penjelasan komisi referral untuk paket ini (max 1000 karakter) |
| `first_purchase_commission_rate` | Number | **Ya** | `0.50` | Persentase komisi untuk pembelian pertama (0.50 = 50%) |
| `renewal_commission_rate` | Number | **Ya** | `0.10` | Persentase komisi untuk perpanjangan berikutnya (0.10 = 10%) |

### MarketplaceCommissionSettings — Konfigurasi Komisi Marketplace

Mengatur persentase komisi yang diambil platform marketplace, serta kebijakan penarikan saldo.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `commission_rate` | Number | **Ya** | `10` | Persentase komisi marketplace (0-100) |
| `description` | String | Tidak | — | Penjelasan kebijakan komisi dan ketentuan penarikan (max 1000 karakter) |
| `min_withdrawal` | Number | Tidak | `100000` | Minimum penarikan saldo (Rupiah) |
| `withdrawal_fee` | Number | Tidak | `5000` | Biaya admin per penarikan (Rupiah) |
| `is_active` | Boolean | Tidak | `true` | Status aktif pengaturan komisi |

### CustomDashboardConfig — Konfigurasi Dashboard Kustom

Memungkinkan pengguna membuat dashboard kustom dengan widget-widget yang dapat dikonfigurasi posisi, tipe, dan sumber datanya.

| Field | Type | Required | Default | Deskripsi |
| - | - | - | - | - |
| `company_id` | String | **Ya** | — | ID perusahaan pemilik dashboard |
| `user_id` | String | **Ya** | — | ID pengguna pemilik dashboard |
| `dashboard_name` | String | **Ya** | — | Nama dashboard kustom |
| `description` | String | Tidak | — | Deskripsi dashboard |
| `role` | String | Tidak | — | Role yang dapat mengakses (opsional) |
| `is_public` | Boolean | Tidak | `false` | Apakah dashboard bisa diakses anggota lain |
| `widgets` | Array\[Object] | **Ya** | — | Daftar widget dalam dashboard |
| `layout` | Enum | Tidak | `grid` | Tata letak dashboard: `grid` atau `list` |
| `created_date` | DateTime | Tidak | — | Tanggal pembuatan dashboard |
| `last_modified_date` | DateTime | Tidak | — | Tanggal terakhir dimodifikasi |

**Sub-Object `widgets[]`**:

| Field | Type | Deskripsi |
| - | - | - |
| `widget_id` | String | ID unik widget |
| `widget_type` | Enum | Tipe widget: `chart`, `table`, `metric`, `list`, `calendar`, `forecast` |
| `title` | String | Judul widget |
| `data_source` | String | Sumber data widget (entity type: Invoice, FinancialRecord, dll.) |
| `filters` | Object | Filter data yang diterapkan pada widget |
| `chart_type` | Enum | Tipe grafik (khusus widget\_type=chart): `line`, `bar`, `pie`, `area` |
| `position` | Object | Posisi widget: `row`, `column`, `width`, `height` |
| `refresh_interval` | Number | Interval refresh data dalam detik |

## Entity Relationship Diagram — Settings Tambahan

```mermaid theme={null}
erDiagram
    Company ||--o{ MenuAccessProfile : "memiliki profil akses menu per role"
    Company ||--o| ShopSettings : "memiliki konfigurasi toko"
    Company ||--o{ CustomDashboardConfig : "memiliki dashboard kustom"
    User ||--o{ CustomDashboardConfig : "membuat dashboard personal"
    Company ||--o| MarketplaceCommissionSettings : "memiliki kebijakan komisi"
    Platform ||--o| MenuSettings : "mengatur navigasi global"
    Platform ||--o| HomeSettings : "mengatur landing page"
    Platform ||--o| AIAgentSettings : "mengatur pricing AI"
    Platform ||--o{ ReferralSetting : "mengatur komisi referral per plan"

    MenuAccessProfile {
        string company_id FK
        string role "owner | admin | supervisor | ..."
        string profile_name
        array allowed_menus "daftar ID menu"
        string dashboard_type "owner | admin | employee | ..."
        boolean is_default
    }

    MenuSettings {
        string menu_id PK
        string menu_name
        string menu_icon
        string menu_url
        string parent_menu FK
        boolean is_visible_free
        boolean is_visible_pro
        boolean is_visible_business
        boolean is_visible_advanced
        boolean is_visible_enterprise
        boolean is_visible_admin
        number order
        boolean is_active
        array requires_subscription
        string badge_text
        string badge_color
    }

    ShopSettings {
        string setting_key PK
        string banner_image_url
        string banner_title
        object promo_banner "active, title, discount, valid_until"
        object reseller_discounts "free, pro, business, advanced, enterprise"
        array featured_categories
    }

    HomeSettings {
        string setting_key PK
        string hero_title
        string hero_subtitle
        string hero_cta_text
        string hero_image_url
        array features "title, description, icon"
        array testimonials "name, role, content, avatar_url"
        object stats "users, tasks, workspaces"
        string contact_email
        string contact_whatsapp
        object social_links "facebook, instagram, twitter, linkedin"
    }

    AIAgentSettings {
        string setting_key PK "global"
        number credit_to_rupiah_rate "default: 10"
        number base_price_per_run "default: 1000"
        boolean allow_credit_payment
        boolean allow_balance_payment
    }

    ReferralSetting {
        string plan_key PK "free, pro, business, ..."
        number first_purchase_commission_rate "default: 0.50"
        number renewal_commission_rate "default: 0.10"
    }

    MarketplaceCommissionSettings {
        number commission_rate "default: 10%"
        number min_withdrawal "default: 100000"
        number withdrawal_fee "default: 5000"
        boolean is_active
    }

    CustomDashboardConfig {
        string company_id FK
        string user_id FK
        string dashboard_name
        string layout "grid | list"
        boolean is_public
        array widgets "widget definitions"
    }
```

## State Diagram — Status Menu & Dashboard

```mermaid theme={null}
stateDiagram-v2
    [*] --> Inactive: MenuSettings dibuat (is_active = false)
    Inactive --> Active: Admin mengaktifkan menu
    Active --> Inactive: Admin menonaktifkan menu
    Active --> Active: Update konfigurasi menu
    Inactive --> [*]: Menu dihapus

    state Active {
        [*] --> VisibleAll
        VisibleAll --> TierRestricted: Set requires_subscription
        TierRestricted --> VisibleAll: Hapus restriction
        VisibleAll --> [*]
    }
```

```mermaid theme={null}
stateDiagram-v2
    [*] --> Draft: CustomDashboardConfig dibuat
    Draft --> Published: Owner mempublikasikan (is_public = true)
    Published --> Private: Owner mengubah ke private (is_public = false)
    Private --> Published: Owner mempublikasikan kembali
    Published --> Published: Update widget/layout
    Private --> Private: Update widget/layout
    Published --> [*]: Dashboard dihapus
    Private --> [*]: Dashboard dihapus
```

## Sequence Diagrams — Settings Tambahan

### Flow Konfigurasi Menu Akses per Role

```mermaid theme={null}
sequenceDiagram
    participant Owner as Owner/Admin
    participant UI as Menu Access Settings
    participant API as Backend API
    participant DB as Database

    Owner->>UI: Buka Menu Access Profiles
    UI->>API: GET /api/company/menu-access-profiles
    API->>DB: Query MenuAccessProfile WHERE company_id
    DB-->>API: Return profiles
    API-->>UI: Render daftar profil

    Owner->>UI: Pilih role "store_admin"
    UI->>API: GET /api/menu-settings
    API-->>UI: Return daftar semua menu

    Owner->>UI: Centang menu yang diizinkan
    Owner->>UI: Pilih dashboard_type = "cashier"
    Owner->>UI: Klik "Simpan"

    UI->>API: PUT /api/company/menu-access-profiles/:id
    Note right of API: Validasi: menu_id exists,<br/>role valid, company_id match
    API->>DB: UPDATE MenuAccessProfile
    DB-->>API: Success
    API-->>UI: 200 OK
    UI-->>Owner: Toast "Profil akses berhasil diperbarui"

    Note over UI: Karyawan dengan role<br/>store_admin sekarang<br/>hanya melihat menu<br/>yang diizinkan
```

### Flow Konfigurasi Landing Page

```mermaid theme={null}
sequenceDiagram
    participant Admin as Admin
    participant UI as Home Settings Page
    participant API as Backend API
    participant DB as Database
    participant CDN as CDN / Storage

    Admin->>UI: Buka Home Settings
    UI->>API: GET /api/home-settings
    API-->>UI: Return current HomeSettings

    Admin->>UI: Upload gambar hero baru
    UI->>CDN: POST /upload (image)
    CDN-->>UI: Return image URL

    Admin->>UI: Edit hero_title, hero_subtitle
    Admin->>UI: Tambah fitur baru (title, description, icon)
    Admin->>UI: Edit testimoni
    Admin->>UI: Update social links
    Admin->>UI: Klik "Simpan"

    UI->>UI: Validasi client-side
    UI->>API: PUT /api/home-settings
    API->>DB: UPDATE HomeSettings
    DB-->>API: Success
    API-->>UI: 200 OK
    UI-->>Admin: Toast "Landing page berhasil diperbarui"
```

### Flow Konfigurasi Pricing AI Agent

```mermaid theme={null}
sequenceDiagram
    participant Admin as Admin
    participant UI as AI Settings Page
    participant API as Backend API
    participant DB as Database
    participant Agent as AI Agent Service

    Admin->>UI: Buka AI Agent Settings
    UI->>API: GET /api/ai-agent-settings
    API-->>UI: Return current settings

    Admin->>UI: Set credit_to_rupiah_rate = 15
    Admin->>UI: Set base_price_per_run = 2000
    Admin->>UI: Nonaktifkan allow_balance_payment
    Admin->>UI: Klik "Simpan"

    UI->>API: PUT /api/ai-agent-settings
    API->>API: Validasi: rate > 0, price >= 0
    API->>DB: UPDATE AIAgentSettings
    DB-->>API: Success
    API->>Agent: Invalidate pricing cache
    Agent-->>API: Cache cleared

    API-->>UI: 200 OK
    UI-->>Admin: Toast "Pengaturan AI berhasil disimpan"

    Note over Agent: Agent selanjutnya menggunakan<br/>pricing baru untuk<br/>perhitungan kredit
```

### Flow Konfigurasi Komisi Marketplace

```mermaid theme={null}
sequenceDiagram
    participant Admin as Admin
    participant UI as Marketplace Settings
    participant API as Backend API
    participant DB as Database
    participant Order as Order Service

    Admin->>UI: Buka Marketplace Commission Settings
    UI->>API: GET /api/marketplace-commission-settings
    API-->>UI: Return current settings

    Admin->>UI: Set commission_rate = 12%
    Admin->>UI: Set min_withdrawal = 50000
    Admin->>UI: Set withdrawal_fee = 2500
    Admin->>UI: Klik "Simpan"

    UI->>API: PUT /api/marketplace-commission-settings
    API->>API: Validasi: rate 0-100, min > 0
    API->>DB: UPDATE MarketplaceCommissionSettings
    DB-->>API: Success
    API->>Order: Notify rate change
    Order-->>API: Acknowledged

    API-->>UI: 200 OK
    UI-->>Admin: Toast "Komisi marketplace berhasil diperbarui"

    Note over Order: Transaksi berikutnya<br/>menggunakan komisi<br/>rate baru (12%)
```

## Enum Reference Tables — Settings Tambahan

### MenuAccessProfile.role

| Nilai | Deskripsi |
| - | - |
| `owner` | Pemilik perusahaan dengan akses penuh |
| `admin` | Administrator perusahaan |
| `supervisor` | Supervisor / kepala divisi |
| `store_admin` | Administrator toko / cabang |
| `stock_admin` | Administrator stok / gudang |
| `finance_admin` | Administrator keuangan |
| `hr_admin` | Administrator HR / SDM |
| `transaction_admin` | Administrator transaksi |
| `employee` | Karyawan biasa |

### MenuAccessProfile.dashboard\_type

| Nilai | Deskripsi |
| - | - |
| `owner` | Dashboard khusus owner dengan overview seluruh perusahaan |
| `admin` | Dashboard administrator umum |
| `supervisor` | Dashboard supervisor tim |
| `employee` | Dashboard karyawan standar (default) |
| `cashier` | Dashboard kasir dengan fokus POS |
| `finance` | Dashboard keuangan dengan laporan finansial |
| `hr` | Dashboard HR dengan data karyawan & absensi |
| `inventory` | Dashboard inventori dengan stok & gudang |

### CustomDashboardConfig.layout

| Nilai | Deskripsi |
| - | - |
| `grid` | Tata letak grid dengan widget yang dapat diposisikan bebas |
| `list` | Tata letak daftar vertikal |

### CustomDashboardConfig.widgets\[].widget\_type

| Nilai | Deskripsi |
| - | - |
| `chart` | Widget grafik (line, bar, pie, area) |
| `table` | Widget tabel data |
| `metric` | Widget metrik tunggal (angka besar) |
| `list` | Widget daftar item |
| `calendar` | Widget tampilan kalender |
| `forecast` | Widget prediksi/forecast berbasis AI |

### CustomDashboardConfig.widgets\[].chart\_type

| Nilai | Deskripsi |
| - | - |
| `line` | Grafik garis — cocok untuk tren waktu |
| `bar` | Grafik batang — cocok untuk perbandingan |
| `pie` | Grafik lingkaran — cocok untuk proporsi |
| `area` | Grafik area — cocok untuk volume kumulatif |

## RBAC Permission Table — Settings Tambahan

### MenuSettings

| Operasi | `user` | `admin` | Deskripsi |
| - | - | - | - |
| **Create** | ❌ | ✅ | Hanya admin platform yang bisa menambah menu |
| **Read** | ✅ | ✅ | Semua user bisa membaca (visibilitas diatur per field) |
| **Update** | ❌ | ✅ | Hanya admin platform yang bisa mengubah menu |
| **Delete** | ❌ | ✅ | Hanya admin platform yang bisa menghapus menu |

### MenuAccessProfile

| Operasi | `user` | `admin` (same company) | `admin` (other company) |
| - | - | - | - |
| **Create** | ❌ | ✅ | ❌ |
| **Read** | ✅ (own role) | ✅ | ❌ |
| **Update** | ❌ | ✅ | ❌ |
| **Delete** | ❌ | ✅ | ❌ |

### ShopSettings

| Operasi | `user` | `admin` (same company) | Deskripsi |
| - | - | - | - |
| **Create** | ❌ | ✅ | Hanya admin yang bisa membuat konfigurasi toko |
| **Read** | ✅ | ✅ | Semua anggota perusahaan bisa membaca |
| **Update** | ❌ | ✅ | Hanya admin perusahaan |
| **Delete** | ❌ | ✅ | Hanya admin perusahaan |

### HomeSettings

| Operasi | `user` | `admin` | Deskripsi |
| - | - | - | - |
| **Create** | ❌ | ✅ | Hanya admin platform |
| **Read** | ✅ | ✅ | Publik (tanpa autentikasi) |
| **Update** | ❌ | ✅ | Hanya admin platform |
| **Delete** | ❌ | ✅ | Hanya admin platform |

### AIAgentSettings

| Operasi | `user` | `admin` | Deskripsi |
| - | - | - | - |
| **Create** | ❌ | ✅ | Hanya admin platform |
| **Read** | ✅ | ✅ | Semua user bisa membaca (untuk transparansi pricing) |
| **Update** | ❌ | ✅ | Hanya admin platform |
| **Delete** | ❌ | ✅ | Hanya admin platform |

### ReferralSetting

| Operasi | `user` | `admin` | Deskripsi |
| - | - | - | - |
| **Create** | ❌ | ✅ | Hanya admin platform |
| **Read** | ✅ | ✅ | Semua user bisa membaca (untuk transparansi komisi) |
| **Update** | ❌ | ✅ | Hanya admin platform |
| **Delete** | ❌ | ✅ | Hanya admin platform |

### MarketplaceCommissionSettings

| Operasi | `user` | `admin` | Deskripsi |
| - | - | - | - |
| **Create** | ❌ | ✅ | Hanya admin platform |
| **Read** | ✅ | ✅ | Semua user bisa membaca |
| **Update** | ❌ | ✅ | Hanya admin platform |
| **Delete** | ❌ | ✅ | Hanya admin platform |

### CustomDashboardConfig

| Operasi | `user` | `admin` (own dashboard) | `admin` (other's dashboard) |
| - | - | - | - |
| **Create** | ✅ | ✅ | ✅ |
| **Read** | ✅ Own + Public | ✅ | ✅ (jika is\_public) |
| **Update** | ✅ Own | ✅ | ❌ |
| **Delete** | ✅ Own | ✅ | ❌ |

***

**Related Documentation**:

* [Home](/docs/core/home)
* [Workspace](/docs/core/workspace)
* [Dashboard](/docs/core/dashboard)


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