# Rencana Migrasi Arsitektur: Monolithic ke Modular Monolith

Rencana ini menjabarkan strategi bertahap untuk memigrasikan database *holding* (`san_30mar`) dari arsitektur Monolithic (tabel tunggal `transaksi_data_registry` dengan `longblob`) menjadi arsitektur **Modular Monolith** dengan meniru dan menyempurnakan struktur *subsidiary* (`san_tsa_28agu` / `san_sarana_30jun`).

Menggunakan pendekatan **Strangler Fig Pattern**, sistem akan dimigrasikan modul demi modul untuk menekan risiko operasional hingga angka 0%.

## User Review Required

> [!CAUTION]
> **Risiko Operasional & Estimasi Waktu:**
> Proyek migrasi ini diproyeksikan memakan waktu **6 hingga 12 bulan** karena melibatkan 50+ modul aktif. Proses ini membutuhkan rombak ulang logika penyimpanan (*source code* PHP CodeIgniter) yang ada di aplikasi *holding*. 
> 
> **Mohon Konfirmasi:** Jika perusahaan membutuhkan ruang penyimpanan (*storage*) secara instan dalam 1 bulan ke depan, solusi **Database Cut-Off (Tutup Buku)** harus dijalankan terlebih dahulu sebelum menjalankan rencana migrasi arsitektur jangka panjang ini.

## Open Questions

> [!WARNING]
> 1. **Daftar Modul Prioritas:** Modul manakah dari 50+ modul tersebut yang memiliki ukuran data transaksi terbesar? Kita akan menjadikannya *Pilot Project* (percobaan pertama) untuk menguji efektivitas metode migrasi ini.

---

## Proposed Changes (Fase Migrasi Bertahap)

### Fase 1: Persiapan & Pondasi Arsitektur (Bulan 1)
Fase ini dilakukan murni di belakang layar. Tidak ada perubahan logika penyimpanan yang terjadi di aplikasi yang sedang berjalan (*Production*).

*   **Langkah 1: Ekstraksi Skema `longblob`** 
    Buat *script* PHP khusus untuk melakukan *query* (misal: `SELECT * FROM transaksi_data_registry LIMIT 100`). Jalankan fungsi `unserialize()` atau `json_decode()` pada kolom `main` dan `items` untuk mengurai variabel-variabel yang tersembunyi di dalamnya.
*   **Langkah 2: Pembuatan Dokumen Mapping** 
    Petakan variabel hasil urai di Langkah 1 ke dalam bentuk kolom relasional SQL. Contoh: variabel `["tanggal_transaksi"]` dipetakan menjadi kolom `tgl_transaksi (DATE)`.
*   **Langkah 3: Pembuatan Struktur Tabel Modular Baru (Kosong)** 
    DBA mengeksekusi sintaks `CREATE TABLE` (contoh: `pembelian_transaksi_data_registry` dan `pembelian_transaksi_detail`) di database `san_30mar`. Tabel lama tidak boleh disentuh atau dihapus.
*   **Langkah 4: Pembuatan `Class Adapter` (`MdlMother`) di CodeIgniter** 
    Buat *Class* induk (seperti di subsidiary) yang akan bertugas sebagai "Pengatur Lalu Lintas". Class ini memiliki fungsi `insert()` dan `update()` tersendiri.
*   **Langkah 5: Setup Server Staging** 
    Salin ( *copy* ) database *Production* `san_30mar` beserta kode *source code* aplikasi ke *server Staging* untuk ujicoba tertutup.

### Fase 2: Implementasi Modul "Pilot" (Contoh: Modul Pembelian) (Bulan 2)
Menerapkan jembatan kode untuk modul target pertama di *server Staging*.

*   **Langkah 1: Pembuatan Domain Model Pembelian** 
    Buat file `MdlPembelianTransaksi.php` yang merupakan turunan (*extends*) dari `MdlMother`. Definisikan nama tabel (`pembelian_transaksi_data_registry`) dan kolom-kolom terkait di dalam class tersebut.
*   **Langkah 2: Refactoring Controller Pembelian** 
    Ubah *source code* di semua *Controller* terkait Pembelian. Hapus sintaks lama seperti `$this->db->insert('transaksi_data_registry')` dan ganti dengan pemanggilan ke model domain baru: `$this->MdlPembelianTransaksi->simpan($data)`.
