Files
apskel-pos-backend/docs/tasks-enakgame.md
T
efrilmandClaude Opus 5.5 3ebc09f818 docs(enakgame): PRD, RFC, and task breakdown
EnakGame: pay EnakCoin to play, earn EnakCoin from the result, exchange
into EnakPoint, and redeem EnakPoint for vouchers only.

- enakgame-prd.md: economy and business rules, including entry cost and
  automatic refund, monthly global budget with a separate budget per
  event (event = campaign), and EnakPoint being voucher-only.
- rfc-enakgame.md: built on the existing wallet, ledger and lots. Game
  sessions with a state machine, versioned reward configs, Economy Guard
  counters, vouchers with internal codes and external providers, and
  realized cost attributed to budgets by tracing the lots spent.
- tasks-enakgame.md: EG-001 to EG-1003 in eleven phases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:48:17 +07:00

23 KiB
Raw Blame History

Task Breakdown: EnakGame

Sumber: RFC EnakGame, PRD EnakGame Tanggal: 2026-10-07

Setiap task menyebut bagian RFC yang dikerjakan, lapisan kode yang disentuh, task yang harus selesai lebih dulu, dan kriteria selesai. Ukuran: S ≤ 1 hari, M 2–3 hari, L 4–5 hari.

Konvensi kode mengikuti yang sudah ada: migrations/ (lanjut dari 000101), entities → repository → processor → service → handler / validator → router, dan wiring di internal/app/app.go. Repository selalu memakai DBFromContext. Semua mutasi saldo hanya lewat WalletProcessor.


Ringkasan

