🔧 Bengkel Pintar ERP
Dokumentasi lengkap alur proses, diagram flow, dan approval workflow untuk seluruh modul sistem ERP manajemen bengkel otomotif multi-cabang.
Arsitektur Sistem
Gambaran besar sistem Bengkel Pintar ERP — stack teknologi, layar aplikasi, dan hubungan antar komponen utama.
🖥️ Tiga Lapisan Aplikasi
- 1bengkel-landing — Halaman marketing SaaS (Next.js, port 3001). Berisi fitur, harga, halaman demo, dan form permintaan demo yang terhubung ke backend via
POST /api/marketing/demo-request. - 2bengkel-admin — Aplikasi operasional utama (Next.js 16 + React 19, port 3000). 118 halaman, 5 grup role. Semua request ke backend via
Authorization: Bearer {token}. - 3bengkel-pintar-api — Backend Hono + Bun (port 4000). 19 modul, 100+ endpoint. Autentikasi JWT, RBAC, multi-cabang, double-entry accounting.
⚙️ Stack Teknologi
| Layer | Teknologi |
|---|---|
| Runtime API | Bun + Hono (TypeScript) |
| Frontend | Next.js 16, React 19, Tailwind v4 |
| Database | PostgreSQL + Prisma ORM |
| File Storage | MinIO (S3-compatible, self-hosted) |
| Auth | JWT dual-token (access 15m + refresh 7d) |
| Generate SPK, Invoice A4, Struk Termal | |
| Notifikasi | WhatsApp (channel notifikasi pelanggan) |
🏢 Konsep Multi-Cabang
- Setiap data transaksi (WO, stok, karyawan) terikat ke branchId.
- Role admin dapat melihat dan mengelola semua cabang.
- Role manager hanya dapat mengakses data cabang sendiri (branch-scoped).
- Harga jasa dapat di-override per cabang via BranchJasaPrice.
- Stok dikelola per cabang via BranchStock, transfer antar cabang memerlukan approval.
- Laporan cabang dapat dibandingkan via endpoint
GET /api/dashboard(branchComparison).
🌐 Arsitektur Aplikasi & Integrasi Komponen
Next.js · Port 3001
SaaS Marketing Site"] ADMIN["bengkel-admin
Next.js 16 + React 19
Port 3000"] end subgraph API["⚙️ Backend API — bengkel-pintar-api"] direction TB HONO["Hono Framework
Bun Runtime · Port 4000"] AUTH_MW["Auth Middleware
JWT Verify + RBAC"] MODULES["19 Route Modules
workorder · quotation · kasir
inventory · hcm · finance · operator"] HONO --> AUTH_MW --> MODULES end subgraph DATA["🗄️ Data Layer"] PRISMA["Prisma ORM"] PG["PostgreSQL
Database"] MINIO["MinIO
Object Storage
Port 9000/9001"] PRISMA --> PG end subgraph INTEGRATIONS["🔗 Integrasi"] PDF["PDF Generator
SPK · Invoice · Receipt"] WA["WhatsApp
Notifikasi"] REPORT["Laporan
Balance Sheet · P&L"] end LANDING -->|"Demo Request API"| HONO ADMIN -->|"REST API + JWT"| HONO MODULES --> PRISMA MODULES --> MINIO MODULES --> PDF MODULES --> WA MODULES --> REPORT style CLIENT fill:#dbeafe,stroke:#3b82f6 style API fill:#ede9fe,stroke:#8b5cf6 style DATA fill:#d1fae5,stroke:#10b981 style INTEGRATIONS fill:#fef3c7,stroke:#f59e0b
👥 Role Pengguna & Akses Modul
Full Access"] MGR["📊 Manager
Branch Scoped"] SA["🎧 Service Advisor
WO + Quotation"] MKN["🔧 Mekanik
Job Execution"] KSR["💰 Kasir
Payment + Invoice"] GDG["📦 Gudang
Inventory + PO"] OPR["📋 Operator
Booking + Checkin"] end subgraph MODULES["Akses Modul"] M1["Work Order"] M2["Quotation"] M3["Kasir"] M4["Inventory"] M5["HCM"] M6["Finance"] M7["Booking"] M8["Master Data"] end ADM --> M1 & M2 & M3 & M4 & M5 & M6 & M7 & M8 MGR --> M1 & M2 & M4 & M5 & M6 & M7 SA --> M1 & M2 MKN --> M1 KSR --> M3 GDG --> M4 OPR --> M7 style ADM fill:#fee2e2,stroke:#ef4444 style MGR fill:#dbeafe,stroke:#3b82f6 style SA fill:#d1fae5,stroke:#10b981 style MKN fill:#fef3c7,stroke:#f59e0b style KSR fill:#ede9fe,stroke:#8b5cf6 style GDG fill:#ccfbf1,stroke:#14b8a6 style OPR fill:#ffedd5,stroke:#f97316
Autentikasi & Manajemen User
Sistem login dengan JWT dual-token (access + refresh), reset password, dan manajemen user berbasis RBAC per cabang.
🔑 Mekanisme JWT Dual-Token
- 1User login → server mengembalikan accessToken (berlaku 15 menit) dan refreshToken (berlaku 7 hari).
- 2Setiap request API menyertakan
Authorization: Bearer {accessToken}di header. - 3Jika accessToken expired (401), frontend otomatis hit
POST /auth/refreshmenggunakan refreshToken untuk mendapat accessToken baru. - 4Jika refreshToken juga expired → user di-logout otomatis dan diredirect ke halaman login.
- !Login dibatasi 10 percobaan per 60 detik per IP (rate limiting) untuk mencegah brute force.
🔄 Redirect Berdasarkan Role (ROLE_REDIRECT)
| Role | Redirect Setelah Login |
|---|---|
| admin | /dashboard |
| manager | /dashboard |
| sa | /sa (Service Advisor) |
| mekanik | /mekanik |
| kasir | /kasir |
| gudang | /dashboard |
| operator | /operator |
🛡️ Manajemen User oleh Admin
- Admin dapat membuat user baru dan menetapkan role serta cabang.
- Admin dapat toggle status user (aktif/nonaktif) tanpa menghapus data.
- Admin dapat mengatur allowedPages[] untuk memberikan akses ke halaman tertentu di luar role default.
- Admin dapat mengatur deniedPages[] untuk memblokir halaman tertentu meski role memiliki izin.
- Reset password dapat dilakukan admin tanpa mengetahui password lama user.
- Semua RefreshToken direvoke otomatis saat password direset.
🔑 Alur Login & Token Management
admin→/dashboard
sa→/sa
mekanik→/mekanik else Gagal API-->>FE: 401 Unauthorized FE-->>U: Tampilkan error end Note over FE,API: Setiap request API FE->>API: Header: Authorization Bearer accessToken API->>API: Verify JWT + check permissions alt Token expired (401) FE->>API: POST /api/auth/refresh API-->>FE: accessToken baru FE->>API: Retry original request else Refresh expired FE->>FE: Logout + redirect /login end
🔄 Alur Reset Password
🛡️ Manajemen User & Permission (Admin)
📋 Struktur Data User & Token
Work Order (SPK — Surat Perintah Kerja)
Inti dari sistem operasional bengkel. Mengelola seluruh siklus servis kendaraan dari antrian masuk hingga kendaraan diserahkan ke pelanggan, termasuk penugasan mekanik, tracking pekerjaan per-item, dan pembayaran.
📋 6 Status Work Order
| Status | Artinya | Aktor |
|---|---|---|
| antrian | Kendaraan masuk, menunggu giliran diagnosa | SA / Sistem |
| diagnosa | SA dan mekanik memeriksa kendaraan, estimasi dibuat | SA |
| pengerjaan | Mekanik aktif mengerjakan job per item | Mekanik |
| quality_check | Pemeriksaan akhir hasil kerja sebelum diserahkan | Kepala Mekanik / SA |
| selesai | Kendaraan siap, menunggu pembayaran lunas | Sistem otomatis |
| diserahkan | Kendaraan sudah diserahkan ke pelanggan | SA |
💳 4 Status Pembayaran WO
| Status | Kondisi |
|---|---|
| belum | Belum ada pembayaran sama sekali |
| dp | Sudah bayar sebagian (down payment) |
| lunas | Pembayaran penuh, WO bisa diserahkan |
| tempo | Kredit — bayar belakangan sesuai kesepakatan |
WO hanya bisa berstatus diserahkan jika paymentStatus = lunas dan WO status = selesai.
⚙️ Job Tracking per Item
- Setiap WOItem (jasa atau parts) dapat memiliki satu WOJob yang di-assign ke mekanik tertentu.
- Mekanik dapat start → pause → resume → complete job dengan timer otomatis.
- Sistem mencatat estMinutes (estimasi) vs actualMinutes (aktual) untuk KPI.
- WO baru dapat masuk Quality Check jika semua WOJob sudah berstatus done.
- Mekanik dapat di-pause untuk request parts ke gudang, lalu resume setelah parts diterima.
👥 Aktor Terlibat
- SA — membuat SPK, assign mekanik, ubah status, serahkan kendaraan.
- Mekanik — mengambil job, tracking waktu, request parts.
- Kasir — menerima pembayaran, cetak invoice dan struk.
- Gudang — menyediakan parts yang di-request mekanik.
🔄 Lifecycle Work Order — Status Flow Lengkap
📝 Proses Pembuatan Work Order (SA Flow)
⚙️ Job Tracking — Alur Kerja Mekanik per Item
💳 Status Pembayaran Work Order
🗂️ Struktur Data Work Order (ERD)
Quotation / Estimasi Harga
Modul untuk membuat penawaran harga servis sebelum pekerjaan dimulai. Quotation yang disetujui pelanggan dapat langsung dikonversi menjadi Work Order.
📊 5 Status Quotation
| Status | Artinya |
|---|---|
| pending | Estimasi dibuat, menunggu konfirmasi pelanggan |
| approved | Pelanggan setuju, siap dikonversi ke SPK |
| rejected | Pelanggan menolak, penawaran tidak dilanjutkan |
| expired | Melewati tanggal validitas (validUntil) |
| converted | Sudah dikonversi menjadi Work Order aktif |
🔄 Proses Konversi ke SPK
- 1SA buat Quotation, tambahkan item jasa dan parts beserta harga.
- 2Quotation dikirim ke pelanggan via email, cetak, atau WhatsApp.
- 3Pelanggan bisa nego — SA update item/harga, lalu kirim ulang.
- 4Pelanggan setuju → status jadi approved.
- 5SA klik Convert → sistem buat WO baru, salin semua item, status WO: antrian.
- !Quotation yang sudah converted tidak bisa diubah lagi.
📋 Aturan Bisnis
- Quotation hanya bisa diedit selama berstatus pending.
- Tanggal validUntil diset saat pembuatan, sistem menandai expired otomatis setelah tanggal ini.
- Harga di Quotation tidak otomatis mengikuti perubahan harga master jasa — harga dikunci saat item ditambahkan.
- Setelah konversi, Quotation berstatus converted dan Work Order baru mendapat nomor SPK sendiri (
displayId). - Quotation yang rejected atau expired tidak dapat diaktifkan kembali, harus buat baru.
📊 Flow Status Quotation
🔄 Proses Quotation ke Work Order
Operator — Booking, Check-in & Follow-up
Modul front-desk untuk mengelola reservasi servis, penerimaan kendaraan, dan tindak lanjut pelanggan (servis berkala, pengingat STNK/asuransi, pelanggan tidak aktif).
📅 5 Status Booking
| Status | Artinya |
|---|---|
| scheduled | Booking dibuat, belum dikonfirmasi ke pelanggan |
| confirmed | Operator sudah konfirmasi jadwal ke pelanggan |
| arrived | Pelanggan sudah tiba, proses check-in dilakukan |
| no_show | Pelanggan tidak datang pada waktu yang dijadwalkan |
| cancelled | Booking dibatalkan oleh pelanggan atau operator |
📬 6 Tipe Follow-up Otomatis
| Tipe | Trigger |
|---|---|
servis_berkala | Km atau bulan interval servis sudah terlewati |
stnk_expired | Tanggal STNK kendaraan mendekati kadaluarsa |
insurance_expired | Asuransi kendaraan mendekati kadaluarsa |
inactive_customer | Pelanggan tidak servis lebih dari 3 bulan |
post_service | Survey kepuasan setelah servis selesai |
manual | Dibuat manual oleh operator |
🔄 Alur Status Follow-up
- 1PENDING — Follow-up masuk antrean operator.
- 2CONTACTED — Operator sudah menghubungi pelanggan via WA / Telepon.
- 3aSCHEDULED — Pelanggan mau booking servis, tanggal berikutnya dijadwalkan.
- 3bCOMPLETED — Pelanggan tidak perlu servis sekarang, follow-up selesai.
- 3cSKIPPED — Tidak relevan atau tidak bisa dihubungi, di-skip.
📅 Alur Booking & Penerimaan Kendaraan
📬 Alur Follow-up Pelanggan
Kasir & Pembayaran
Modul pengelolaan pembayaran, rekonsiliasi kas, dan pembuatan dokumen keuangan (invoice A4, struk termal). Mendukung multi-metode bayar dan sistem laci kas.
💳 5 Metode Pembayaran
| Metode | Keterangan |
|---|---|
| cash | Tunai — langsung dicatat ke laci kas aktif |
| transfer | Transfer bank — kasir input nomor referensi |
| debit_card | Kartu debit via mesin EDC |
| credit_card | Kartu kredit via mesin EDC |
| qris | Scan QR — terintegrasi via payment gateway |
🗄️ Laci Kas (Cash Drawer)
- 1Awal shift: kasir buka laci kas dan input saldo awal (opening balance).
- 2Setiap transaksi tunai otomatis tercatat: kas_masuk, kas_keluar, atau pembayaran_spk.
- 3Akhir shift: kasir tutup laci kas, input jumlah uang fisik yang dihitung.
- 4Sistem hitung selisih (difference) antara kas tercatat vs fisik untuk rekonsiliasi.
- !
Laci yang sudah closed tidak bisa dibuka ulang — harus buat laci baru.
📄 Dokumen yang Dicetak Kasir
| Dokumen | Format | Endpoint |
|---|---|---|
| Invoice Resmi | PDF A4 berlogo bengkel, detail item, total, PPn | GET /kasir/invoices/:id/pdf |
| Struk Kasir | PDF Thermal 80mm, ringkas untuk pelanggan | GET /kasir/invoices/:id/receipt |
| SPK / Work Order | PDF detail pekerjaan untuk mekanik | GET /api/spk/:id/pdf |
Invoice dan struk hanya bisa dicetak setelah WO berstatus selesai.
💳 Alur Pembayaran Work Order
🗄️ Manajemen Laci Kas (Cash Drawer)
🏦 Metode Pembayaran yang Didukung
Inventory & Manajemen Stok
Pengelolaan stok parts/sparepart per cabang, mutasi stok, transfer antar cabang, dan peringatan stok minimum. Setiap gerakan stok tercatat sebagai StockMovement.
📊 5 Tipe Stock Movement
| Tipe | Sumber | Efek |
|---|---|---|
masuk | PO diterima dari supplier | Stok bertambah (+qty) |
keluar | Pemakaian di Work Order / parts request | Stok berkurang (-qty) |
adjustment | Koreksi manual oleh gudang | Bisa +/- sesuai koreksi |
transfer_in | Menerima stok dari cabang lain | Stok bertambah (+qty) |
transfer_out | Mengirim stok ke cabang lain | Stok berkurang (-qty) |
⚠️ Low-Stock Alert
- Setiap part memiliki nilai minStock yang diset per cabang di
BranchStock. - Setiap kali stok bergerak, sistem cek: jika
stock <= minStock, part masuk daftar alert. - Alert tampil di Dashboard via endpoint
GET /api/parts/low-stock. - Gudang wajib menindaklanjuti dengan buat Purchase Request ke supplier.
- Setiap StockMovement menyimpan nilai stockAfter untuk audit trail historis.
🔄 Transfer Antar Cabang — 5 Status
| Status | Artinya |
|---|---|
| pending | Permintaan transfer dikirim, menunggu persetujuan cabang tujuan |
| approved | Manager cabang tujuan menyetujui transfer |
| in_transit | Barang sedang dalam perjalanan ke cabang tujuan |
| received | Barang diterima, stok kedua cabang diperbarui otomatis |
| rejected | Permintaan ditolak oleh cabang tujuan |
📊 Alur Pergerakan Stok (Stock Movement)
🔄 Transfer Stok Antar Cabang + Approval
Purchase Order & Purchase Request
Pengelolaan pembelian parts/sparepart ke supplier — dari permintaan pembelian (PR) oleh gudang/mekanik, approval, pembuatan PO, pengiriman, penerimaan, hingga pembayaran ke supplier.
📋 Purchase Request (PR)
- 1Gudang atau mekanik buat PR berisi daftar part yang dibutuhkan beserta alasan.
- 2PR masuk ke manager/admin untuk disetujui atau ditolak.
- 3PR yang disetujui dijadikan dasar pembuatan Purchase Order ke supplier.
- !PR yang ditolak harus dibuat ulang — tidak dapat diaktifkan kembali.
| Status PR | Artinya |
|---|---|
| pending | Menunggu persetujuan manager |
| approved | Disetujui, siap dibuatkan PO |
| rejected | Ditolak dengan catatan alasan |
| fulfilled | Barang sudah diterima dari supplier |
🛒 Purchase Order (PO) — 5 Status
| Status | Artinya | Bisa Diedit? |
|---|---|---|
| draft | Sedang disiapkan oleh gudang | Ya |
| dikirim | Sudah dikirim ke supplier | Tidak |
| diterima | Barang tiba, stok otomatis bertambah | Tidak |
| dibayar | Pembayaran ke supplier lunas | Tidak |
| batal | PO dibatalkan | Tidak |
📦 Integrasi dengan Stok
- Saat PO berstatus diterima via
POST /purchase-orders/:id/receive, sistem otomatis membuat StockMovement tipemasukuntuk setiap item PO. - BranchStock cabang yang menerima akan bertambah sejumlah qty yang diterima.
- Nilai stockAfter dicatat di setiap StockMovement untuk keperluan audit trail.
- Jika PO memiliki nominal besar, akan di-routing ke Approval Workflow sebelum bisa dikirim ke supplier.
🛒 Alur Purchase Request → Purchase Order
📊 Status Flow Purchase Order
Parts Request — Permintaan Parts dari Mekanik
Alur permintaan parts dari mekanik saat mengerjakan Work Order, approval oleh gudang, dan penyerahan fisik parts ke mekanik.
🔩 4 Status Parts Request
| Status | Artinya | Aktor |
|---|---|---|
| pending | Request dikirim, menunggu review gudang | Sistem |
| approved | Gudang menyetujui, sedang menyiapkan parts | Gudang |
| rejected | Stok tidak ada atau permintaan tidak valid | Gudang |
| delivered | Parts sudah diserahkan fisik ke mekanik, stok terpotong | Gudang |
📋 Aturan Bisnis
- Setiap request wajib mencantumkan referensi Work Order agar bisa di-tracking per SPK.
- Gudang memutuskan: jika stok ada → approve; jika tidak ada → reject dan buat PR ke supplier.
- Saat status berubah ke delivered, sistem otomatis membuat StockMovement tipe
keluar— stok cabang berkurang sejumlah qty yang diminta. - Mekanik bisa menjeda job (pause) sambil menunggu parts, lalu resume setelah parts diterima.
- Jika request ditolak, mekanik harus buat request baru dengan justifikasi alternatif.
🔩 Alur Parts Request
📋 Antrian Mekanik
HCM — Human Capital Management
Pengelolaan data karyawan, absensi harian, dan evaluasi performa mekanik melalui sistem KPI yang terukur (SPK selesai, on-time rate, return rate, customer rating, akurasi parts).
👤 Status Karyawan
| Status | Artinya |
|---|---|
| aktif | Karyawan aktif bekerja, bisa di-assign ke WO dan job |
| tidak_aktif | Sementara nonaktif (cuti panjang, dll) |
| resign | Karyawan sudah keluar — soft delete, data historis tetap tersimpan |
| Status Absensi | Keterangan |
|---|---|
| hadir | Check-in dan check-out tercatat normal |
| izin | Izin resmi dengan dokumen |
| sakit | Sakit dengan/tanpa surat dokter |
| alpha | Tidak hadir tanpa keterangan |
📊 5 Komponen KPI Mekanik
| Komponen | Cara Hitung | Bobot |
|---|---|---|
| SPK Done | Jumlah SPK selesai / target bulan | Produktivitas |
| On-Time Rate | % job selesai tepat waktu vs estimasi | Ketepatan |
| Return Rate | % SPK yang kembali karena keluhan (lebih rendah = lebih baik) | Kualitas |
| Customer Rating | Rata-rata rating dari pelanggan post-service | Kepuasan |
| Parts Accuracy | % request parts yang sesuai tanpa retur/lebih | Efisiensi |
Total KPI Score dipakai sebagai dasar penghitungan bonusKPI di modul Payroll. Satu record per mekanik per bulan (unique: empId + month).
🔩 Spesialisasi Mekanik
- Mesin / Engine — overhaul, tune up, timing belt, dll.
- AC Mobil — service AC, freon, kompresor.
- Kelistrikan — aki, alternator, kabel, ECU.
- Body & Cat — ketok, las, pengecatan.
- General — ganti oli, ban, rem, filter — semua mekanik bisa.
Spesialisasi dipakai SA saat assign mekanik ke WO Item untuk memastikan keahlian yang tepat.
👤 Manajemen Karyawan
⏰ Absensi — Check-in / Check-out
📊 KPI Mekanik — Komponen & Kalkulasi
Finance & Akuntansi
Sistem akuntansi double-entry lengkap dengan chart of accounts, jurnal, buku besar, periode fiskal, anggaran (budget), aset tetap, dan laporan keuangan otomatis (Balance Sheet, P&L, Trial Balance).
📒 Prinsip Double-Entry & Status Jurnal
- Setiap transaksi keuangan dibuat sebagai JournalEntry dengan minimal dua baris (JournalLine): satu sisi Debit, satu sisi Kredit.
- Sistem menolak jurnal jika total Debit ≠ total Kredit — wajib balance.
| Status | Artinya |
|---|---|
| draft | Jurnal masih bisa diedit, belum mempengaruhi saldo akun |
| posted | Jurnal dikunci, LedgerEntry dibuat, saldo akun diperbarui |
| voided | Jurnal dibatalkan — sistem buat entry reversal otomatis |
📅 Fiscal Period — Locking Periode
- 1Admin buat periode fiskal baru setiap bulan — status awal: OPEN.
- 2Selama periode OPEN, jurnal bisa diposting ke periode tersebut.
- 3Akhir bulan: admin tutup periode (
PATCH /periods/:id/close). - !Periode CLOSED tidak bisa dibuka kembali. Jurnal baru tidak dapat diposting ke periode yang sudah tutup — mencegah manipulasi laporan historis.
- 4Sistem otomatis buat closing entries — saldo Revenue dan Expense dipindah ke Retained Earnings.
📊 5 Tipe Akun (Chart of Accounts)
| Tipe | Contoh Akun | Laporan |
|---|---|---|
| asset | Kas, Bank, Piutang, Stok | Balance Sheet |
| liability | Hutang Usaha, Hutang Pajak | Balance Sheet |
| equity | Modal, Retained Earnings | Balance Sheet |
| revenue | Pendapatan Jasa, Pendapatan Parts | P&L / Income Statement |
| expense | HPP, Gaji, Sewa, Listrik | P&L / Income Statement |
Akun dengan flag isCashBank = true dipakai sebagai acuan laporan Arus Kas.
📈 Jurnal Otomatis dari Transaksi
- Pembayaran WO (Kasir) — Debit: Kas/Bank; Kredit: Pendapatan Jasa + Pendapatan Parts.
- Pembelian PO — Debit: Stok Parts; Kredit: Hutang Usaha / Kas.
- Penggajian (Payroll) — Debit: Beban Gaji; Kredit: Kas / Hutang Gaji.
- Penyesuaian Manual — Dibuat langsung oleh akuntan via modul Jurnal.
- Semua jurnal otomatis dibuat dengan status posted langsung (tanpa melalui draft).
📒 Alur Jurnal Akuntansi Double-Entry
📅 Manajemen Periode Fiskal
📈 Chart of Accounts & Laporan Keuangan
Aset Tetap & Penyusutan
Pencatatan aset tetap bengkel (lift, kompresor, kendaraan operasional, inventaris kantor), perhitungan penyusutan otomatis metode Garis Lurus (Straight-Line), serta pencatatan jurnal akuntansi yang dipicu sistem setiap awal bulan secara otomatis.
📐 Formula Penyusutan Garis Lurus
Harga Perolehan: Rp 45.000.000
Nilai Sisa: Rp 5.000.000
Masa Manfaat: 10 tahun (120 bulan)
Penyusutan = (45jt − 5jt) / 120 = Rp 333.333/bulan
📒 3 Akun Utama per Aset
| Field | Akun | Tipe |
|---|---|---|
accountId | Aset Tetap (1501–1504) | Asset |
accDepAccountId | Akumulasi Penyusutan (1502) | Asset contra |
depExpAccountId | Beban Penyusutan (6006) | Expense |
| Kode Akun | Nama |
|---|---|
| 1501 | Peralatan Bengkel |
| 1502 | Akumulasi Penyusutan |
| 1503 | Kendaraan Operasional |
| 1504 | Inventaris Kantor |
| 6006 | Beban Penyusutan |
| 4500 | Keuntungan Pelepasan Aset |
| 6500 | Kerugian Pelepasan Aset |
⚙️ Aturan Bisnis Penting
- Penyusutan berjalan otomatis via CRON setiap tanggal 1 untuk semua aset aktif (
isActive = true). - Penyusutan berhenti ketika
bookValue <= salvageValue— nilai buku tidak boleh turun di bawah nilai sisa. - Nilai buku (
bookValue) =purchaseCost − accumulatedDepreciation, diperbarui setiap bulan. - Setiap penyusutan bulanan otomatis membuat JournalEntry dengan tipe
depreciationdan statusposted. - Aset yang di-dispose di-set
isActive = falsedandisposedAtdiisi, penyusutan berhenti otomatis. - Disposal aset menghasilkan laba atau rugi pelepasan yang dicatat sebagai jurnal tersendiri.
🏭 Kategori Aset Bengkel
| Kategori | Contoh Aset | Masa Manfaat |
|---|---|---|
| Peralatan Bengkel | Lift hidrolik, kompresor, scanner ECU | 7–10 tahun |
| Kendaraan | Pick-up operasional, motor kurir | 5–8 tahun |
| Inventaris Kantor | Komputer, printer, meja kasir | 4–5 tahun |
| Bangunan | Gedung, pos satpam | 20–40 tahun |
🔄 Lifecycle Aset Tetap — Dari Pembelian hingga Disposal
📊 Simulasi Penyusutan Bulanan — Garis Lurus
💼 Jurnal Pelepasan Aset (Disposal) — Laba vs Rugi
🗂️ Struktur Data FixedAsset (ERD)
⏰ Alur Cron Penyusutan Otomatis (Tanggal 1 Setiap Bulan)
📈 Dampak Penyusutan ke Laporan Keuangan
Approval Workflow — Multi-Level Approval
Sistem persetujuan bertingkat yang fleksibel untuk berbagai modul (PO, PR, Payroll, Transfer Stok). Mendukung konfigurasi level approval, filter berdasarkan nominal, dan jenis approver (user/role).
🏗️ Konsep ApprovalRule
- module — modul yang diatur (PO, PR, Transfer, Payroll, Quotation).
- minAmount / maxAmount — rule berlaku hanya jika nominal transaksi berada di rentang ini. Contoh: rule khusus PO senilai Rp 10jt–50jt.
- applyToDraft — jika true, approval dibutuhkan bahkan sebelum dokumen di-finalize.
- isActive — rule bisa dinonaktifkan tanpa dihapus.
🔢 Level Approval & Tipe Persetujuan
| requireType | Artinya |
|---|---|
| any | Cukup satu approver di level ini yang menyetujui — request naik ke level berikutnya |
| all | Semua approver di level ini harus menyetujui sebelum naik ke level berikutnya |
- Approver bisa berupa user spesifik (userId) atau role (semua user dengan role tersebut bisa approve).
- Jika satu level di-reject, seluruh ApprovalRequest langsung ditolak — tidak perlu konfirmasi level lain.
- Request yang disetujui semua level → status approved, transaksi asal dapat dilanjutkan.
🔄 Cara Kerja Approval Check
- 1Sistem query
GET /api/approval/check?module=PO&amount=25000000untuk cek apakah transaksi perlu approval. - 2Jika perlu, sistem buat ApprovalRequest dan set
currentLevel = 1. - 3Approver Level 1 mendapat notifikasi, lalu submit keputusan via
POST /api/approval/decide. - 4Jika disetujui dan masih ada level berikutnya,
currentLevelnaik ke level 2. - 5Setelah semua level approve → ApprovalRequest berstatus approved, transaksi dilanjutkan.
🏗️ Konfigurasi Approval Rule
🔄 Alur Proses Approval Request
🗂️ ERD Sistem Approval
📋 Modul yang Menggunakan Approval
RBAC — Role-Based Access Control
Sistem izin akses berlapis: role sistem bawaan (admin, manager, sa, mekanik, kasir, gudang, operator) + custom dynamic role per cabang, dengan permission per resource dan override per user (allowedPages/deniedPages).
🛡️ 3 Lapisan Permission
- 1deniedPages[] — Pemblokiran per user. Jika route ada di sini, akses ditolak meski role punya izin. Dicek pertama kali.
- 2allowedPages[] — Pengecualian per user. Jika route ada di sini, akses diberikan meski role tidak punya izin. Dicek kedua.
- 3Role Permission — Default akses berdasarkan role sistem atau custom role. Dicek terakhir.
🔑 4 Operasi per Resource
| Operasi | HTTP Method | Contoh |
|---|---|---|
| canView | GET | Lihat daftar WO |
| canCreate | POST | Buat WO baru |
| canEdit | PUT / PATCH | Update status WO |
| canDelete | DELETE | Hapus item WO |
Permission diset per resource (contoh: workorder, inventory, finance) di RolePermission, baik untuk role sistem maupun custom role.
👥 7 Role Sistem (Built-in)
| Role | Scope | Akses Utama |
|---|---|---|
| admin | Semua cabang | Full — semua modul |
| manager | 1 cabang | Full — cabang sendiri |
| sa | 1 cabang | WO, Quotation, Customer |
| mekanik | 1 cabang | Job, Parts Request |
| kasir | 1 cabang | Pembayaran, Cash Drawer |
| gudang | 1 cabang | Inventory, PO, Transfer |
| operator | 1 cabang | Booking, Check-in, Follow-up |
🔐 Hirarki Permission Check
👥 Matrix Role × Modul Akses
Master Data
Data referensi yang menjadi pondasi seluruh transaksi — jasa bengkel, paket servis, parts, supplier, metode bayar, kendaraan, dan pengaturan per cabang.
📋 Hierarki Master Jasa
- 1Kategori Jasa — Pengelompokan layanan (Tune Up, AC, Rem, Kelistrikan, dll.).
- 2Master Jasa — Item layanan spesifik dengan harga dasar nasional dan estimasi waktu (
estMin). - 3BranchJasaPrice — Override harga per cabang. Jika ada, harga ini dipakai; jika tidak ada, pakai harga dasar.
- 4Service Package — Bundel jasa + parts dalam satu paket harga (misal: Paket Servis Berkala 10.000 km).
📦 Hierarki Master Parts
- 1Kategori Part — Pengelompokan (Filter, Oli, Kampas Rem, Busi, dll.).
- 2Master Part — Data global part: kode, SKU, harga beli, harga jual, brand, supplier default.
- 3BranchStock — Stok aktual per cabang +
minStockalert threshold per cabang.
⚙️ Setting Penting Per Cabang
| Setting | Konfigurasi |
|---|---|
| Penomoran | Prefix SPK (SPK-JKT-) dan Invoice (INV-JKT-) per cabang |
| Pajak | PPN default 11%, bisa dioverride per cabang |
| Metode Bayar | Aktifkan/nonaktifkan metode per cabang |
| Jam Operasional | Disimpan sebagai JSON (operHours) per hari |
| Bay / Lift | Status: available / occupied / maintenance |
| Department | Struktur organisasi per cabang (unique: branchId + name) |
🗂️ Peta Master Data
💰 Harga Jasa — Global vs Per-Cabang
Laporan & Dashboard
Pusat analitik real-time untuk monitoring operasional bengkel — dari SPK harian, utilitas mekanik, stok kritis, perbandingan cabang, hingga laporan keuangan lengkap.
📊 Dashboard Metrics — GET /api/dashboard
📑 Laporan yang Tersedia
End-to-End — Alur Sistem Lengkap
Gambaran alur transaksi dari pelanggan datang hingga laporan keuangan tercatat secara otomatis.
🔄 Alur Transaksi End-to-End Bengkel Pintar
Setup Awal & Prasyarat
Data master dan akun yang harus tersedia sebelum memulai pengujian.
👤 Akun Testing yang Dibutuhkan
| Role | Email Contoh | Akses Utama |
|---|---|---|
| admin | admin@bengkel.test | Semua modul |
| manager | manager@bengkel.test | Semua kecuali user management |
| sa | sa@bengkel.test | SPK, Booking, CRM, Quotation |
| mekanik | mekanik@bengkel.test | Antrian, Job, Parts request |
| kasir | kasir@bengkel.test | Pembayaran, Cash drawer |
| gudang | gudang@bengkel.test | Inventaris, PR approval |
| operator | operator@bengkel.test | Check-in, Booking, Status WO |
📦 Data Master yang Harus Ada
- Minimal 1 cabang aktif
- Minimal 1 Bay tersedia
- Minimal 1 data Jasa (service type)
- Minimal 1 data Part dengan stok > 0
- Minimal 1 Pelanggan + Kendaraan
- Metode Bayar: Tunai, Transfer, Kartu
- COA Finance sudah dikonfigurasi
Autentikasi & Manajemen User
Login, token refresh, reset password, buat user, nonaktifkan akun, rate limiting.
Login Valid — redirect sesuai role
- 1Buka
/login, masukkan email dan password valid - 2Klik Login
- Redirect sesuai role: admin/manager →
/dashboard, kasir →/kasir, mekanik →/mekanik/antrian - Token tersimpan di cookie/storage
- Header Topbar menampilkan nama dan initials user
Token Expired → Auto Refresh tanpa logout paksa
- 1Login, tunggu 15 menit (access token TTL)
- 2Buka halaman baru atau klik navigasi
Forgot Password — email link, token sekali pakai
- 1Buka
/forgot-password, masukkan email valid - 2Cek inbox email
- 3Klik link reset → isi password baru → submit
- Email berisi link reset (berlaku 1 jam)
- API tidak mengembalikan token di response (security)
- Token ditandai
used: truesetelah dipakai — tidak bisa dipakai ulang - Semua refresh token lama di-revoke → force re-login di device lain
Buat User Baru → welcome email + efek ke modul lain
- 1Admin → Settings → Users → Tambah User
- 2Isi nama, email, role, cabang, password sementara → Simpan
- Role
mekanik: user muncul di dropdown assign mekanik SPK - Role
kasir: user bisa membuka shift kasir
Nonaktifkan User → session di device lain mati
- 1User A sedang login di device lain
- 2Admin toggle inactive pada User A
/login.Rate Limiting Login — 429 setelah 10 percobaan
- 1Lakukan 11 kali percobaan login gagal dalam 60 detik
429 Too Many Requests.Golden Path End-to-End
Alur bisnis utama: Booking → Check-in → SPK → Mekanik → Parts → Kasir → Diserahkan. Melibatkan semua modul secara berurutan.
🔄 Urutan Alur
↓
OPERATOR → Check-in (buat SPK, assign bay)
↓
SA → Tambah item jasa + part, assign mekanik
↓
MEKANIK → Mulai → selesai job
↓
GUDANG → Approve parts request (jika perlu)
↓
SA/MANAGER → Quality check → selesai
↓
KASIR → Proses pembayaran lunas
↓
KASIR → Status → diserahkan
↓
[Efek: stok -1, jurnal keuangan, CRM update, bay free, audit log]
📋 TC-FLOW-01: Detail Step-by-Step
| # | Role | Aksi | Expected & Efek Samping |
|---|---|---|---|
| 1 | operator | Buat booking H-1, customer A, kendaraan B, jam 09:00 | Status = scheduled. Email konfirmasi terkirim. WS booking:created |
| 2 | operator | Customer datang → konfirmasi booking | Status = confirmed |
| 3 | operator | Check-in: pilih pelanggan, kendaraan, odometer, bay | SPK dibuat SPK-YYYYMM-XXXX, status = antrian. Bay = occupied. lastVisit diperbarui. WS wo:created + bay:occupied |
| 4 | sa | Tambah item: Tune Up Rp 150.000 + Filter Oli Rp 50.000 qty 1 | subtotal=200.000, PPn 11%=22.000, total=222.000. Job otomatis untuk item jasa |
| 5 | sa | Assign mekanik ke SPK | MechanicAssignment dibuat. Job.employeeId terisi |
| 6 | sa | Status → pengerjaan | Validasi: semua job harus ada mekanik. WS wo:status_changed |
| 7 | mekanik | Klik "Mulai" pada job Tune Up | Job status = running, startedAt terisi. WS wo:job_started |
| 8 | mekanik | Klik "Selesai" pada job | Job = done, actualMinutes dihitung. WS wo:job_done |
| 9 | sa | Status → quality_check | Validasi: semua job harus done. Error jika ada yang belum. WS wo:status_changed |
| 10 | sa | Status → selesai | WS wo:ready_to_pay → kasir. Email: Vehicle Ready + WhatsApp ke customer |
| 11 | kasir | Terima notifikasi → buka daftar antrian bayar | SPK muncul dengan total tagihan |
| 12 | kasir | Bayar Tunai Rp 222.000 | paymentStatus = lunas. Journal keuangan dibuat. WS wo:paid. Email: Invoice |
| 13 | kasir | Status → diserahkan | Validasi: harus lunas. totalSpend +222.000. Bay = available. WS bay:free |
| 14 | admin | Cek Audit Log | Semua aksi tercatat: create WO, status changes, payment, assignment |
| 15 | admin | Cek Finance → Jurnal | Journal entry otomatis dari payment muncul (Dr Kas / Cr Pendapatan) |
| 16 | admin | Cek Inventaris → Mutasi Stok | Stok Filter Oli berkurang 1. Movement tipe keluar dibuat |
| 17 | admin | Cek CRM → Pelanggan A | totalSpend bertambah, lastVisit diperbarui, riwayat servis muncul |
Work Order (SPK) — Detail
Validasi transisi status, kalkulasi total, blokir kondisi tidak valid, cetak PDF.
Transisi Status Tidak Valid
- 1Buat SPK status
antrian - 2Coba langsung ubah ke
diserahkan
Blokir quality_check jika Job Belum Selesai
- 1SPK status
pengerjaandengan 2 job - 2Mekanik selesaikan hanya 1 job
- 3SA ubah status →
quality_check
Blokir diserahkan jika Belum Lunas
- 1SPK status
selesai, paymentStatus =dp - 2Ubah status →
diserahkan
Hitung Ulang Total saat Item Berubah
| Aksi | Subtotal | PPn | Total |
|---|---|---|---|
| qty=2, price=100rb, disc=0% | 200.000 | 22.000 | 222.000 |
| Update disc=10% | 180.000 | 19.800 | 199.800 |
| + item baru 50rb | 230.000 | 25.300 | 255.300 |
| Hapus item pertama | 50.000 | 5.500 | 55.500 |
Status Flow yang Valid
| Dari | Ke (boleh) | Syarat |
|---|---|---|
| antrian | diagnosa | - |
| diagnosa | pengerjaan | Semua job punya mekanik |
| pengerjaan | quality_check | Semua job done |
| quality_check | selesai | - |
| selesai | diserahkan | paymentStatus = lunas |
Cetak SPK (PDF)
Kasir & Pembayaran
Pembayaran penuh, DP, pelunasan, invoice, efek ke keuangan dan CRM.
Pembayaran Penuh (Lunas)
- 1Kasir pilih SPK dari antrian bayar
- 2Jumlah = total tagihan, metode: Tunai → Submit
paymentStatus= lunas- Payment record type =
full. Invoice record dibuat - Journal entry: Dr. Kas / Cr. Pendapatan Jasa + Part + PPN
- WS wo:paid. Email Invoice ke customer
DP → Pelunasan (2 Transaksi)
- 1Bayar 50% dari total → type =
dp - 2Bayar sisa 50% → type =
pelunasan
- Setelah DP:
paymentStatus= dp. Belum bisa diserahkan - Setelah pelunasan: akumulasi = total. Status = lunas
- Journal entry terpisah untuk masing-masing transaksi
Pembayaran Melebihi Total
- 1Masukkan jumlah melebihi total tagihan → submit
Cetak Invoice
Cash Drawer & Shift Kasir
Buka/tutup shift, saldo kas, selisih, blokir payment tanpa shift aktif.
Buka Shift
- 1Kasir → Shift → Buka Shift, isi saldo awal kas
open. WS cash:drawer_opened. Hanya 1 shift aktif per branch.Tutup Shift → Hitung Selisih
- 1Klik Tutup Shift, isi saldo akhir (hitung fisik)
Payment Tanpa Shift Aktif
- 1Kasir proses pembayaran saat tidak ada shift aktif
Saldo Kas Real-Time saat Shift
Mekanik — Antrian & Pengerjaan Job
Isolasi antrian per mekanik, timer pengerjaan, pause/resume, trigger WS.
Antrian Terisolasi per Mekanik
waiting, running, paused, done terlihat.Mulai Job → startedAt & WS
- 1Klik "Mulai" pada job
waiting
running. startedAt terisi. WS wo:job_started. SA terima notifikasi.Pause & Resume — Akumulasi Waktu
- 1Job
running→ Pause - 2Resume
Selesaikan Job → Trigger wo:ready_to_pay
- 1Job terakhir di SPK → Klik Selesai
done. actualMinutes dihitung. WS wo:job_done. Jika semua job done → WS wo:ready_to_pay ke kasir.Parts Request (Mekanik → Gudang)
Create, approve/reject, efek ke stok, email notification, low stock trigger.
Buat Parts Request → Email ke Gudang/Manager
pending. WS parts:requested → gudang. Email PR Approval ke semua gudang/manager di branch.Approve → Stok Berkurang + Low Stock Check
approved. Stok −qty. Movement tipe keluar. WS parts:approved → mekanik. Jika stok ≤ minStock → WS stock:low + email alert.Reject → Stok Tidak Berubah
rejected. Stok tidak berubah. WS parts:rejected + alasan ke mekanik.Approve dengan Stok = 0
pending.Inventaris — Stok, Mutasi, Transfer
Masuk/keluar/adjustment, transfer antar cabang, alert minimum stok.
Penerimaan Stok (Masuk)
masuk. stockAfter terisi nilai baru.Adjustment — Set Nilai Absolut
stockAfter = 12.Keluar Melebihi Stok Tersedia
Transfer Stok Antar Cabang (3 Fase)
| Fase | Status | Efek Stok |
|---|---|---|
| Buat transfer Branch A→B qty=5 | pending | Tidak berubah |
| Admin approve | approved | Branch A −5, movement transfer_out |
| Branch B konfirmasi terima | received | Branch B +5, movement transfer_in |
Purchase Order (PO)
Buat, approve, receive, return ke supplier. Efek ke stok dan finance AP.
Alur PO: Draft → Approved → Received
| Step | Status | Efek |
|---|---|---|
| Buat PO + item | draft | displayId tergenerate |
| Submit | submitted | Approval flow aktif |
| Manager approve | approved | - |
| Receive barang | received | Stok +qty, Movement masuk, AP bertambah |
Return ke Supplier
CRM — Pelanggan, Kendaraan, Followup
Registrasi, loyalty tier, followup otomatis, STNK expired, service reminder email.
Registrasi Pelanggan + Kendaraan
loyaltyTier = bronze, totalSpend = 0. Vehicle terhubung ke customer. Kendaraan muncul di dropdown check-in.totalSpend Update setelah SPK Lunas
lastVisit diperbarui, totalSpend bertambah, riwayat servis muncul di profil.Loyalty Tier Naik (Cron)
| totalSpend | Tier |
|---|---|
| < 1.000.000 | Bronze |
| 1 jt – 4,9 jt | Silver |
| 5 jt – 14,9 jt | Gold |
| ≥ 15 jt | Platinum |
Followup Otomatis (Inactive + STNK)
- Pelanggan tidak berkunjung > 6 bulan → followup tipe
inactive_customer - Kendaraan STNK expired → followup tipe
stnk_expired
Service Reminder Email (Cron 09:00)
HCM — Karyawan, Absensi, KPI, Payroll
Tambah karyawan, absensi harian, input KPI, proses payroll dengan jurnal otomatis.
Tambah Karyawan → Muncul di Dropdown Mekanik
Absensi Clock In / Clock Out
hadir. Clock Out: jam keluar tersimpan, durasi dihitung, keterlambatan dicatat.Payroll → Jurnal Keuangan Otomatis
Keuangan (Finance)
COA, jurnal manual/otomatis, neraca balanced, cashflow, budget vs aktual, fiscal period lock.
Jurnal Manual — Harus Balanced
Jurnal Otomatis dari Payment SPK
| Akun | Debit | Kredit |
|---|---|---|
| Kas / 1100 | 222.000 | - |
| Pendapatan Jasa / 4100 | - | porsi jasa |
| Pendapatan Parts / 4200 | - | porsi parts |
| PPN Keluaran / 2300 | - | 22.000 |
Neraca — Total Aset = Kewajiban + Ekuitas
Fiscal Period Lock
- 1Admin tutup periode bulan lalu
- 2Coba buat jurnal dengan tanggal bulan tsb
Notifikasi Real-Time (WebSocket + Email)
17 WS event types, 8 email triggers, koneksi indikator, routing ke role yang tepat.
📡 WebSocket Events
| Event | Trigger | Target |
|---|---|---|
| wo:created | Check-in buat SPK | Branch |
| wo:status_changed | Status transition | Branch |
| wo:job_started | Mekanik mulai job | Branch |
| wo:job_done | Mekanik selesai job | Branch |
| wo:ready_to_pay | Semua job done | role:kasir |
| wo:paid | Payment lunas | Branch |
| parts:requested | Mekanik buat PR | role:gudang |
| parts:approved | Gudang approve PR | role:mekanik |
| parts:rejected | Gudang reject PR | role:mekanik |
| booking:created | Buat booking | Branch |
| bay:occupied | Check-in assign bay | Branch |
| bay:free | WO diserahkan | Branch |
| stock:low | Stok ≤ minStock | role:gudang |
| stock:transfer | Transfer stok | Branch |
| cash:drawer_opened | Buka shift | Branch |
| cash:drawer_closed | Tutup shift | Branch |
📧 Email Triggers
| Trigger | Penerima | |
|---|---|---|
| Welcome | Admin buat user baru | User baru |
| Reset Password | Forgot password | User |
| Booking Conf. | Booking dibuat | Customer |
| Invoice | Payment lunas | Customer |
| Vehicle Ready | WO → selesai | Customer |
| Service Reminder | Cron 09:00, 3 bln | Customer |
| Low Stock Alert | Stok ≤ minStock | Manager/Admin |
| PR Approval | Mekanik buat PR | Gudang/Manager |
WS Connection Indicator
Routing WS ke Role yang Tepat
- wo:ready_to_pay hanya kasir yang terima
- parts:requested hanya gudang yang terima
- parts:approved/rejected hanya mekanik yang terima
- stock:low hanya gudang yang terima
Email Booking Confirmation (< 30 detik)
Email Invoice + Vehicle Ready setelah Lunas/Selesai
- Payment lunas → invoice otomatis ke email customer
- WO → selesai → "Kendaraan Siap" ke email customer
- Jika customer tidak punya email → tidak error, silent skip
RBAC & Kontrol Akses Per Role
Isolasi role, branch scope, custom role, page-level ACL.
🗂️ Matriks Akses Fitur per Role
| Fitur | admin | manager | sa | mekanik | kasir | gudang | operator |
|---|---|---|---|---|---|---|---|
| Buat SPK | ✓ | ✓ | ✓ | − | − | − | ✓ |
| Proses Pembayaran | ✓ | ✓ | − | − | ✓ | − | − |
| Approve PO | ✓ | ✓ | − | − | − | − | − |
| Approve Parts Request | ✓ | ✓ | − | − | − | ✓ | − |
| Buat User | ✓ | − | − | − | − | − | − |
| Lihat Finance / Jurnal | ✓ | ✓ | − | − | − | − | − |
| Mutasi Stok Manual | ✓ | ✓ | − | − | − | ✓ | − |
| Dashboard Konsolidasi | ✓ | ✓ | − | − | − | − | − |
Kasir Tidak Bisa Akses Finance
- 1Login kasir → akses URL
/finance/jurnallangsung
Mekanik Hanya Lihat Job Sendiri
Manager Terbatas pada Branch Sendiri
branchScope middleware memfilter otomatis di API.Custom Role + Page-Level ACL
can('finance', 'view') = false jika tidak diberi permission.deniedPages=['/finance'] pada manager B → akses /finance ditolak meski role normalnya bisa.Matriks Efek Lintas Modul
Setiap aksi kunci dan modul mana saja yang ikut terpengaruh secara otomatis.
| Aksi | WO | Stok | Finance | CRM | Bay | WS Event | Audit | |
|---|---|---|---|---|---|---|---|---|
| Check-in (buat SPK) | Create | − | − | lastVisit | Occupied | wo:created | − | ✓ |
| Tambah item Part ke SPK | Recalc | − | − | − | − | − | − | ✓ |
| Assign Mekanik | ✓ | − | − | − | − | − | − | ✓ |
| WO → pengerjaan | ✓ | − | − | − | − | wo:status_changed | − | ✓ |
| Job mulai | startedAt | − | − | − | − | wo:job_started | − | − |
| Job selesai | done | − | − | − | − | wo:job_done | − | − |
| Semua job selesai | ✓ | − | − | − | − | wo:ready_to_pay → kasir | − | − |
| WO → selesai | ✓ | − | − | − | − | wo:status_changed | Vehicle Ready | ✓ |
| Payment Lunas | payStatus | − | Journal | totalSpend | − | wo:paid | Invoice | ✓ |
| WO → diserahkan | ✓ | − | − | lastVisit | Free | bay:free | − | ✓ |
| Parts Request create | − | − | − | − | − | parts:requested → gudang | PR Approval | − |
| Parts Request approve | − | Keluar | − | − | − | parts:approved → mekanik | − | − |
| PO Receive | − | Masuk | AP | − | − | − | − | ✓ |
| Stok ≤ minStock | − | − | − | − | − | stock:low → gudang | Low Stock | − |
| Buat Booking | − | − | − | − | − | booking:created | Booking Conf. | − |
| Buka Shift Kasir | − | − | − | − | − | cash:drawer_opened | − | − |
| Payroll Approved | − | − | Journal | − | − | − | − | ✓ |
| Buat User | − | − | − | − | − | − | Welcome | ✓ |
| Forgot Password | − | − | − | − | − | − | Reset Link | − |
Checklist Regresi Sebelum Release
Minimum skenario yang harus diverifikasi sebelum setiap deployment ke production.
🔴 Wajib Lulus — Core Flow
- Login semua 7 role berhasil dan redirect ke halaman yang benar
- Golden Path end-to-end (TC-FLOW-01) berjalan tanpa error
- Payment lunas → journal keuangan terbuat otomatis
- Payment lunas → email invoice terkirim (cek inbox atau log)
- Parts request approve → stok berkurang
- Stok ≤ minStock → WS event + email alert berjalan
🟠 Wajib Lulus — Security & Integrity
- WO selesai → email "kendaraan siap" terkirim ke customer
- Manager hanya lihat data branch sendiri
- Mekanik hanya lihat job milik sendiri
- Cash drawer: tidak bisa payment tanpa shift aktif
- Fiscal period closed → tidak bisa buat jurnal di periode tsb
- Dashboard angka konsisten dengan laporan detail