*   **Langkah 3: Normalisasi Detail Transaksi (Krusial)** 
    Saat *Controller* mengirim data barang (items) ke Model, instruksikan model untuk menyimpannya baris-demi-baris (satu baris per barang) ke dalam tabel relasional murni `pembelian_transaksi_detail`, BUKAN menggumpalkannya kembali menjadi bentuk *blob/JSON*.
*   **Langkah 4: Validasi Logika di Staging** 
    Lakukan uji coba penyimpanan ( *input data* ) transaksi baru dan pastikan data tersimpan dengan rapi di tabel modular.

### Fase 3: Dual-Write & Data Backfill (Bulan 2-3)
Proses krusial menyalin jutaan data histori tanpa mengganggu operasional.

*   **Langkah 1: Setup Logika Dual-Write (Sistem Ganda)** 
    Modifikasi `MdlMother` sehingga ketika menyimpan transaksi pembelian baru, data ditulis ke tabel `pembelian_*` (baru) **DAN** secara otomatis direplika/ditulis dalam format `longblob` ke tabel global lama. Ini memastikan modul Akuntansi/Gudang yang belum dimigrasi tidak mengalami "kehilangan data" pembelian.
*   **Langkah 2: Deployment ke Production** 
    Rilis (*deploy*) kode *Dual-Write* modul Pembelian ini ke server *Production*. Operasional perusahaan berlanjut normal.
*   **Langkah 3: Eksekusi *Cron Job* Data Backfill (Migrasi Histori)** 
    Jalankan *script* malam hari untuk menarik semua data pembelian histori (5-10 tahun ke belakang) dari tabel global lama, mengubahnya dari `longblob` ke data berkolom, lalu menyuntikkannya ke tabel `pembelian_*` yang baru.

### Fase 4: Cut-Over & Pembersihan Storage (Bulan 3)
Pemutusan total dari sistem lama untuk modul Pembelian.

*   **Langkah 1: Verifikasi Integrasi Data** 
    Jalankan *script* validasi (*Checksum*) untuk memastikan total Rp dan Kuantitas di tabel baru persis sama dengan di tabel lama.
*   **Langkah 2: Hard Cut-Over (Mematikan Dual-Write)** 
    Hapus/matikan instruksi penulisan ke tabel global lama (Dual-Write) di `MdlMother`. Modul Pembelian kini resmi 100% independen (hanya membaca dan menulis di tabel modular barunya).
*   **Langkah 3: Penghapusan Blob Historis (Storage Recovery)** 
    Jalankan perintah `DELETE FROM transaksi_data_registry WHERE jenis = 'pembelian'`. Ruang *storage* yang membengkak akibat *longblob* pembelian akan terbebaskan secara signifikan.

### Fase 5: Iterasi Sisa Modul (Bulan 4-12)
*   **Langkah 1: Repetisi Massal secara Paralel** 
    Gunakan alur Fase 2 hingga Fase 4 untuk mengeksekusi sisa 49 modul lainnya (Penjualan, HRD, Produksi, dll). Proses ini bisa dilakukan secara paralel oleh beberapa *developer* karena setiap domain modul kini sudah mandiri.
*   **Langkah 2: Penghapusan Tabel Global (*Sunsetting*)** 
    Setelah modul terakhir sukses dimigrasi, tabel raksasa `transaksi_data_registry` akan dikosongkan total dan dapat dihancurkan (`DROP TABLE`) selamanya.

---

## Verification Plan

Langkah validasi untuk memastikan tidak ada sepeser pun data bisnis yang meleset (*zero data loss*).

### Automated & Data Tests
- **Data Integrity / Checksum Script:** Menjalankan perbandingan logika algoritmik antara total nilai (Rupiah/Kuantitas) di data `longblob` versi lama dengan total nilai yang ada di kolom-kolom tabel baru. *Script* harus memberikan laporan **PASS** tanpa selisih (Rp 0).

### Manual Verification
- **UAT (User Acceptance Testing) per Divisi:** Saat masa *Dual-Write* (Fase 3) berlangsung, kepala divisi terkait (misal: Kepala Pembelian) harus memeriksa laporannya setiap hari untuk memastikan hasil akhir transaksi lama maupun baru muncul dengan sempurna.
