Deteksi Transaksi Duplikat
Contoh dokumen nyata — ditulis dari kode erdigma-api, service transaction.
Ringkasan
Section titled “Ringkasan”Memeriksa apakah satu transaksi kemungkinan merupakan duplikat dari transaksi lain. Dipakai oleh tim CS untuk menolak order ganda sebelum diproses, bukan untuk memblokir otomatis.
- Client memanggil
GET /check-duplicate/{id}. - Sistem mengambil transaksi berdasarkan
id. Kalau tidak ada →400 Transaksi Tidak Ditemukan. - Sistem mencari kandidat transaksi lain dalam rentang tanggal ±7 hari dengan kriteria yang sama (lihat Aturan bisnis).
- Setiap detail transaksi dibandingkan dengan detail kandidat: produk dan kuantitas harus cocok.
- Respons berisi
duplicatedan, jika duplikat, kode transaksi pembanding.
Aturan bisnis
Section titled “Aturan bisnis”Kandidat duplikat hanya diambil bila semua kondisi berikut terpenuhi:
codeberbeda dari transaksi yang diperiksa.statusbukan salah satu dari:Cancelled,Cancelled by System,Cancelled-Out of Stock,Waiting for Payment,Payment Confirmed,Draft.invoiceDateberada dalam rentang 7 hari sebelum atau 7 hari sesudah tanggal transaksi.customerServiceIdsama.kelurahandankecamatansama.source=INPUT.omsetsama persis.paymentMethod=TF-UNIQUECODE.
Sebuah transaksi dinyatakan duplikat bila setiap detailnya punya pasangan
product.id + quantity yang sama pada satu kandidat yang sama.
| Field | Tipe | Keterangan |
|---|---|---|
code |
string | kode transaksi, dipakai sebagai pembeda |
invoiceDate |
date (invoice_date) |
dasar jendela ±7 hari |
status |
string | filter status aktif |
customerServiceId |
relasi CS | pembanding |
kelurahan / kecamatan |
string | pembanding wilayah |
source |
string | hanya INPUT |
omset |
integer | pembanding nominal |
paymentMethod |
string | hanya TF-UNIQUECODE |
| Method | Path | Lambda | Catatan |
|---|---|---|---|
| GET | /check-duplicate/{id} |
checkDuplicate |
reservedConcurrency: low, CORS aktif |
Contoh respons:
{ "duplicate": true, "transaction": { "id": 8123, "code": "TRX-2026-00123" } }Edge case
Section titled “Edge case”transactionDetailskosong →duplicate: true. Loop tidak pernah jalan, sehingga nilai awalduplicate = truelolos ke respons. Ini false positive: transaksi tanpa detail dilaporkan duplikat. (Temuan saat dokumentasi — belum diperbaiki.)duplicateTransactionhanya terisi pada iterasi terakhir yang cocok, jadi untuk kasus duplikat dengan beberapa kandidat, pasangan yang dilaporkan bisa berbeda dari kandidat pertama.- Perbandingan produk/kuantitas memakai
==, bukan===. - Kandidat diambil tanpa paginasi (
paged: false), seluruh transaksi dalam jendela 7 hari dimuat ke memori. omsetharus sama persis; perbedaan pembulatan membuat transaksi tidak dianggap kandidat.
Keputusan desain
Section titled “Keputusan desain”- Endpoint bersifat informatif, tidak memblokir pembuatan transaksi — keputusan akhir di tangan CS.
- Rentang ±7 hari dipilih karena invoice bisa diinput terlambat maupun lebih awal.
- Kombinasi status yang dikecualikan sengaja menutup transaksi yang belum final atau sudah batal, supaya perbandingan hanya terjadi antar transaksi yang benar-benar berjalan.
Riwayat
Section titled “Riwayat”- 2026-10-29 — dokumen dibuat dari kode
src/services/transaction(commit terakhir didev).