158 lines
4.8 KiB
Markdown
158 lines
4.8 KiB
Markdown
# Fase 1 — Task Pack (Urutan Implementasi Langsung)
|
|
|
|
Dokumen ini adalah daftar kerja yang bisa langsung dipakai sebagai urutan PR/ticket.
|
|
|
|
## Paket A — Foundation Core (Step 1)
|
|
|
|
## A.1 PR: Shared Foundation + Middleware
|
|
- scope: `shared`, tracing, request/error wrapper, idempotency table baseline, audit helper
|
|
- target file:
|
|
- shared error formatter
|
|
- request_id/trace_id generator
|
|
- idempotency service CRUD/read
|
|
- acceptance:
|
|
- semua response punya `request_id` di body meta
|
|
- idempotency write/read bisa ditest di local endpoint sample
|
|
|
|
## A.2 PR: Auth Baseline
|
|
- scope: login/admin token minimal, auth middleware, role dasar
|
|
- acceptance:
|
|
- endpoint admin menolak tanpa token (`401`)
|
|
- token valid memberi akses CRUD Step 1
|
|
|
|
## A.3 PR: Merchant CRUD
|
|
- scope: `POST /admin/merchants`, `GET /admin/merchants`, `GET /admin/merchants/{id}`, `PATCH /admin/merchants/{id}`
|
|
- acceptance:
|
|
- create/read/update berhasil
|
|
- duplikasi create dengan idempotency key tidak membuat duplicate
|
|
|
|
## A.4 PR: Outlet + Terminal
|
|
- scope:
|
|
- `POST /admin/merchants/{merchantId}/outlets`
|
|
- `GET /admin/outlets`, `GET /admin/outlets/{id}`, `PATCH /admin/outlets/{id}`
|
|
- `POST /admin/outlets/{outletId}/terminals`
|
|
- `GET /admin/terminals`, `GET /admin/terminals/{id}`, `PATCH /admin/terminals/{id}`
|
|
- acceptance:
|
|
- outlet/terminal berkait dengan merchant/outlet parent
|
|
- error jika parent tidak valid
|
|
|
|
## A.5 PR: Device Registry + Binding
|
|
- scope:
|
|
- `POST /admin/devices`, `GET /admin/devices`, `GET /admin/devices/{id}`, `PATCH /admin/devices/{id}`
|
|
- `POST /admin/devices/{id}/bind`
|
|
- `POST /admin/devices/{id}/unbind`
|
|
- acceptance:
|
|
- bind menghasilkan `device_bindings` aktif tunggal
|
|
- unbind menonaktifkan binding aktif
|
|
|
|
## A.6 PR: Migration + Seed Phase 1
|
|
- scope:
|
|
- tables dari Step 1 MVP
|
|
- seed: 2 merchant, 2 outlet, 2 terminal, 3 device
|
|
- user/admin seed baseline
|
|
- acceptance:
|
|
- sistem startup clean dengan data seed
|
|
- query dasar berjalan
|
|
|
|
## Paket B — Transaction + Webhook (Step 2)
|
|
|
|
## B.1 PR: Transaction Core & State Machine
|
|
- scope:
|
|
- tabel `transactions`, `transaction_events`
|
|
- states: initiated, awaiting_payment, paid, failed, expired
|
|
- acceptance:
|
|
- create transaksi dasar
|
|
- timeline event tercatat saat state berubah
|
|
|
|
## B.2 PR: Callback Receiver
|
|
- scope: `POST /integrations/qris/callback`
|
|
- rules:
|
|
- signature validation
|
|
- idempotency callback
|
|
- duplicate replay handling
|
|
- acceptance:
|
|
- valid callback -> state paid
|
|
- duplicate callback tidak mengubah state
|
|
- signature salah -> 401
|
|
|
|
## B.3 PR: Event Emission (`transaction.paid`)
|
|
- scope:
|
|
- emit internal event saat status bayar sukses
|
|
- acceptance:
|
|
- setiap successful callback menghasilkan event sekali (idempotent)
|
|
|
|
## Paket C — Notification (Step 3)
|
|
|
|
## C.1 PR: Notification Orchestrator
|
|
- scope:
|
|
- listen `transaction.paid`
|
|
- buat `notifications` record
|
|
- acceptance:
|
|
- transaksi paid menghasilkan record notification
|
|
|
|
## C.2 PR: MQTT Publisher
|
|
- scope:
|
|
- publish ke `devices/{deviceId}/downlink/payment/success`
|
|
- payload sesuai kontrak
|
|
- acceptance:
|
|
- publish sukses update `delivery_status=sent`
|
|
- fallback jika publish gagal -> `retrying/failed`
|
|
|
|
## C.3 PR: Retry + Admin Retry API
|
|
- scope:
|
|
- retry loop (15/30/60)
|
|
- `POST /admin/transactions/{transactionId}/retry-notification`
|
|
- acceptance:
|
|
- status update berjalan dari retrying ke sent/gagal
|
|
|
|
## Paket D — Device & Ops Monitoring (Step 4)
|
|
|
|
## D.1 PR: Heartbeat Ingestion
|
|
- scope:
|
|
- `POST /device/heartbeat`
|
|
- update `devices.last_seen_at`
|
|
- simpan `device_heartbeats`
|
|
- acceptance:
|
|
- status heartbeat dan latest heartbeat terlihat per device
|
|
|
|
## D.2 PR: Device Listing + Detail
|
|
- scope:
|
|
- `GET /admin/devices`
|
|
- `GET /admin/devices/{id}`
|
|
- derived status online/stale/offline/degraded
|
|
- acceptance:
|
|
- list/detail bisa difilter dan menampilkan status
|
|
|
|
## D.3 PR: Transaction List/Detail + Heartbeat History
|
|
- scope:
|
|
- `GET /admin/transactions`, `GET /admin/transactions/{id}`
|
|
- `GET /admin/devices/{id}/heartbeats`
|
|
- acceptance:
|
|
- timeline event dan heartbeat history tampil
|
|
|
|
## D.4 PR: Dashboard KPI + Failed Notification View
|
|
- scope:
|
|
- `GET /admin/dashboard/summary`
|
|
- `GET /admin/notifications/failed`
|
|
- acceptance:
|
|
- 5 metrik minimum tampil
|
|
- daftar notifikasi failed bisa difilter
|
|
|
|
## Urutan Eksekusi Terbuka
|
|
1. A.1 → A.2 → A.6 (mendukung semua service berikutnya)
|
|
2. A.3 → A.4 → A.5
|
|
3. B.1 → B.2 → B.3
|
|
4. C.1 → C.2 → C.3
|
|
5. D.1 → D.2 → D.3 → D.4
|
|
|
|
## Aturan Dependensi
|
|
- B paket tidak boleh dimulai jika A.5 belum selesai (binding + transaksi dasar belum valid)
|
|
- C paket tidak boleh dimulai jika B.3 belum siap
|
|
- D paket bisa jalan paralel dengan C jika A dan B core sudah jalan
|
|
|
|
## Exit Criteria Fase 1 (siap Step 2)
|
|
- [ ] static paid flow jalan end-to-end
|
|
- [ ] tidak ada duplicate state via callback
|
|
- [ ] notification ada untuk paid tx
|
|
- [ ] device heartbeat dan status ops visible
|