Lewati ke konten

Skema Data & Tabel Kanonik

Skema Postgres Catera tumbuh dari proses migrasi data Convex → Supabase yang dilakukan bertahap per domain, bukan “big bang” satu kali. Ini menghasilkan dua lapis tabel yang hidup berdampingan selama masa transisi.

1. Landing zone JSONB — legacy_documents

Section titled “1. Landing zone JSONB — legacy_documents”

Saat sebuah domain data belum dimigrasikan ke tabel kanonik, baris data disimpan generik di public.legacy_documents dengan kolom table_name (nama koleksi asal) dan document (JSONB berisi field aslinya). Pola ini memungkinkan aplikasi tetap berjalan terhadap Supabase sejak awal cutover, sebelum setiap domain satu per satu mendapat tabel kanoniknya sendiri.

Domain yang sudah “naik kelas” mendapat tabel bertipe sendiri di public (mis. employees, attendance_records), dengan kolom asli JSONB tetap disimpan di kolom raw_document untuk kompatibilitas mundur selama masa transisi, didampingi fungsi project_<domain>() yang mem-parse dokumen JSONB legacy menjadi baris kanonik tersebut. Pola ini terlihat konsisten di seluruh migrasi domain kanonik, misalnya project_employee() dan project_attendance_record() di supabase/migrations/20261011120000_employees_attendance_canonical.sql.

Domain yang sudah punya migrasi kanonik pada repo ini antara lain (lihat nama berkas): pelanggan (write-path projection), master produk/inventori, sales-config/zona/promo, komplain & food-waste, karyawan & absensi, langganan (subscriptions), invoice, konfigurasi CCTV, payroll inti, THR, pinjaman karyawan, dan faktur pajak.

Kode frontend tidak langsung berasumsi tabel kanonik sudah siap. Helper seperti readHrTable() (src/features/hr/supabase-hr.ts) membaca tabel kanonik hanya jika:

  1. Flag VITE_SUPABASE_CANONICAL_CONFIG_READS=true diaktifkan, dan
  2. Jumlah baris di tabel legacy dan kanonik untuk domain itu sudah sama (dicek lewat count query, di-cache sementara per domain).

Jika salah satu syarat tidak terpenuhi, kode otomatis jatuh ke pembacaan legacy_documents. Pola ini membuat rollout per-domain bisa dibatalkan (toggle flag) tanpa deploy ulang kode, dan mencegah UI menampilkan data kosong saat tabel kanonik baru separuh terisi.

public.profiles (lihat Model Keamanan) adalah tabel identitas inti yang terhubung 1:1 ke auth.users, menyimpan role dan status yang dipakai hampir semua fungsi RLS lain di database.

5. Skema landing migrasi (sekali pakai, bukan tabel operasional)

Section titled “5. Skema landing migrasi (sekali pakai, bukan tabel operasional)”

Schema terpisah migration (migration.runs, migration.convex_documents, migration.id_map, migration.storage_map) dipakai untuk mencatat proses impor data Convex → Supabase itu sendiri (bukan data operasional aplikasi) dan ditutup aksesnya dari public/anon/authenticated.


Sumber: supabase/migrations/0001_migration_control.sql, supabase/migrations/0002_identity_and_rls.sql, supabase/migrations/20261011120000_employees_attendance_canonical.sql, src/features/hr/supabase-hr.ts.