Siklus status Order: Kontrak & Spot Order (OTO)
Order kontrak/agreement dan Spot Order bukan dua sistem yang berbeda. Keduanya memakai Order dan mesin pengiriman yang sama persis, mulai dari driver ditugaskan sampai pencairan dana. Karena itu dokumen ini menggabungkan keduanya jadi satu alur, bukan dua dokumen terpisah. Tabel "Bedanya order kontrak vs Spot Order" di bawah merangkum persisnya di mana saja bedanya.
Sumber lain yang lebih rinci untuk urutan API per langkah (khusus Spot Order, format sequence diagram) ada di diagram sequence Spot Order, dibuat tim backend sendiri. Beberapa temuan di dokumen ini justru berasal dari situ, ditelusuri ulang ke kode untuk memastikan masih akurat.
Kalau bukan orang teknis, boleh langsung lewati kolom Dipicu oleh, Endpoint / mekanisme, dan Aplikasi di semua tabel di bawah, sisanya (Arti, Aktor, Label Transporter, Label Shipper) tetap kebaca lengkap tanpa itu semua.
Definisi
Aktor
| Aktor | Siapa/apa | Muncul lewat aplikasi apa |
|---|---|---|
| Shipper | Pengirim barang, pemilik order | Web (karlo_platform, sisi Shipper) |
| Transporter / Admin | Perusahaan penyedia truk & driver, atau admin internal Karlo yang bertindak atas nama transporter — backend memperlakukan keduanya sama | Web (karlo_platform, sisi Transporter) |
| Driver | Pengemudi truk | Aplikasi mobile. Backend sendiri menyebutnya "kTrip" berulang kali di kode (nama alur pengiriman, field versi aplikasi, dst.), tapi karena kode aplikasi mobilenya tidak ada di repo ini, sebaiknya dikonfirmasi ke tim mobile apakah ini masih nama produk yang dipakai sekarang |
| PIC Warehouse | Penanggung jawab gudang muat/bongkar | Karlo Web Field — bukan aplikasi yang di-install, tapi halaman web yang dibuka lewat link "magic login" yang dikirim ke PIC (lihat Fase 6.1 di bawah) |
| Sistem / Karlo Backend | Backend Karlo sendiri, menulis status secara otomatis tanpa ada orang yang menekan tombol | — |
| Cron / Terjadwal | Tugas backend yang jalan sendiri di jam tertentu, bukan dipicu satu kejadian tertentu | — |
| Xendit | Penyedia pembayaran & pencairan dana pihak ketiga | — |
| WA Gateway | Jalur pengiriman WhatsApp, dipakai untuk mengirim kode OTP dan link Karlo Web Field ke PIC | — |
Dipicu oleh
| Nilai | Artinya |
|---|---|
| API | Ada permintaan langsung dari salah satu aplikasi di atas yang membuat status ini berubah |
| AUTO | Backend menulis status ini sendiri, efek samping dari proses lain, tanpa permintaan terpisah dari siapa pun |
| WEBHOOK | Xendit yang mengirim kabar balik ke Karlo (pembayaran masuk, pencairan selesai, dst.) |
| CRON | Tugas terjadwal yang mengecek dan mengubah status sendiri |
Soal ketidakpastian
Hampir semua status di dokumen ini sudah ditelusuri langsung ke kode backend, bukan dugaan. Satu hal yang tersisa perlu ditandai beda:
❓ Perlu ditanya ke tim mobile, bukan ke backend — hanya berlaku untuk satu kasus (verifyCargoLoading/cargoLoadingVerified, Fase 4): backend punya dua endpoint asli yang sama-sama aktif untuk hal yang sama, dan yang menentukan mana yang kepakai adalah aplikasi driver, bukan sesuatu yang bisa dijawab dari sisi backend saja.
Peta umum
flowchart LR
A["Negosiasi"] --> B["Pembayaran"]
B --> C["Penugasan Driver"]
C --> D["Proses Muat"]
D --> E["Menuju Lokasi Bongkar"]
E --> F["Proses Bongkar"]
F --> G["Menunggu Konfirmasi<br/>Pengiriman"]
G --> H["Selesai / Terkonfirmasi"]
H --> I["Pencairan Dana"]
A -.semua transporter menolak.-> X["Dibatalkan"]
C -.dibatalkan.-> X
D -.dibatalkan.-> X
E -.dibatalkan.-> X
F -.dibatalkan.-> XBabak Negosiasi dan Pembayaran hanya berlaku untuk Spot Order. Order kontrak masuk langsung ke Penugasan Driver karena harga dan syaratnya sudah disepakati lewat Agreement sejak awal.
Peta detail: seluruh perjalanan Spot Order
flowchart TD
classDef confirmed fill:#dff7e0,stroke:#1a7a34,color:#14231a
classDef dead fill:#eeeeee,stroke:#999999,color:#666666,stroke-dasharray: 2 2
classDef entry fill:#e6ecff,stroke:#33449a,color:#1a2140
subgraph LEGEND["Legenda"]
direction LR
L1["Dikonfirmasi terjadi<br/>& aktif dipakai"]:::confirmed
L3["Terbukti tidak<br/>pernah berjalan"]:::dead
L4["Titik masuk order kontrak"]:::entry
end
DR["draft<br/>Belum disubmit"]:::confirmed --> OC["otoCreated<br/>Order diajukan"]:::confirmed --> ON["otoNegotiation<br/>Negosiasi"]:::confirmed
ON -->|disepakati| OWP["otoWaitingPayment<br/>Menunggu Pembayaran"]:::confirmed
ON -.semua tipe truk ditolak.-> CN["cancel<br/>Order Dibatalkan"]:::confirmed
ON -.lewat batas waktu.-> EXP["expired<br/>Order Kadaluarsa"]:::confirmed
OWP --> OPP["otoPaymentInProgress<br/>Proses Pembayaran"]:::confirmed
OPP --> RAD["requestAssignmentDriver<br/>Menunggu Penugasan"]:::confirmed
KONTRAK["Order Kontrak<br/>(Agreement sudah ada,<br/>tanpa negosiasi & pembayaran)"]:::entry --> RAD
RAD --> ASD["assignDriver<br/>Pengemudi Ditugaskan"]:::confirmed
ASD --> STL["startToLoadingPoint<br/>Menuju Lokasi Muat"]:::confirmed
STL -->|GPS otomatis, masuk radius lokasi| AAL["arriveAtLoadingPoint<br/>Tiba di Lokasi Muat"]:::confirmed
STL -->|hanya kalau OTP Bongkar aktif| SL["startLoading<br/>Mulai Muat"]:::confirmed
STL -->|endpoint finish-loading lama| FL["finishLoading<br/>Selesai Muat"]:::confirmed
AAL --> FL
SL --> FL
STL -->|endpoint finish-loading-verification| VCL["verifyCargoLoading<br/>Pengecekan Muatan"]:::confirmed
VCL --> CLV["cargoLoadingVerified<br/>Muatan Dilaporkan"]:::confirmed
CLV --> FL
FL --> VPL["verifyPodLoading<br/>Verifikasi Muatan"]:::confirmed
VPL -->|ditolak| PLR["podLoadingRejected"]:::confirmed
PLR --> VPL
VPL -->|disetujui| PLV["podLoadingVerified"]:::confirmed
PLV --> STU["startToUnloadingPoint<br/>Menuju Lokasi Bongkar"]:::confirmed
STU -->|GPS otomatis| AAU["arriveAtUnloadingPoint<br/>Tiba di Lokasi Bongkar"]:::confirmed
STU --> SU["startUnloading<br/>Mulai Bongkar"]:::confirmed
AAU --> SU
SU --> FU["finishUnloading<br/>Selesai Bongkar"]:::confirmed
SU -->|hanya kalau OTP Bongkar aktif, lewat PIC Web Field| VCU["verifyCargoUnloading<br/>Bongkar Dilaporkan"]:::confirmed
VCU --> CUV["cargoUnloadingVerified<br/>Selesai Bongkar"]:::confirmed
CUV --> VPU
FU --> VPU["verifyPodUnloading<br/>Verifikasi Bongkar"]:::confirmed
VPU -->|ditolak| PUR["podUnloadingRejected"]:::confirmed
PUR --> VPU
VPU -->|disetujui, shipment terakhir| DN["done<br/>Menunggu Konfirmasi Pengiriman"]:::confirmed
DN --> OF["orderFinal<br/>Terkonfirmasi Selesai"]:::confirmed
OF --> DISB["orderDisbursement<br/>Pencairan Diproses"]:::confirmed
DISB --> OTU["otoTranspoterUpdate<br/>Pencairan Sukses"]:::confirmed
OF --> OTUOrder kontrak masuk di kotak biru dan langsung bergabung ke alur yang sama persis dari requestAssignmentDriver sampai selesai. Titik arriveAtLoadingPoint/arriveAtUnloadingPoint sengaja digambar bukan sebagai langkah berurutan biasa, itu ditulis otomatis lewat pelacakan GPS begitu posisi truk masuk radius lokasi, terpisah dari alur langkah-demi-langkah yang lain, lihat Fase 4 untuk detailnya. Status yang terbukti tidak pernah berjalan sama sekali tidak digambar di sini supaya diagram tidak terlalu padat, daftarnya ada di bagian "Status yang terbukti tidak pernah berjalan" di bawah.
Bedanya order kontrak vs Spot Order
| Order kontrak | Spot Order | |
|---|---|---|
| Titik mulai | Langsung dibuat dari Agreement yang sudah disepakati sebelumnya | Diajukan shipper dari nol, belum ada kesepakatan harga/transporter |
| Negosiasi & pembayaran di muka | Tidak ada, harga dan transporter sudah pasti sejak awal | Ada, dua fase penuh sebelum driver ditugaskan |
| Penugasan driver sampai selesai kirim | Sama persis, mesin dan status yang sama | Sama persis |
| Finalisasi & pencairan dana | Sama persis | Sama persis |
| Pembatalan | Hanya menghapus status order, tidak ada pengembalian dana di titik ini | Ada tambahan proses pengembalian dana, karena Spot Order sudah dibayar di muka |
Karena bagian "sama persis" itu adalah mesin yang sama-sama dipakai (bukan dua mesin yang kebetulan mirip), mengubah satu status di tengah alur pengiriman akan memengaruhi order kontrak dan Spot Order sekaligus, kecuali sengaja dibuat bercabang dengan syarat khusus seperti negosiasi/pembayaran di atas, atau seperti fitur OTP Bongkar di Fase 6.1. Perubahan di tengah alur bersama ini bukan hal sepele, dan sebaiknya selalu dikonfirmasi ke backend sebelum dianggap "tinggal ubah sedikit."
Fase 1: Negosiasi (khusus Spot Order)
Shipper mengajukan kebutuhan, sampai 3 transporter diundang, harga ditawar-tawar sebelum apa pun dikunci.
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor | Aplikasi |
|---|---|---|---|---|---|
draft | Shipper belum submit, order masih tersimpan sebagai draft | API | POST /spot-order dengan isDraft: true | Shipper | Web |
otoCreated | Order baru diajukan shipper (submit, bukan draft) | API | POST /spot-order dengan isDraft: false | Shipper | Web |
otoNegotiation | Negosiasi aktif. Satu status ini mewakili seluruh proses tawar-menawar, sampai 3 putaran per pihak, tidak ada status terpisah untuk tiap tawaran/penolakan | API | POST /spot-order/:id/negotiate | Shipper | Web |
Kalau semua transporter menolak semua tipe truk yang ditawarkan, order langsung berpindah ke cancel (lihat Fase Pembatalan). Order juga bisa berakhir di expired kalau melewati batas waktu tanpa ada tindakan (lihat Fase Pembatalan juga), keduanya beda dari "ditolak saat negosiasi".
Fase 2: Pembayaran (khusus Spot Order)
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor | Aplikasi |
|---|---|---|---|---|---|
otoWaitingPayment | Penawaran disepakati, transporter terkunci, menunggu shipper mulai bayar | API | PUT /spot-order/:id/confirm | Shipper | Web |
otoPaymentInProgress | Shipper sudah mulai transfer, menunggu konfirmasi dari penyedia pembayaran. Status paling lama menggantung di fase ini, bisa sampai batas waktu pembayaran | WEBHOOK | POST /callback/update | Sistem | — |
otoPaymentSuccess | Pembayaran berhasil dikonfirmasi, tapi tidak pernah jadi status hidup yang bisa dicek | WEBHOOK, hanya tercatat di riwayat | POST /callback/paid | Sistem | — |
Begitu pembayaran sukses, dalam proses yang sama sistem langsung memaksa status berpindah ke requestAssignmentDriver sepersekian detik kemudian.
Fase 3: Penugasan Driver
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor | Aplikasi |
|---|---|---|---|---|---|
requestAssignmentDriver | Pembayaran sukses (Spot Order) atau order baru dibuat (kontrak), transporter perlu memilih driver | AUTO | dipaksa sistem setelah pembayaran, atau langsung dari pembuatan order kontrak | Sistem | — |
assignDriver | Driver dan truk sudah dipilih | API | PUT /order/:id/assign-driver | Transporter | Web |
Fase 4: Proses Muat
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor | Aplikasi | Label Transporter | Label Shipper |
|---|---|---|---|---|---|---|---|
startToLoadingPoint | Driver menuju lokasi muat | API | PUT /order/:id/shipment/start-to-loading-point | Driver | Mobile | Menuju Lokasi Muat | Menuju Lokasi Muat |
arriveAtLoadingPoint | Driver tiba di lokasi muat | AUTO | dipicu otomatis lewat pelacakan GPS truk (posisi masuk radius tertentu di sekitar lokasi muat), lihat catatan di bawah | Sistem | Mobile (GPS latar belakang) | Tiba di Lokasi Muat | Tiba di Lokasi Muat |
outOfLoadingPoint | Driver sudah meninggalkan lokasi muat | AUTO | sama seperti arriveAtLoadingPoint, pelacakan GPS, posisi keluar radius | Sistem | Mobile (GPS latar belakang) | tidak ada label tersendiri | Keluar dari Lokasi Muat |
startLoading | Proses muat dimulai | AUTO, hanya jalan kalau order.isUsingOtpBongkar aktif (lihat Fase 6.1) | — | Driver | Mobile | Proses Muat Barang | Mulai Muat |
verifyCargoLoading | Driver mengecek kesesuaian muatan sebelum kirim POD | API — dua endpoint asli sama-sama aktif untuk menyelesaikan proses muat, mana yang kepakai tergantung aplikasi driver, ❓ lihat catatan Definisi | PUT .../finish-loading-verification (endpoint baru, dengan cek muatan) vs PUT .../finish-loading (endpoint lama, tanpa cek muatan) | Driver | Mobile | tidak ada label tersendiri | Pengecekan Muatan |
cargoLoadingVerified | Pengecekan muatan lolos | sama seperti verifyCargoLoading | sama seperti verifyCargoLoading | Driver | Mobile | tidak ada label tersendiri | Muatan Dilaporkan |
cargoLoadingRejected | Pengecekan muatan tidak lolos, muatan dianggap tidak sesuai | sama seperti verifyCargoLoading | sama seperti verifyCargoLoading | Driver | Mobile | — | — |
finishLoading | Proses muat selesai, foto bukti pengiriman (POD) dikirim | API | PUT .../finish-loading atau PUT .../finish-loading-verification | Driver | Mobile | Selesai Muat | Selesai Muat |
verifyPodLoading | POD muat sedang direview | AUTO (otomatis beberapa detik setelah finishLoading) | — | Sistem | — | Verifikasi POD dan Muatan | Verifikasi Muatan |
podLoadingRejected | POD muat ditolak, driver harus kirim ulang | AUTO, hanya tercatat di riwayat | driver kirim ulang lewat PUT /upload-pod/:id | Sistem | Mobile | — | — |
podLoadingVerified | POD muat disetujui | API | PUT /pod/:id/verify {type:'loading'} | Transporter / Admin | Web | POD dan Muatan Terverifikasi | Muatan Terverifikasi |
arriveAtLoadingPoint punya tiga jalur kode berbeda yang bisa menulisnya. Yang ditelusuri di atas adalah pelacakan GPS otomatis (dikirim lewat POST /tracking/last-location, bisa dari GPS aplikasi mobile driver atau dari alat GPS fisik terpasang di truk). Ada juga dua endpoint manual terpisah untuk hal yang konsepnya sama (PUT .../arrive-at-loading-point dan PUT .../arrive-loading), keduanya wired, belum ditelusuri lebih jauh apakah salah satunya masih benar-benar dipanggil aplikasi sekarang.
Fase 5: Menuju Lokasi Bongkar
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor | Aplikasi |
|---|---|---|---|---|---|
startToUnloadingPoint | Driver menuju lokasi tujuan | AUTO, langsung setelah POD muat disetujui | — | Sistem | — |
Fase 6: Proses Bongkar
Bentuknya sama seperti Fase 4, dengan satu perbedaan kata yang disengaja: untuk muat, Transporter dan Shipper sama-sama bilang "Selesai Muat" di langkah selesai-muat. Untuk bongkar, Transporter bilang "Selesai Bongkar" tapi Shipper menyimpan sebutan itu untuk langkah setelahnya (saat muatan terkonfirmasi lolos cek), dan menyebut langkah selesai-bongkar sebagai "Pengecekan Bongkar". Ini bukan salah ketik di lembar kerja bisnis, biarkan seperti itu.
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor | Aplikasi | Label Transporter | Label Shipper |
|---|---|---|---|---|---|---|---|
arriveAtUnloadingPoint | Driver tiba di lokasi bongkar | AUTO, sama seperti arriveAtLoadingPoint di Fase 4 (pelacakan GPS) | — | Sistem | Mobile (GPS latar belakang) | Tiba di Lokasi Bongkar | Tiba di Lokasi Bongkar |
outOfUnloadingPoint | Driver sudah meninggalkan lokasi bongkar | AUTO, sama seperti outOfLoadingPoint di Fase 4 (pelacakan GPS) | — | Sistem | Mobile (GPS latar belakang) | tidak ada label tersendiri | — |
startUnloading | Proses bongkar dimulai | API | PUT /order/:id/shipment/start-unloading | Driver | Mobile | Proses Bongkar Muatan | Mulai Bongkar |
verifyCargoUnloading | Driver mengecek kesesuaian muatan saat bongkar, lewat PIC Warehouse | AUTO, hanya jalan kalau order.isUsingOtpBongkar aktif, bagian dari fitur OTP Bongkar (lihat Fase 6.1) | — | Driver + PIC Warehouse | Mobile + Karlo Web Field | tidak ada label tersendiri | Bongkar Dilaporkan |
cargoUnloadingVerified | Pengecekan muatan saat bongkar lolos | sama seperti verifyCargoUnloading | sama seperti verifyCargoUnloading | Driver + PIC Warehouse | Mobile + Karlo Web Field | tidak ada label tersendiri | Selesai Bongkar |
cargoUnloadingRejected | Pengecekan muatan saat bongkar tidak lolos | sama seperti verifyCargoUnloading | sama seperti verifyCargoUnloading | Driver + PIC Warehouse | Mobile + Karlo Web Field | — | — |
finishUnloading | Proses bongkar selesai, POD dikirim | API | PUT /order/:id/shipment/finish-unloading | Driver | Mobile | Selesai Bongkar | Pengecekan Bongkar |
verifyPodUnloading | POD bongkar sedang direview | AUTO (langsung, tanpa jeda beberapa detik seperti sisi muat) | — | Sistem | — | Verifikasi POD dan Muatan | Verifikasi Bongkar |
podUnloadingRejected | POD bongkar ditolak, driver kirim ulang | AUTO, hanya tercatat di riwayat | driver kirim ulang lewat PUT /upload-pod/:id | Sistem | Mobile | — | — |
podUnloadingVerified | POD bongkar disetujui | API | PUT /pod/:id/verify {type:'unloading'} | Transporter / Admin | Web | POD dan Muatan Terverifikasi | Bongkar Terverifikasi |
6.1 Fitur OTP Bongkar & PIC Web Field
Alur verifikasi bongkar yang lebih lengkap dari langkah dasar di tabel atas, aktif untuk order dengan isUsingOtpBongkar: true. Melibatkan aktor ketiga (PIC Warehouse lewat Karlo Web Field) dan kanal terpisah (WA Gateway untuk mengirim OTP).
Cara kerjanya: PIC Warehouse dikirim kode OTP dan link Karlo Web Field lewat WhatsApp, driver meminta kode OTP itu ke PIC saat tiba di lokasi bongkar, PIC memeriksa kesesuaian muatan lewat halaman Karlo Web Field (verifyCargoUnloading → cargoUnloadingVerified), baru setelah itu proses bongkar dianggap terverifikasi. Ada juga alur cadangan kalau PIC yang terdaftar tidak bisa dihubungi (ganti PIC, approval ganti PIC, notifikasi PIC tidak aktif):
POST .../send-otp-pic-unloading, PUT .../pic-verify-hold-using-code, POST .../change-pic, PUT .../change-pic/approval, GET .../new-pic-status, POST .../report-pic-inactive, dan di sisi muat: PUT .../scan-code-loading, PUT .../checklist-loading, PUT .../approval-loading (plus versi publik tanpa login -using-code untuk PIC).
6.2 Toggle yang ditulis sebagai status order, bukan cuma pengaturan
Dua toggle di sisi Transporter/Shipper ini tidak cuma mengubah sebuah pengaturan diam-diam, keduanya menulis statusnya sendiri sebagai status order yang sedang berlaku, menimpa apa pun status pengiriman yang sebenarnya sedang berjalan (Fase 4–6 di atas) untuk sesaat/selama toggle itu aktif:
| Status | Arti | Dipicu oleh |
|---|---|---|
updateIsGeofencingActive / updateIsGeofencingNonActive | Pengaturan geofencing diaktifkan/dinonaktifkan | API (toggle manual Transporter) — atau AUTO, sistem sendiri menuliskannya sebagai koreksi otomatis saat driver selesai muat/bongkar dengan geofencing yang belum aktif |
updateVerifBongkarActive / updateVerifBongkarNonActive | Verifikasi checklist PIC saat bongkar dilewati/diaktifkan kembali (bypass) | API (toggle manual Transporter/Admin) |
Konsekuensinya: kalau order sedang di tengah pengiriman (misalnya di verifyPodLoading) lalu Transporter menekan salah satu toggle ini, status order yang terlihat berubah sesaat ke salah satu status di atas, bukan tetap di status pengiriman yang sebenarnya. Penting diketahui supaya tidak salah baca "status berubah sendiri tanpa sebab" saat toggle ini dipakai.
Cara mengetahui POD ditolak atau tidak
Status utama order tidak bisa dipakai untuk mengecek apakah sebuah POD sedang ditolak, karena penolakan (podLoadingRejected/podUnloadingRejected) adalah status yang hanya tercatat di riwayat, tidak pernah tersimpan sebagai status utama yang sedang berlaku. Yang benar-benar dipakai untuk mengecek ini ada di level pengiriman per shipment itu sendiri (bukan level order), ditambah satu penanda di level order yang bernilai benar selama ada penolakan yang belum diselesaikan, dan kembali salah begitu driver mengirim ulang POD-nya.
Fase 7: Finalisasi
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor | Aplikasi | Label Transporter | Label Shipper |
|---|---|---|---|---|---|---|---|
done | Pengiriman selesai secara fisik. Status paling lama bertahan di seluruh siklus, bisa menggantung sampai 3 hari, menunggu shipper mengonfirmasi barang diterima (atau batas waktu otomatis) | AUTO, otomatis setelah POD bongkar disetujui pada shipment terakhir | — | Sistem | — | Menunggu Konfirmasi Pengiriman | Konfirmasi Penerimaan |
orderFinal | Shipper sudah konfirmasi terima (atau batas waktu 3 hari otomatis terlewati) | API atau CRON | konfirmasi manual, atau tugas terjadwal harian yang memeriksa order yang sudah lebih dari 3 hari di status done | Shipper / Admin / Sistem terjadwal | Web | Pengiriman Terkonfirmasi | Terkonfirmasi Selesai |
Karena barang baru benar-benar "selesai" setelah shipper mengonfirmasi penerimaan, hanya shipper yang punya tombol konfirmasi ini. Transporter tugasnya berhenti di done, ini keputusan bisnis yang disengaja (model pembeli-konfirmasi-penerimaan), bukan fitur yang belum dibuat.
Fase 8: Pencairan Dana
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor |
|---|---|---|---|---|
orderDisbursement | Pencairan sedang diproses. Fase ini sering terlewati sepenuhnya kalau pencairan langsung berhasil | kondisional | permintaan pencairan diajukan, tapi baru muncul kalau penyedia pembayaran membalas "masih diproses" | Sistem |
otoTranspoterUpdate | Pencairan berhasil, ke transporter | WEBHOOK | POST /callback/disbursement | Sistem |
otoCancelInactive | Pencairan gagal dibuat karena akun transporter tidak aktif | AUTO | ditemukan saat proses pencairan meminta akun bank transporter | Sistem |
Nama otoCancelInactive ("Order Cancelled by Inactive Transporter") menyesatkan kalau dibaca sekilas — ini bukan status pembatalan order, ini status kegagalan pencairan yang terjadi di tengah proses Fase 8 di atas, ditulis persis di titik ini, bukan di Fase pembatalan di bawah.
Fase pembatalan
| Status | Arti | Dipicu oleh | Endpoint / mekanisme | Aktor | Label Transporter | Label Shipper |
|---|---|---|---|---|---|---|
cancel | Order dibatalkan, oleh salah satu pihak, atau otomatis kalau semua transporter menolak semua tawaran saat negosiasi | API atau AUTO | PUT /order/:id/cancel-order, atau otomatis saat negosiasi gagal total | Shipper / Transporter / Admin / Sistem | Order Dibatalkan | Order Dibatalkan |
expired | Order kadaluarsa, batas waktu terlewati tanpa tindakan | AUTO | — | Sistem | Order Kadaluarsa | Kadaluarsa |
Spot Order dibayar di muka saat penawaran disepakati, jadi pembatalan Spot Order juga memicu pengembalian dana. Order kontrak tidak, cara penagihannya berbeda dan tidak melibatkan pengembalian dana di titik ini. expired berbeda dari kalah negosiasi (yang berakhir di cancel, lihat Fase 1) — ini soal order yang dibiarkan tanpa tindakan sampai lewat batas waktu, bukan ditolak aktif oleh siapa pun.
Status yang terbukti tidak pernah berjalan
Status-status ini tidak punya jalur kode aktif sama sekali, di order kontrak maupun Spot Order manapun. Catatan metodologi, bukan cuma soal dua status ini: sistem punya dua kumpulan langkah pengiriman yang bisa dipilih backend untuk memajukan status, satu lebih rinci (lewat PIC gudang, scan kode, checklist barang) dan satu lebih sederhana, dan hanya yang sederhana yang pernah dipilih. Tapi status yang tidak masuk kumpulan yang aktif belum tentu mati — arriveAtLoadingPoint di Fase 4 adalah contohnya, ditulis lewat pelacakan GPS, sama sekali di luar kedua kumpulan itu. Dua baris di bawah ini sudah ditelusuri sampai benar-benar tidak ada jalur lain yang menulisnya, bukan cuma "tidak ada di kumpulan yang aktif":
| Status | Arti singkat | Kenapa mati |
|---|---|---|
requestOrderToDriver, waitingDriverApprove, noDriverApprove | Alur "sistem otomatis menawarkan order ke semua driver yang available" sebelum transporter memilih manual | Variabel yang menentukan jalur ini dikunci ke nol secara sengaja di kode, sistem selalu langsung ke requestAssignmentDriver — tidak ada endpoint manapun yang menulis status ini |
enterWaitingOnLoading, exitWaitingOnLoading | Driver masuk/keluar antrean di lokasi muat | Baris kode yang menulis status ini sengaja dikomentari (dinonaktifkan) di dalam logika pelacakan GPS, bukan terhapus, tapi juga tidak aktif |
scanCodeLoading, checklistCargoLoading, approvalLoadingAccepted/Canceled/Rescheduled, scanCodeUnloading, dan checklistCargoUnloading sengaja tidak masuk tabel di atas — semuanya punya endpoint aktif sendiri, dan itu persis fitur OTP Bongkar & PIC Web Field di Fase 6.1.
Status lain yang ada di sistem, di luar alur utama
Status-status ini ada kodenya dan endpoint-nya sungguhan, tapi belum ditelusuri lebih jauh seberapa sering dipakai di luar dokumen ini:
| Status | Arti singkat | Keterangan |
|---|---|---|
ttdLoading, ttdUnloading | Konfirmasi muat/bongkar pakai tanda tangan, sebagai alternatif dari foto POD | Endpoint asli, wired, seberapa sering benar-benar dipakai belum ditelusuri |
alihBongkar | Pengalihan/pemindahan pengaturan lokasi bongkar | Endpoint asli, wired (PUT /order/:id/approve-alih-bongkar), butuh persetujuan Admin |
reuploadPodLoading, reuploadPodUnloading | Kelihatannya untuk menandai "POD diunggah ulang" | Kemungkinan tidak pernah ditulis, proses unggah ulang yang sebenarnya justru mengembalikan status ke verifyPodLoading/verifyPodUnloading, bukan status ini |
finishShipmentUnloading | Kelihatannya penanda "shipment selesai" | Bukan status yang tersimpan di riwayat, hanya proses internal sesaat |
readyToPlan | Order siap masuk perencanaan rute | Bagian dari fitur perencanaan rute yang terpisah, di luar alur pengiriman yang dibahas dokumen ini |
goToLoadingPoint | Kelihatannya sama seperti startToLoadingPoint | Nama status yang berbeda untuk konsep yang sama, belum ditelusuri kapan salah satunya dipakai dibanding yang lain |
update, updateInvoice, updateEstimatedTrip | Penanda generik "ada yang diperbarui di order ini" | Bukan bagian dari alur berurutan di atas, tidak menandakan fase tertentu, hanya metadata perubahan |
requestChooseDriver, approvalChooseDriverAccepted, approvalDriverRejected | Bagian dari fitur 3PL (pihak ketiga memilih driver untuk transporter) | Fitur terpisah dari Spot Order maupun kontrak biasa, di luar cakupan dokumen ini |
Beberapa nama yang beredar tidak sama dengan nama di sistem
Kalau mendengar nama-nama ini dalam rapat atau tiket, ini padanannya di sistem: otoFinal yang dimaksud adalah orderFinal. otoDbInProgress yang dimaksud adalah orderDisbursement. otoDbSuccess yang dimaksud adalah otoTranspoterUpdate (ejaan "Transpoter" tanpa "r" ini memang typo lama di sistem, tapi itu nilai yang harus dipakai kalau mencari/memfilter berdasarkan status). Ketiganya bukan status baru atau rencana penggantian nama, cuma sebutan tidak resmi yang berbeda dari nama aslinya.
Lima nama lain terdengar seperti status order yang sesungguhnya tapi sebenarnya bukan: otoShipperUpdate, otoTransporterUpdate, otoShipperApprove, otoShipperReject, dan otoMaxReject hanya dipakai sebagai label notifikasi, tidak pernah ditulis sebagai status order yang sungguhan (dicek langsung, tidak ada satu pun tempat di kode yang menuliskannya sebagai status order). Order yang gagal karena semua penawaran ditolak tidak berakhir di otoMaxReject, dia berakhir di cancel biasa, sama seperti pembatalan lainnya.