Fase Task Terblokir oleh
0. Matikan bayar dengan EnakPoint EG-001 – EG-002 –
1. Fondasi EG-101 – EG-106 –
2. Admin game & session EG-201 – EG-206 –
3. Reward Engine & complete EG-301 – EG-303 Pembulatan (RFC §19.2 #1) sebelum rilis
4. Economy Guard EG-401 – EG-402 –
5. Voucher & redemption EG-501 – EG-507 –
6. Budget metrics EG-601 – EG-602 Exhaustion policy & threshold (#3, #4) sebelum rilis
7. Event / campaign EG-701 – EG-704 Event stacking (#2) sebelum rilis
8. Voucher eksternal EG-801 – EG-803 Provider pertama yang konkret sebelum dikerjakan
9. Budget Controller & analytics EG-901 – EG-903 Threshold (#4) sebelum dikerjakan
10. Spin & bersih-bersih EG-1001 – EG-1003 –

Fase 0 independen dan bisa jalan paralel dengan semua fase lain, tetapi harus selesai sebelum EnakGame rilis (PRD §3.2).

Fase 1–3 membuat game bisa dimainkan end-to-end dengan Coin. Fase 5 membuat Point bisa ditukar. Fase 6 membuat Finance bisa melihat biaya.

Fase 0   EG-001 ── EG-002

Fondasi  EG-101 ── EG-102 ── EG-105
         EG-103, EG-104, EG-106, EG-301 (independen)

Game     EG-104 + EG-105 ─────────────────── EG-201, EG-203
         EG-104 + EG-105 + EG-301 ────────── EG-202
         EG-103 + EG-201 + EG-202 + EG-203 ─ EG-204 ── EG-205
         EG-204 + EG-205 + EG-301 + EG-302 ─ EG-303
         EG-106 ── EG-401
         EG-303 + EG-401 ─────────────────── EG-402

Voucher  EG-501 ── EG-502
         EG-103 + EG-502 + EG-503 ────────── EG-504
         EG-303 + EG-504 ─────────────────── EG-505 ── EG-601 ─┬─ EG-602
                                                               └─ EG-901 ── EG-902
         EG-504 ── EG-801
         EG-505 + EG-801 ─────────────────── EG-802 ── EG-803

Event    EG-102 ── EG-701
         EG-203 + EG-701 ─────────────────── EG-702
         EG-402 + EG-702 ─────────────────── EG-703

Akhir    EG-402 ── EG-1001 ── EG-1002 ── EG-1003

Task kecil yang tidak digambar: EG-206, EG-302 (setelah EG-105), EG-506 (EG-504), EG-507 (EG-501), EG-704 (EG-206 + EG-702), EG-903 (EG-303 + EG-505).


Fase 0 — Matikan Bayar dengan EnakPoint

PRD §3.2: Point hanya bisa ditukar ke voucher. Belum ada order yang dibayar dengan Point, jadi tidak ada data yang dimigrasi.

EG-001 · Tutup semua jalur pembayaran EnakPoint · M

  • RFC: §14
  • Kerjakan:
    • Sudah dikonfirmasi belum ada pembayaran dengan EnakPoint di production (2026-10-07).
    • Migrasi: drop trigger yang membuat payment method point untuk organisasi baru (000094), lalu nonaktifkan / hapus baris payment_methods tipe point.
    • Tolak pembayaran bertipe point di jalur POS (order_handler, order_processor, payment_method_processor) dan customer app (customer_order_payment_service).
    • Hapus route GET /orders/:id/point-payment/preview dan POST /customer/wallet/payment-code.
    • Hapus PAYMENT dan PAYMENT_REFUND dari walletTypeRules, supaya engine menolak keduanya. CHECK database dibiarkan.
    • Hapus setting loyalty.point.accept_payment dari descriptor LoyaltySettingsProcessor dan dari response outlet customer.
  • Selesai jika: pembayaran order dengan method point ditolak di POS dan customer app, outlet baru tidak lagi mendapat payment method EnakPoint, dan test yang ada diperbarui.
  • Bergantung pada: –

EG-002 · Hapus kode point payment · S

  • Kerjakan: hapus PointPaymentProcessor, point_payment_refund.go, PointPaymentRepository, PointPaymentService, PointPaymentHandler, wiring di app.go / router.go, dan test-nya (point_payment_db_test.go, point_payment_method_db_test.go). Pindahkan dulu helper yang ternyata dipakai di tempat lain (mis. pola pembuatan lot refund, yang dipakai ulang di EG-205).
  • Selesai jika: go build ./... dan seluruh test lulus, dan grep -rn "PointPayment" internal/ kosong.
  • Bergantung pada: EG-001

Fase 1 — Fondasi

EG-101 · Migrasi extend games + arsipkan game lama · S

  • RFC: §5.1, §14
  • Kerjakan: migrasi up & down persis seperti §5.1. Semua baris lama menjadi ARCHIVED. Tidak ada DELETE (FK game_plays CASCADE).
  • Selesai jika:
    • Up/down bersih di database kosong dan di salinan staging.
    • Jumlah baris game_plays sebelum = sesudah.
    • Ditolak database: game ACTIVE tanpa organization_id atau slug; entry_cost = 0; dua game dengan slug sama di satu org.
  • Bergantung pada: –

EG-102 · Migrasi budget, reward config, session · M

  • RFC: §5.2, §5.3, §5.4, §5.6
  • Kerjakan: game_budgets, game_reward_configs, game_sessions, game_session_rewards, dalam urutan foreign key.
  • Selesai jika: up/down bersih. Ditolak database: dua config ACTIVE untuk satu game; session REFUNDED tanpa refund_transaction_id; dua budget GLOBAL dengan period_start sama di satu org; game_session_rewards dengan wallet_transaction_id yang sama dua kali.
  • Bergantung pada: EG-101

EG-103 · Tipe ledger baru · M

  • RFC: §6
  • Kerjakan:
    • Konstanta GAME_SPEND_REFUND, GAME_REWARD, REWARD_REDEEM_REFUND, ref GAME_SESSION di constants/wallet.go.
    • walletTypeRules: tambah tiga tipe, dan izinkan ref GAME_SESSION pada GAME_SPEND.
    • Migrasi: drop + create ulang tiga CHECK di wallet_transactions (§6.2).
    • Periksa invariant di wallet_reconciliation_repository.go terhadap tipe baru.
  • Selesai jika: test validasi di wallet_processor_test.go per tipe baru (currency salah, ref salah, reversal tanpa reverses_transaction_id → ditolak), dan test DB yang benar-benar insert ke wallet_transactions untuk setiap tipe (lolos engine dan CHECK).
  • Bergantung pada: –

EG-104 · audit_logs + helper · S

  • RFC: §5.9, §13
  • Kerjakan: migrasi, entity, dan AuditLogger.Record(ctx, entry) yang menulis lewat DBFromContext, sehingga audit ikut commit/rollback bersama perubahannya.
  • Selesai jika: perubahan yang di-rollback tidak meninggalkan baris audit.
  • Bergantung pada: –

EG-105 · Entities & repository EnakGame · M

  • RFC: §5.1–§5.6
  • Kerjakan: entities dan repository untuk kolom baru games, game_reward_configs, game_sessions, game_session_rewards, game_budgets. Transisi status session sebagai UPDATE ... WHERE status = 'STARTED' yang mengembalikan jumlah baris ter-update (D4). Semua query game/budget memfilter organization_id.
  • Selesai jika: test repository: dua transisi bersamaan pada session yang sama, hanya satu yang mendapat 1 baris.
  • Bergantung pada: EG-101, EG-102

EG-106 · Setting limit EnakGame · S

  • RFC: §5.10
  • Kerjakan: key enakgame.limit.user_daily dan enakgame.limit.global_daily sebagai field descriptor di LoyaltySettingsProcessor (default 0 = tanpa batas, min 0).
  • Selesai jika: setting terbaca dengan default, bisa diubah lewat endpoint loyalty settings yang ada, dan perubahan tercatat di loyalty_setting_changes.
  • Bergantung pada: –

Fase 2 — Admin Game & Session

EG-201 · Admin game CRUD · M

  • RFC: §11 (admin)
  • Kerjakan: /marketing/enakgame/games CRUD + PUT /:id/status, org dari user admin. Validasi slug, entry_cost ≥ 1, result_rules. Game ARCHIVED tidak bisa diubah. Perubahan status masuk audit_logs.
  • Selesai jika: admin org A tidak bisa melihat atau mengubah game org B; game lama (arsip) tidak muncul.
  • Bergantung pada: EG-104, EG-105

EG-202 · Admin reward config versioning · M

  • RFC: §5.2, D7
  • Kerjakan: POST /games/:id/reward-configs (versi baru, rules divalidasi RewardCalculator.Validate), POST /reward-configs/:id/activate (dalam satu transaksi: config lama → RETIRED, yang baru → ACTIVE), GET daftar versi. Tidak ada endpoint update atau delete. Wajib RequireLoyaltyManager. Semua aksi masuk audit_logs.
  • Selesai jika: config yang sudah dipakai session tidak bisa diubah lewat jalur apa pun; aktivasi bersamaan dua versi berakhir dengan tepat satu ACTIVE.
  • Bergantung pada: EG-104, EG-105, EG-301

EG-203 · Admin budget + GameBudgetPeriodJob · M

  • RFC: §5.6, §12
  • Kerjakan: CRUD /marketing/enakgame/budgets (scope GLOBAL / EVENT), wajib RequireLoyaltyManager, audit. Job harian yang membuat budget global bulan berikutnya dari bulan berjalan bila belum ada.
  • Selesai jika: job aman dijalankan berulang (unique index mencegah duplikat), dan perubahan amount tercatat sebelum/sesudah di audit.
  • Bergantung pada: EG-104, EG-105

EG-204 · Start Game · M

  • RFC: §7.1
  • Kerjakan: POST /customer/enakgame/sessions dengan Idempotency-Key wajib (≤ 50 karakter, pola customer_wallet_handler.go). Langkah persis §7.1.
  • Selesai jika: test untuk:
    • Key yang sama dua kali → satu debit, session yang sama dikembalikan.
    • Coin kurang → ditolak, tidak ada ledger maupun session.
    • Game org lain, game tidak ACTIVE, tanpa config aktif, tanpa budget global → ditolak.
    • entry_cost dan reward_config_id tersimpan sebagai snapshot: mengubah game setelah start tidak mengubah session.
  • Bergantung pada: EG-103, EG-105, EG-201, EG-202, EG-203

EG-205 · Refund otomatis + GameSessionJob · M

  • RFC: §7.3, §6.3
  • Kerjakan:
    • RefundSession(ctx, sessionID, reason): lock wallet → transisi bersyarat ke REFUNDED → Credit GAME_SPEND_REFUND dengan lot per alokasi asal (RefundExpiry, origin_lot_id) → audit SYSTEM.
    • Job tiap 1 menit, per batch, satu transaksi per session, sesuai tabel §7.3.
    • Wiring start/stop di app.go seperti WalletExpiryJob.
  • Selesai jika: test untuk:
    • Game dinonaktifkan → session STARTED di-refund tanpa menunggu kedaluwarsa.
    • Expired dengan completion_failed_at → refund. Expired tanpa → EXPIRED, saldo tetap.
    • Lot refund punya origin_lot_id ke lot asal dan expires_at minimal 7 hari.
    • Complete dan refund bersamaan pada session yang sama → tepat satu yang berhasil.
    • Job dijalankan dua kali → tidak ada refund ganda.
  • Bergantung pada: EG-204

EG-206 · Customer: daftar game & riwayat session · S

  • RFC: §11 (customer)
  • Kerjakan: GET /customer/enakgame/games, GET /sessions, GET /sessions/:id. Hanya game ACTIVE milik org customer. Rincian internal (reward_breakdown lengkap, angka RNG) tidak ditampilkan.
  • Bergantung pada: EG-105

Fase 3 — Reward Engine & Complete

EG-301 · RewardCalculator + empat tipe · M

  • RFC: §8
  • Kerjakan: interface Validate / Calculate, implementasi FIXED, SCORE_BASED, OUTCOME_BASED, PROBABILITY. RNG lewat interface yang diisi crypto/rand di production dan RNG tetap di test. Pembulatan ke bawah.
  • Selesai jika: unit test: contoh tabel PRD §12 untuk setiap tipe; band skor tumpang tindih / berlubang ditolak Validate; bobot PROBABILITY nol atau negatif ditolak; distribusi PROBABILITY pada 100.000 undian berada dalam toleransi bobotnya.
  • Bergantung pada: –

EG-302 · Result Validator · S

  • RFC: §7.2 langkah 5
  • Kerjakan: validasi result terhadap games.result_rules: durasi minimal, skor maksimum, skor per detik, outcome yang dikenal. Mengembalikan alasan, bukan error.
  • Selesai jika: unit test per aturan, termasuk game tanpa result_rules (semua lolos).
  • Bergantung pada: EG-105

EG-303 · Complete Game · L

  • RFC: §7.2, §7.3 (bagian completion_failed_at)
  • Kerjakan:
    • POST /customer/enakgame/sessions/:id/complete, langkah §7.2 dengan base reward dari budget global saja. Event menyusul di EG-703, guard di EG-402.
    • Satu baris GAME_REWARD + game_session_rewards per budget, key game-reward:{session}:{budget}. Lot dengan ComputeExpiry(CoinExpiry).
    • Game tidak ACTIVE saat complete → RefundSession(GAME_DEACTIVATED).
    • Error non-bisnis → tulis completion_failed_at di transaksi terpisah (DetachTransaction), lalu kembalikan 5xx.
  • Selesai jika: test untuk:
    • Complete dua kali → satu reward, response kedua sama dengan yang pertama.
    • Hasil tidak valid → reward 0, flagged, session COMPLETED, tanpa refund.
    • Session milik customer lain → 404. Session expired → ditolak.
    • Error yang disuntikkan setelah kredit → rollback total, completion_failed_at terisi.
    • Request yang membawa field reward diabaikan (P1).
  • Bergantung pada: EG-204, EG-205, EG-301, EG-302

Fase 4 — Economy Guard

EG-401 · Counter reward + increment bersyarat · M

  • RFC: §5.8, §9
  • Kerjakan: migrasi game_reward_counters; repository Consume(scope, id, day, x, limit) yang mengembalikan jumlah yang benar-benar diterima (dipotong ke sisa limit, 0 bila habis). Hari dihitung di Asia/Jakarta.
  • Selesai jika: test DB: 20 goroutine menambah counter yang sama dengan limit 100 → total tepat 100, tidak pernah lewat.
  • Bergantung pada: EG-106

EG-402 · Guard di complete · S

  • RFC: §9
  • Kerjakan: panggil Consume untuk USER dan GLOBAL harian (dari setting) dan GAME harian (dari result_rules) sebelum kredit. Batas yang memotong dicatat di reward_breakdown dan dikembalikan di response.
  • Selesai jika: reward 30 dengan sisa limit user 10 → kredit 10, breakdown menyebut limit user. Sisa 0 → session COMPLETED dengan reward 0.
  • Bergantung pada: EG-303, EG-401

Fase 5 — Voucher & Redemption

EG-501 · Migrasi voucher · M

  • RFC: §5.7
  • Kerjakan: vouchers, voucher_codes, voucher_redemptions, voucher_redemption_costs.
  • Selesai jika: up/down bersih. Ditolak database: voucher STATIC tanpa stock; EXTERNAL tanpa provider; kode REDEEMED tanpa redemption_id; dua redemption dengan (customer_id, idempotency_key) yang sama.
  • Bergantung pada: –

EG-502 · Admin voucher + impor kode · M

  • RFC: §11 (admin)
  • Kerjakan: CRUD /marketing/enakgame/vouchers, POST /:id/codes (CSV, kode duplikat dilewati dan dilaporkan), GET /:id/codes dengan jumlah per status. RequireLoyaltyManager dan audit.
  • Selesai jika: impor CSV yang sama dua kali tidak menggandakan kode.
  • Bergantung pada: EG-104, EG-501

EG-503 · Aksi PIN REDEEM · S

  • RFC: §7.4 langkah 2
  • Kerjakan: PinActionRedeem di customer_pin_processor.go, ikut aturan kunci yang ada (5 salah, 30 menit).
  • Bergantung pada: –

EG-504 · Redemption internal · L

  • RFC: §7.4
  • Kerjakan: POST /customer/enakgame/vouchers/:id/redeem untuk STATIC dan CODE_POOL, satu transaksi, langkah persis §7.4. Debit REWARD_REDEEM dengan key redeem:{redemption}.
  • Selesai jika: test untuk:
    • Stok tersisa 1, dua customer menukar bersamaan → tepat satu berhasil.
    • CODE_POOL: dua redemption bersamaan mendapat kode berbeda (SKIP LOCKED).
    • Key yang sama dua kali → satu debit, satu kode.
    • Point kurang, PIN salah, max_per_customer tercapai, voucher di luar masa berlaku → ditolak tanpa apa pun tercatat.
  • Bergantung pada: EG-103, EG-501, EG-502, EG-503

EG-505 · Atribusi realized cost · M

  • RFC: §7.6, D5
  • Kerjakan: query rekursif §7.6 di dalam transaksi redemption, pembagian face_value proporsional dengan sisa pembulatan ke bagian terbesar, insert voucher_redemption_costs.
  • Selesai jika: test DB untuk rantai: GAME_REWARD → exchange → redeem; GAME_REWARD → transfer → exchange → redeem; campuran GAME_REWARD + EARN (contoh §7.6: Rp7.500 ke budget, Rp2.500 tanpa budget); Σ cost = face_value untuk kombinasi angka yang tidak habis dibagi.
  • Bergantung pada: EG-303, EG-504

EG-506 · Customer: katalog & voucher saya · S

  • RFC: §11 (customer)
  • Kerjakan: GET /customer/enakgame/vouchers (stok tersedia, tanpa membocorkan jumlah kode per status) dan GET /redemptions (dengan kode voucher).
  • Bergantung pada: EG-504

EG-507 · VoucherCodeExpiryJob · S

  • RFC: §12
  • Kerjakan: AVAILABLE → EXPIRED untuk kode lewat expires_at, per batch.
  • Bergantung pada: EG-501

Fase 6 — Budget Metrics

EG-601 · Perhitungan metrik & status budget · M

  • RFC: §10
  • Kerjakan: realized cost, Coin issued, remaining, utilization, forecast, exposure, dan status per budget. Global dibatasi periode; event tanpa batas waktu. Threshold dari game_budgets.thresholds.
  • Selesai jika: test dengan data tetap menghasilkan angka contoh PRD §30 (budget Rp100M, realized Rp60M, sisa 10 hari); Point dari EARN tidak ikut dihitung.
  • Bergantung pada: EG-505

EG-602 · Endpoint metrik budget · S

  • Kerjakan: GET /marketing/enakgame/budgets/:id/metrics.
  • Bergantung pada: EG-601

Fase 7 — Event / Campaign

EG-701 · Migrasi event · S

  • RFC: §5.5
  • Kerjakan: game_events, game_event_games.
  • Selesai jika: up/down bersih; event tanpa budget_id atau dengan end_at ≤ start_at ditolak.
  • Bergantung pada: EG-102

EG-702 · Admin event · M

  • RFC: §5.5, §11
  • Kerjakan: CRUD + status. Budget yang dipasang harus milik org yang sama dan ber-scope EVENT. Audit.
  • Bergantung pada: EG-203, EG-701

EG-703 · Modifier event di complete · M

  • RFC: §7.2 langkah 7, §8 (modifier), D6
  • Kerjakan: cari event aktif untuk game, hitung tambahan dari multiplier dan bonus, pisahkan menjadi komponen per budget, terapkan reward_limit dan user_daily_limit event lewat counter EVENT, cap max_reward. Aturan tumpuk mengikuti default PRD §16.
  • Selesai jika: contoh PRD §7 (10 Coin + Ramadan 2x) menghasilkan dua baris GAME_REWARD: 10 ke budget global, 10 ke budget event; event di luar jam aktif tidak berpengaruh.
  • Bergantung pada: EG-402, EG-702

EG-704 · Event di daftar game customer · S

  • Kerjakan: GET /customer/enakgame/games menyertakan event aktif per game (nama, banner, multiplier/bonus, berakhir kapan).
  • Bergantung pada: EG-206, EG-702

Fase 8 — Voucher Eksternal

Terblokir sampai provider pertama ditentukan: API-nya menentukan bentuk adapter dan apakah provider menerima idempotency key (RFC §18).

EG-801 · Interface provider + adapter pertama · M

  • Kerjakan: VoucherProvider (Issue(ctx, redemptionID, voucher), Lookup(ctx, redemptionID)), adapter provider pertama, dan klasifikasi hasil: sukses, gagal pasti, tidak jelas.
  • Bergantung pada: EG-504

EG-802 · Redemption dua tahap · M

  • RFC: §7.5
  • Kerjakan: jalur EXTERNAL di endpoint redeem: transaksi 1 (PENDING + debit), panggil provider di luar transaksi, transaksi 2 (COMPLETED + atribusi, atau FAILED + REWARD_REDEEM_REFUND).
  • Selesai jika: test dengan provider palsu untuk ketiga hasil; timeout meninggalkan PENDING dengan Point terpotong dan response "sedang diproses".
  • Bergantung pada: EG-505, EG-801

EG-803 · VoucherRedemptionRecoveryJob · M

  • RFC: §7.5 langkah 4, §12
  • Kerjakan: ambil PENDING lewat N menit, Lookup ke provider, selesaikan transaksi 2. Setelah batas percobaan → refund + FAILED.
  • Selesai jika: tidak ada redemption yang tertinggal PENDING melewati batas percobaan; job berjalan dua kali tidak merefund dua kali.
  • Bergantung pada: EG-802

Fase 9 — Budget Controller & Analytics

EG-901 · Rekomendasi multiplier · M

  • RFC: §10 (rekomendasi), PRD §30–§31
  • Kerjakan: hitung multiplier yang membuat forecast = budget, dibatasi step maksimum dan min/max multiplier. GET /budgets/:id/recommendation.
  • Bergantung pada: EG-601

EG-902 · Terima rekomendasi · S

  • Kerjakan: admin menerima rekomendasi → reward config versi baru dibuat dari config aktif dengan angka yang disesuaikan, tercatat di audit dengan source = budget_controller.
  • Bergantung pada: EG-202, EG-901

EG-903 · Analytics · M

  • RFC: PRD §36
  • Kerjakan: endpoint dashboard game (plays, completed, rata-rata skor & reward, Coin issued, entry cost dibayar, Coin di-refund) dan economy (Coin generated / spent / expired / outstanding, Point redeemed), per org dan rentang tanggal.
  • Bergantung pada: EG-303, EG-505

Fase 10 — Spin & Bersih-bersih

EG-1001 · Spin sebagai game EnakGame · S

  • RFC: §14
  • Kerjakan: seeder / langkah admin untuk game spin baru dengan config PROBABILITY dan reward Coin. Client Phaser di luar repo ini.
  • Selesai jika: spin bisa dimainkan lewat /customer/enakgame/sessions end-to-end.
  • Bergantung pada: EG-402

EG-1002 · Hapus alur game lama · M

  • RFC: §14, §15
  • Kerjakan: hapus route POST /customer/spin, GET /customer/games, GET /customer/ferris-wheel, admin /marketing/games, /marketing/game-prizes, dan /marketing/rewards, beserta handler, service, processor, dan test-nya (GamePlayProcessor, SpinGameService, dan seterusnya). Tabel games, game_prizes, game_plays tetap ada untuk riwayat ledger.
  • Selesai jika: build dan test lulus; aplikasi customer sudah tidak memanggil endpoint lama (konfirmasi tim aplikasi).
  • Bergantung pada: EG-1001. Tabel rewards tidak punya data produksi (dikonfirmasi 2026-10-07), jadi tidak ada yang dipindah ke vouchers.
  • Catatan: endpoint customer lama boleh dimatikan lebih awal, kapan pun, untuk menutup temuan RFC §15 nomor 1 dan 2.

EG-1003 · Bersihkan kolom lama games · S

  • Kerjakan: drop games.is_active dan berhenti membaca metadata.coin_cost.
  • Bergantung pada: EG-1002

Yang Bisa Dimulai Sekarang

Bisa dikerjakan paralel tanpa menunggu apa pun:

  • EG-001 (matikan bayar dengan EnakPoint) → EG-002
  • EG-101 → EG-102 → EG-105 (skema & repository)
  • EG-103 (tipe ledger)
  • EG-104 (audit), EG-106 (setting limit)
  • EG-301 (Reward Engine, kode murni tanpa database)
  • EG-501, EG-503 (fondasi voucher)

Jalur kritis: EG-105 → EG-204 → EG-303 → EG-402. Hampir semua fase setelahnya menunggu complete game selesai.