Lewati ke isi

Sentra Rental — Availability Calendar Module

Kalender ketersediaan adalah jantung dari sistem rental. Ia harus memberikan jawaban biner (tersedia/tidak) secara atomik dalam hitungan milidetik untuk ribuan unit secara bersamaan.

10.1 Mekanisme Redis Bitmask

Setiap unit aset direpresentasikan oleh satu key Redis per bulan dengan format:

avail:<SKU>:<AssetID>:<YearMonth>

Contoh: avail:TOY-AVNZ-G:uuid-avanza-001:202605

Aturan bit: - Bit = 0 → tanggal tersedia - Bit = 1 → tanggal sudah dipesan/diblokir - Bit ke-0 = tanggal 1, bit ke-1 = tanggal 2, dst.

Alur Pengecekan & Pemblokiran Tanggal

1. Booking request masuk untuk asset_id + date_range
2. Server mengambil bitmask bulan terkait dari Redis
3. BITOP AND untuk memeriksa apakah semua bit dalam rentang = 0 (semua hari tersedia)
4. Jika tersedia → acquire Redlock (TTL 10 menit)
5. Set bit 1 via SETBIT untuk setiap hari dalam rentang secara atomik
6. Insert booking ke PostgreSQL
7. Release Redlock setelah commit transaksi DB

Redis Commands

# Cek ketersediaan tanggal 25 (bit index 24)
GETBIT avail:TOY-AVNZ-G:uuid-avanza-001:202605 24
# → 0 (tersedia) atau 1 (sudah dipesan)

# Tandai tanggal 25-27 sebagai dipesan
SETBIT avail:TOY-AVNZ-G:uuid-avanza-001:202605 24 1
SETBIT avail:TOY-AVNZ-G:uuid-avanza-001:202605 25 1
SETBIT avail:TOY-AVNZ-G:uuid-avanza-001:202605 26 1

# Bebaskan kembali saat booking dibatalkan / expired
SETBIT avail:TOY-AVNZ-G:uuid-avanza-001:202605 24 0

Kenapa Bitmask?

  • Memory efisien: 1 bulan (31 hari) per unit = 31 bit = 4 byte. 10.000 unit × 12 bulan ke depan = ~480 KB di RAM Redis — trivial.
  • Atomik: SETBIT dan GETBIT di Redis bersifat atomic — tidak perlu lock tambahan untuk operasi single-bit.
  • Scan cepat: Mengecek ketersediaan multi-unit serentak cukup dengan pipeline GETBIT.

10.2 Booking State Timeline

stateDiagram-v2
    [*] --> PENDING_PAYMENT : Create Booking Request (Redlock acquired)
    PENDING_PAYMENT --> CANCELLED : Timeout 15 Menit / Manual Cancel
    PENDING_PAYMENT --> PAID_APPROVED : Payment Gateway Webhook OK
    PAID_APPROVED --> DISPATCHED : Inspector Check-out Handover
    DISPATCHED --> ACTIVE_RENTAL : Unit in Customer Possession
    ACTIVE_RENTAL --> EXTENSION_PENDING : Request Extension
    EXTENSION_PENDING --> ACTIVE_RENTAL : Approved (Additional Payment)
    EXTENSION_PENDING --> ACTIVE_RENTAL : Rejected (Return on Schedule)
    ACTIVE_RENTAL --> RETURNED_PENDING_CHECK : Inspector Check-in Handover
    RETURNED_PENDING_CHECK --> DISPUTED : Damages / Late Return Detected
    RETURNED_PENDING_CHECK --> COMPLETED : Clear Return
    DISPUTED --> COMPLETED : Fine Paid / Deposit Deducted

Catatan: saat status CANCELLED atau COMPLETED, bit Redis direset ke 0 agar tanggal kembali tersedia.

10.3 Waitlist Automation

Jika seluruh unit SKU tertentu sudah penuh untuk tanggal yang diminta:

  1. Pelanggan menekan tombol "Ingatkan Saya / Antrean".
  2. Sistem memasukkan entri ke Redis Sorted Set:
    ZADD waitlist:TOY-AVNZ-G:20260525 <score> <user_id>
    
    Score = (tier_weight × 10^9) + unix_timestamp — member tier lebih tinggi dapat prioritas lebih baik.
  3. Jika penyewa membatalkan pesanan, sistem BullMQ menjalankan job ProcessWaitlistJob:
  4. Ambil member teratas dari Sorted Set (ZPOPMIN).
  5. Kirim link pembayaran unik via WhatsApp dengan masa aktif 15 menit.
  6. Jika tidak direspons dalam 15 menit, lanjut ke member berikutnya.

10.4 Maintenance Blocking

Saat aset masuk status MAINTENANCE, sistem secara otomatis memblokir bit Redis untuk seluruh estimasi downtime:

# Contoh: unit masuk service tanggal 26 s.d 28 Mei 2026
SETBIT avail:TOY-AVNZ-G:uuid-avanza-001:202605 25 1
SETBIT avail:TOY-AVNZ-G:uuid-avanza-001:202605 26 1
SETBIT avail:TOY-AVNZ-G:uuid-avanza-001:202605 27 1

Unit tidak akan muncul di katalog depan pelanggan selama periode ini.