[TASK-SET-EXPIRED-BILLING-V3] Implementasi Endpoint Set Expired Billing V3 dan Tracking Pembatalan Single Billing
Modul: Single Billing | Tipe: Feature | Stage Saat Ini:
DEVELOPMENT| Tanggal Dokumen: 2026-08-27
1. Informasi Tugas & Referensi Bisnis
Task ID / Nomor Referensi:
TASK-SET-EXPIRED-BILLING-V3Sumber Instruksi: Instruksi Penambahan Endpoint Set Expired Billing V3
Dokumen Referensi / Lampiran:
-Task / Dependensi Terkait (Cross-Service): TASK-SPLIT-BILLING-202608 — Dikonsumsi oleh modul Pengangkut saat void & reset split billing
Modul Terkait:
Single BillingService / Repository:
single-billing-BEPIC Pengembang: Hermansyah Efendi
Latar Belakang & Ringkasan Kebutuhan: Implementasi endpoint baru
POST /v3/set-expired-billingpada layanan Single Billing untuk mengakomodasi kebutuhan pembatalan dan pembaruan status billing menjadi kedaluwarsa (expired) sebelum waktu jatuh tempo reguler tercapai. Endpoint ini dilengkapi dengan proteksi validasi skema Joi anti-SQL injection, penjagaan status billing (fl_paiddanfl_expired), pembaruan flag dan timestamp kedaluwarsa pada database, pencatatan event tracking status code312, serta audit logging terpadu. Selain itu, penyesuaian dilakukan pada query pengecekan billing eksisting agar mengabaikan billing yang telah berstatus expired.Ruang Lingkup & Rincian Sub-Pekerjaan (Technical Scope & Milestones):
- [x] Milestone 1: Validation Schema Definition (Definisi skema validasi Joi
schemasSetExpiredBillingV3dengan proteksi anti-SQL Injection). - [x] Milestone 2: Route Registration & Security Guard (Implementasi route handler
POST /v3/set-expired-billingyang diamankan middlewaredoIntrospectiondanvalidateSchemaSimponi). - [x] Milestone 3: Core Service Logic & Orchestration (Implementasi business logic
setExpiredBillingHelperuntuk validasi status billingfl_paid/fl_expired, update database, insert tracking312, dan logging audit). - [x] Milestone 4: Database Model Query (Implementasi query model
setBillingExpiredpada tabelbilling.subbiller_hdr). - [x] Milestone 5: Existing Billing Filter Adjustment (Penyesuaian query
checkExistingBillingagar mengabaikan billing yang telah berstatus expired dengan kondisifl_expired is not true).
- [x] Milestone 1: Validation Schema Definition (Definisi skema validasi Joi
2. Deployment Lifecycle
| # | Environment | Tanggal & Waktu | PIC | Status | Catatan |
|---|---|---|---|---|---|
| 1 | Development | 2026-08-27 12:18 | Hermansyah Efendi | DEPLOYED | Branch: development (Commit: ec51278e) |
| 2 | Staging (UAT) | — | — | PENDING | — |
| 3 | Production | — | — | PENDING | — |
Riwayat Update Log
| Tanggal | Environment | Perubahan | PIC |
|---|---|---|---|
| 2026-08-27 | Development | Inisialisasi draft audit log dari context block backend (commit ec51278e) | Hermansyah Efendi |
3. Analisis Teknis & Rincian Perubahan
Alur Logika & Bisnis:
- Validasi Kondisi Billing: Memeriksa keberadaan data billing berdasarkan
trx_id_insw(mengembalikan 404 jika tidak ditemukan). Memastikan billing belum dibayar (fl_paid !== true), jika sudah dibayar ditolak dengan status 400. Memastikan billing belum berstatus expired (fl_expired !== true), jika sudah expired ditolak dengan status 400. - Eksekusi Update Database: Mengubah flag
fl_expiredmenjaditruedan memperbaruiexpired_datedengan timestamp sistem saat ini pada tabelbilling.subbiller_hdr. - Pencatatan Audit & Tracking: Menambahkan event tracking baru ke tabel tracking dengan status code
312pada timestamp zona waktuAsia/Jakarta, serta mencatat raw audit log ke tabel logging sistem INSW. - Penyesuaian Inquiry & Existing Billing Check: Penyesuaian query
checkExistingBillingpadaapp/models/tagihan_models.jsdengan menyertakan filterfl_expired is not truesehingga billing yang telah dibatalkan/expired tidak menghambat pembentukan siklus billing baru. - Daftar File yang Berubah:
app/routes/v3/index.js[Controller / API Route]app/controllers/v3/billing_controller.js[Controller / API Route]app/helpers/billing_helper.js[Service / Business Logic]app/models/billing_models.js[Model / Database Access]app/models/tagihan_models.js[Validation / Schema & Model]tests/helpers/billing_helper.test.js[Unit Test]
- Validasi Kondisi Billing: Memeriksa keberadaan data billing berdasarkan
Perubahan Database (DDL / DML):
sql-- DML Update Status Expired pada tabel billing.subbiller_hdr UPDATE billing.subbiller_hdr SET fl_expired = true, expired_date = to_char(now(), 'YYYY-MM-DD HH24:MI:SS') WHERE trx_id_insw = $1 RETURNING *;Kontrak API & Response Payload:
POST/api/v3/set-expired-billing- Deskripsi: Mengubah status billing yang terdaftar di Single Billing menjadi expired sebelum jatuh tempo reguler.
- Autentikasi / Guard:
Bearer Token(doIntrospection, scope:single_billing, menu:/billing,validateSchemaSimponi) - Request Header / Content-Type:
Authorization:Bearer <token>Content-Type:application/json
- Request Body:json
{ "trx_id_insw": "TRX-INSW-20260827-0001", "alasan": "Permintaan pembatalan layanan oleh pengguna jasa" } - Response Payload (
200 OK):json{ "success": true, "statusCode": 200, "message": "Berhasil mengubah status billing menjadi expired", "data": { "trx_id_insw": "TRX-INSW-20260827-0001", "kode_billing_induk": "8202608270001", "fl_expired": true, "expired_date": "2026-08-27 14:45:00.000", "alasan": "Permintaan pembatalan layanan oleh pengguna jasa" } } - Response Error (
400 Bad Request/404 Not Found/500 Server Error):json{ "success": false, "statusCode": 400, "message": "Billing sudah dibayar dan tidak dapat diubah statusnya menjadi expired" }json{ "success": false, "statusCode": 404, "message": "Data billing dengan aju tersebut tidak ditemukan" }
4. Bukti Teknis (Technical Proof & Audit Trail)
- Repository:
single-billing-BE - Branch Utama:
development - Merge Request / PR:
-
Daftar Commit Terkait (Multi-Commit Trail)
| Commit ID | Branch | Author | Tanggal & Jam | Ringkasan Perubahan |
|---|---|---|---|---|
ec51278e1c156bfbc5048155996bc14e2a6b21e9 | development | Hermansyah Efendi | 2026-08-27 12:18 | feat(billing): implement set expired billing endpoint v3 |
Cuplikan Kode / Implementasi Inti
// app/helpers/billing_helper.js
export const setExpiredBillingHelper = async ({ trx_id_insw, alasan }) => {
let logging = [
null, null, Date.now() / 1000, null, 1, trx_id_insw,
{ trx_id_insw, alasan }, null, null, "Set Expired Billing",
null, true, null, null, "set_expired", "INSW"
];
try {
const dataSubbillerHdr = await getDataSubbillerByTrxIdINSW(trx_id_insw);
if (!dataSubbillerHdr) {
return {
success: false,
statusCode: status.notfound,
message: "Data billing dengan aju tersebut tidak ditemukan",
};
}
if (dataSubbillerHdr.fl_paid === true) {
return {
success: false,
statusCode: status.bad,
message: "Billing sudah dibayar dan tidak dapat diubah statusnya menjadi expired",
};
}
if (dataSubbillerHdr.fl_expired === true) {
return {
success: false,
statusCode: status.bad,
message: "Billing sudah dalam status expired",
};
}
const updatedBilling = await setBillingExpired(trx_id_insw);
if (!updatedBilling) {
return {
success: false,
statusCode: status.error,
message: "Gagal memperbarui status expired di database",
};
}
const recordTime = moment().tz("Asia/Jakarta").format("YYYY-MM-DD HH:mm:ss.SSS");
await insertTableTracking(trx_id_insw, recordTime, "312");
logging[0] = dataSubbillerHdr.id_subbiller_hdr;
logging[1] = dataSubbillerHdr.kode_billing_induk || null;
logging[9] = "Success Set Expired Billing >> setExpiredBilling_V3";
await insertLogRawQuery(logging);
return {
success: true,
statusCode: status.success,
message: "Berhasil mengubah status billing menjadi expired",
data: {
trx_id_insw: trx_id_insw,
kode_billing_induk: dataSubbillerHdr.kode_billing_induk || null,
fl_expired: true,
expired_date: updatedBilling.expired_date || recordTime,
alasan: alasan || null,
},
};
} catch (error) {
logging[3] = Date.now() / 1000;
logging[9] = "Error Set Expired Billing";
await insertLogRawQuery(logging);
return {
success: false,
statusCode: status.error,
message: "Internal server error",
error: error.message || error,
};
}
};5. Bukti Verifikasi Pengujian (QA / Unit Test / API Verification)
A. Verifikasi Unit Test (Development Stage)
- Test Suite File:
tests/helpers/billing_helper.test.js - Status Eksekusi CLI:
PASSED (7/7 tests passed)
RUN v4.1.11 D:/WORK/LNSW/single-billing-BE
✓ tests/helpers/billing_helper.test.js (7 tests) 41ms
Test Files 1 passed (1)
Tests 7 passed (7)
Start at 15:22:21
Duration 705ms (transform 159ms, setup 138ms, import 120ms, tests 41ms, environment 0ms)B. Verifikasi Integrasi Staging / Production
Diisi saat naik ke Staging atau Production.
{
"test_suites": [
"tests/helpers/billing_helper.test.js (PASS)"
],
"verification_status": "DEV_PASSED"
}- Hasil Pengujian UAT:
PENDING - Catatan QA: Unit test lokal (7 tests) telah lulus secara empiris. Menunggu jadwal deployment dan verifikasi staging.