# Runbook Cutover Stok Telur Historis Kandang ke Gudang Farm ## Tujuan Runbook ini dipakai untuk memindahkan **stok telur historis yang masih on-hand di gudang kandang** ke **gudang farm** secara aman, audit-able, dan reversible. Cutover dilakukan dengan **transfer stok eksplisit**, bukan dengan mengubah `recording_eggs.product_warehouse_id` historis. ## Scope Runbook ini hanya untuk: - stok telur historis kandang-level yang masih punya saldo on-hand - lokasi yang masuk kategori **clean cutover** - lokasi yang sudah punya gudang farm Runbook ini **tidak** dipakai untuk: - lokasi overlap seperti `Cijangkar` - koreksi histori `recording_eggs` - migrasi stok non-telur ## Kebijakan yang Dikunci - Sumber qty yang dipindah adalah **`product_warehouses.qty` saat cutover** - Perintah dijalankan **per lokasi** - Wajib mulai dari `dry-run` - `--apply` hanya boleh dijalankan setelah review dry-run dan SQL checklist - Lokasi overlap tidak ikut otomatis kecuali ada approval khusus dan `--include-overlap` - Rollback hanya boleh dilakukan jika transfer hasil cutover belum dipakai transaksi turunan ## Lokasi Fase 1 Lokasi yang boleh dieksekusi pada fase pertama: - `Jamali` - `Cantilan` - `Darawati` - `Tamansari` Lokasi yang harus ditahan: - `Cijangkar` ## Prasyarat Sebelum eksekusi, pastikan: - backend sudah ter-deploy dengan command [main.go](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/cmd/migrate-legacy-egg-stock-to-farm/main.go) - reusable transfer core sudah ikut ter-deploy: - [transfer.service.go](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/internal/modules/inventory/transfers/services/transfer.service.go) - [system_transfer.go](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/internal/modules/inventory/transfers/services/system_transfer.go) - migrasi farm stock attribution sebelumnya sudah terpasang - akses database target sudah tersedia - environment target memakai SSL bila RDS mewajibkan, contoh: - `DB_SSLMODE=require` ## Catatan Output Command Mode `--output table` adalah mode operasional yang direkomendasikan. Mode `--output json` bisa dipakai, tetapi pada environment saat ini output JSON masih dapat didahului log bootstrap aplikasi atau SQL logger. Untuk review manual gunakan `table`. Untuk parsing otomatis, filter payload mulai dari `{`. ## Format Command ### Dry-run ```bash DB_SSLMODE=require go run ./cmd/migrate-legacy-egg-stock-to-farm \ --location-name Jamali \ --output table ``` ### Apply ```bash DB_SSLMODE=require go run ./cmd/migrate-legacy-egg-stock-to-farm \ --location-name Jamali \ --cutover-date 2026-04-07 \ --apply \ --output table ``` ### Rollback Preview ```bash DB_SSLMODE=require go run ./cmd/migrate-legacy-egg-stock-to-farm \ --rollback-run-id \ --output table ``` ### Rollback Apply ```bash DB_SSLMODE=require go run ./cmd/migrate-legacy-egg-stock-to-farm \ --rollback-run-id \ --apply \ --output table ``` ## Arti `run_id` Setiap dry-run/apply menghasilkan `run_id`, misalnya: ```text egg-cutover-20260407T130344.220407000Z ``` `run_id` ini wajib disimpan karena dipakai untuk: - audit hasil cutover - query verifikasi - rollback ## Prosedur Eksekusi Per Lokasi ### 1. Persiapan Tentukan: - `location_name` - `cutover_date` - operator yang bertanggung jawab Contoh: - lokasi: `Jamali` - cutover date: `2026-04-07` ### 2. Jalankan Dry-run ```bash DB_SSLMODE=require go run ./cmd/migrate-legacy-egg-stock-to-farm \ --location-name Jamali \ --output table ``` Yang harus dicek pada hasil dry-run: - status lokasi `CLEAN_CUTOVER` - semua baris yang akan dipindah punya `status=eligible` - gudang tujuan adalah gudang farm lokasi tersebut - qty yang dipindah masuk akal dan sesuai saldo on-hand aktual - tidak ada `missing_farm_warehouse` - tidak ada `overlap_location` ### 3. Jalankan Checklist SQL Before Gunakan file: - [legacy_egg_cutover_verification_checklist.sql](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/docs/sql/legacy_egg_cutover_verification_checklist.sql) Minimal pastikan: - lokasi memang clean cutover - stok telur kandang positif masih ada - gudang farm ada - belum ada transfer `EGG_FARM_CUTOVER` aktif untuk lokasi yang sama pada run yang akan dipakai ### 4. Simpan Evidence Sebelum Apply Simpan: - output dry-run - hasil query before - nama operator - waktu eksekusi Disarankan simpan dalam ticket / change record. ### 5. Jalankan Apply ```bash DB_SSLMODE=require go run ./cmd/migrate-legacy-egg-stock-to-farm \ --location-name Jamali \ --cutover-date 2026-04-07 \ --apply \ --output table ``` Setelah apply, simpan: - `run_id` - seluruh row dengan `transfer_id` - movement number yang terbentuk ### 6. Jalankan Checklist SQL After Masih menggunakan file: - [legacy_egg_cutover_verification_checklist.sql](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/docs/sql/legacy_egg_cutover_verification_checklist.sql) Minimal pastikan: - transfer header/detail tercatat untuk `run_id` - qty source berkurang sesuai transfer - qty farm bertambah sesuai transfer - total gabungan source+dest per produk per lokasi tetap sama - stok eligible tidak lagi tersedia di gudang kandang - stok telur sekarang tersedia di gudang farm ### 7. Smoke Test UI Lakukan minimal: - buka product stock farm untuk lokasi tersebut - pastikan produk telur hasil migrasi muncul - buat SO farm-level dan pastikan opsi produk telur tersedia - pastikan recording telur baru setelah cutover tetap langsung masuk ke gudang farm ### 8. Tutup Eksekusi Catat hasil akhir: - sukses/gagal - `run_id` - lokasi - tanggal cutover - operator - link ke evidence SQL/UI ## Kriteria Go / No-Go ### Boleh lanjut apply bila: - dry-run menunjukkan hanya row yang memang expected - lokasi `CLEAN_CUTOVER` - gudang farm valid - query before menunjukkan tidak ada anomaly blocking ### Wajib stop bila: - lokasi terdeteksi `OVERLAP` - ada qty aneh atau tidak sesuai data lapangan - gudang farm tidak ada - ada transfer lama serupa yang belum direkonsiliasi - setelah apply terjadi selisih total source+dest ## Rollback Runbook ### Kapan rollback boleh dilakukan Rollback boleh jika: - transfer hasil cutover belum dipakai transaksi turunan - verifikasi after menunjukkan issue yang membuat hasil cutover tidak dapat diterima ### Langkah rollback 1. Preview rollback: ```bash DB_SSLMODE=require go run ./cmd/migrate-legacy-egg-stock-to-farm \ --rollback-run-id \ --output table ``` 2. Jalankan query rollback readiness pada file audit/helper SQL. 3. Jika aman, apply rollback: ```bash DB_SSLMODE=require go run ./cmd/migrate-legacy-egg-stock-to-farm \ --rollback-run-id \ --apply \ --output table ``` 4. Jalankan ulang query verifikasi after rollback. ### Kapan rollback akan gagal by design Rollback memang harus gagal jika: - transfer hasil cutover sudah dipakai sales/recording/transaksi turunan - sudah ada `stock_allocations` consume aktif terhadap `STOCK_TRANSFER_IN` ## Urutan Rollout yang Direkomendasikan ### Dev 1. Dry-run per lokasi 2. Review SQL before 3. Apply per lokasi 4. SQL after 5. Smoke UI 6. Simpan `run_id` ### Production 1. Freeze operasional lokasi target bila perlu 2. Dry-run 3. Review by dev + ops + finance/stock owner 4. Apply 5. SQL after 6. Smoke UI 7. Release lokasi berikutnya ## Referensi - Command cutover: [main.go](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/cmd/migrate-legacy-egg-stock-to-farm/main.go) - Test command: [main_test.go](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/cmd/migrate-legacy-egg-stock-to-farm/main_test.go) - Core reusable transfer: [system_transfer.go](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/internal/modules/inventory/transfers/services/system_transfer.go) - Transfer service refactor: [transfer.service.go](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/internal/modules/inventory/transfers/services/transfer.service.go) - Checklist SQL: [legacy_egg_cutover_verification_checklist.sql](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/docs/sql/legacy_egg_cutover_verification_checklist.sql) - Helper query audit: [legacy_egg_cutover_audit_queries.sql](/Users/macbookair/Documents/coding/projects/LTI-ERP/lti-api/docs/sql/legacy_egg_cutover_audit_queries.sql)