KANTOR AI - PAKET LENGKAP ========================= Sistem kantor dengan karyawan AI untuk mengelola Instagram dan Threads klien UMKM. PHP 8 + MySQL. Bisa dipasang di hosting biasa atau XAMPP. Panduan lengkap dengan gambar langkah ada di Docs "Panduan Memasang dan Menguji Kantor AI". URUTAN PASANG 1. Buat database kosong (utf8mb4), misalnya kantor_ai. Cadangkan dulu bila sudah ada isinya. 2. Impor file di folder sql/ SATU PER SATU, dengan urutan ini (jangan diacak, jangan diulang): 1. kantor_ai_schema.sql 2. migrasi_status.sql 3. migrasi_perencana.sql 4. migrasi_gambar.sql 5. migrasi_teks_wajib.sql 6. migrasi_posting.sql 7. migrasi_hasil.sql 8. migrasi_tebar.sql (hanya bila ingin jalur Tebar; aman dijalankan walau belum dipakai) 9. migrasi_carousel.sql (hanya bila ingin carousel; tanpa ini tetap bisa posting satu gambar) 10. migrasi_pustaka.sql (hanya bila ingin pustaka foto klien) 11. migrasi_platform.sql (hanya bila ingin Facebook, LinkedIn, X, dan Pinterest) 3. Salin config_sample.php menjadi config.php, lalu isi: - db (host, nama, user, pass) - anthropic_api_key (sebaiknya lewat environment variable ANTHROPIC_API_KEY) - admin: jalankan php buat_hash.php "kata-sandi-anda" lalu salin hasilnya - kunci_enkripsi: jalankan php buat_kunci.php lalu salin barisnya - url_dasar: alamat situs Anda (https, publik) bila gambar diambil Meta langsung Setelah SEMUA file SQL diimpor dan config.php terisi (langkah 3), jalankan migrasi multi-pengguna SATU KALI: php migrasi_multiuser.php email-admin@contoh.com (atau buka migrasi_multiuser.php di browser: isi email admin, lalu nama dan sandi admin dari config.php). Ini membuat tabel users dan user_settings, menambah kolom user_id ke semua tabel, dan membuat pengguna admin (id 1) yang memiliki semua data lama. Aman dijalankan ulang. Login memakai EMAIL tadi dan sandi admin config.php. Hapus migrasi_multiuser.php dari server bila sudah selesai (opsional). 4. Taruh satu file font .ttf di folder fonts/ (untuk gambar Instagram). 5. Pastikan PHP punya ekstensi: pdo_mysql, curl, openssl, mbstring, gd, fileinfo. 6. Buka login.php di browser, masuk dengan EMAIL dan sandi admin, lalu isi kunci API di Akun > Koneksi akun dan data klien di klien.php. CRON (atau Task Scheduler di Windows) */10 * * * * php /path/ke/worker.php >> worker.log 2>&1 (menulis dan memeriksa tugas) */5 * * * * php /path/ke/posting.php >> posting.log 2>&1 (memposting yang jatuh tempo) 0 * * * * php /path/ke/hasil.php >> hasil.log 2>&1 (mengambil hasil posting) Akhir bulan: php /path/ke/planner.php --depan (menyusun rencana bulan depan) AMAN DULU - posting_mode di config.php bawaannya 'uji': tidak ada yang dikirim ke Meta atau Tebar. Ubah ke 'nyata' hanya setelah dicoba dengan akun milik sendiri. - Batas anggaran bulanan tiap pengguna (halaman Akun) menghentikan tugasnya bila biaya AI bulan itu sudah mencapai batas. - Setiap posting tetap menunggu persetujuan Anda (status menunggu_setuju). - Posting otomatis hanya mengambil tugas Selesai yang punya jadwal tayang. Isi jadwal saat menekan Setujui, atau belakangan lewat kotak "Atur jadwal tayang" di tugas yang sudah Selesai (tab Tugas > Selesai). Jadwal yang sudah lewat lebih dari 6 jam (jendela_terlambat_jam) tidak diposting otomatis. - Jangan unggah config.php ke tempat publik. Jangan pernah menyimpan sandi Instagram klien. DUA JALUR POSTING (dipilih per klien di halaman Akun) - Meta langsung: masukkan token dan ID akun (butuh aplikasi Meta sendiri). - Tebar (tebar.app): simpan kunci API Tebar di kartu "Kunci API AI Anda" (halaman Akun), lalu pilih akun yang sudah dihubungkan di Tebar. FOTO DARI AI (OpenAI, opsional) - Isi kunci OpenAI di halaman Akun (kartu "Kunci API AI Anda"). Kosong = fitur mati, sisanya tetap jalan. (Pengguna Managed memakai openai_api_key milik server di config.php.) - Di halaman Gambar tugas: centang "Buat foto baru dengan AI", cek deskripsi, lalu "Buat gambar". Hanya untuk template foto/kartu. Judul dan logo tetap dipasang oleh template. - Opsi (lihat config_sample.php): openai_model, openai_kualitas (low/medium/high), openai_ukuran, openai_biaya_per_gambar_usd (perkiraan untuk laporan biaya), openai_maks_per_tugas (bawaan 10). - Nama model OpenAI sering berganti: cek daftar model di akun OpenAI Anda dan sesuaikan openai_model. Bila muncul galat verifikasi organisasi, selesaikan verifikasi di dashboard OpenAI. - Biaya masuk laporan biaya dan ikut batas anggaran pengguna. Angka aslinya bisa beda dari perkiraan. - Pembuatan gambar bisa 30-120 detik. Bila hosting memutus halaman, pakai openai_kualitas = 'low'. - Foto AI BUKAN foto produk asli. Pakai untuk suasana/ilustrasi, jangan untuk menunjukkan barang atau hasil kerja klien yang sebenarnya, dan sebut "ilustrasi AI" di caption. CAROUSEL INSTAGRAM (2 sampai 10 slide) - Jalankan migrasi_carousel.sql sekali. Tugas lama yang sudah punya satu gambar tidak berubah. - Di halaman Gambar tugas ada deretan slide. Tiap slide bisa dipilih sendiri-sendiri: * teks + warna brand (gaya "Warna brand + judul besar"), tanpa foto * foto unggahan sendiri (gaya foto atau kartu) * foto AI (centang "Buat foto baru dengan AI"; satu foto per klik, ulangi per slide) - "Carousel cepat": tulis satu judul per baris (atau klik "Susun judul slide" agar Claude menyusunnya dari teks posting), lalu "Buat semua slide". Ini mengganti semua slide yang ada. - Tombol segitiga menggeser urutan, tanda x menghapus slide. Slide 1 selalu jadi sampul. - Satu slide = posting satu gambar seperti biasa. Dua slide atau lebih = carousel otomatis (khusus Instagram; Threads memakai sampul saja). - Biaya foto AI naik sebanyak slide fotonya. Slide teks + warna tidak ada biaya foto. - Kirim carousel ke Meta langsung dan lewat Tebar sudah diuji dengan server tiruan saja. Cara Tebar menerima banyak gambar sekaligus belum dicek ke Tebar yang asli: uji dulu dengan akun milik sendiri. - Di export CSV, kolom url_gambar berisi semua alamat slide dipisah spasi. GAYA SLIDE, PUSTAKA FOTO, GAMBAR OTOMATIS - Gaya tanpa foto ada empat: warna brand, latar terang, latar gelap, dan kutipan. Semuanya memakai warna dan logo klien, jadi tetap satu keluarga brand tapi tampilannya bergantian. - Pustaka foto (jalankan migrasi_pustaka.sql): di halaman Klien (klik "Ubah", bagian "Pustaka foto") atau di halaman Gambar tugas, unggah foto produk atau tangkapan layar aplikasi klien (boleh banyak sekaligus). Di form slide tinggal pilih fotonya. - Gambar otomatis: setelah caption Instagram lolos pemeriksa, sistem menyusun judul slide (Claude) dan membuat gambarnya sendiri. Sampul bergantian menurut nomor tugas antara gaya polos, foto pustaka (bila ada), dan foto AI (hanya bila auto_foto_ai = true). Gagal tidak menghentikan alur: tugas tetap sampai ke persetujuan. - Tombol "Susun gambar otomatis" di halaman Gambar tugas menjalankannya untuk tugas yang sudah ada (MENGGANTI semua slide). - Pengaturan (config_sample.php): auto_gambar, auto_gambar_slide, auto_foto_ai, auto_foto_ai_maks_bulan. - Teks di slide diambil dari caption saat lolos pemeriksa. Kalau Anda mengubah caption saat menyetujui, slide tidak ikut berubah: ubah slide-nya sendiri bila perlu. PLATFORM: FACEBOOK, LINKEDIN, X, PINTEREST (semuanya lewat Tebar) - Jalankan migrasi_platform.sql sekali. Instagram dan Threads tidak berubah. - Hubungkan akun klien di dashboard Tebar, lalu di halaman Akun pilih akunnya (bagian "Atau pakai akun dari Tebar"). Tugas Facebook, LinkedIn, X, atau Pinterest baru bisa dibuat untuk klien yang akunnya sudah terhubung. Perencana bulanan otomatis ikut merencanakan platform ini bila akunnya sudah terhubung. - Aturan tiap platform ada di platform_service.php (batas karakter, gambar wajib atau opsional, jumlah gambar): Facebook Halaman (Page) saja, bukan profil pribadi. Teks, 1 sampai 10 foto. Gambar otomatis aktif. LinkedIn Profil pribadi saja (Company Page belum didukung Tebar). Teks 3.000 karakter, sampai 10 gambar. Dengan 2 gambar atau lebih dikirim sebagai carousel PDF (matikan: 'linkedin_carousel_pdf' => false). X 280 karakter berbobot (emoji dihitung 2, tautan 23), sampai 4 gambar. BERBAYAR dari saldo Tebar: sekitar Rp400 per posting, Rp4.000 bila ada tautan. Pastikan saldo Tebar cukup. Pinterest Akun Business. Deskripsi maksimal 800 karakter, tepat 1 foto (wajib), dan wajib memilih papan (board) di halaman Akun. Judul Pin diambil dari baris pertama teks. - Statistik (halaman Hasil) hanya ada untuk Instagram, Threads, dan Facebook. Tebar belum menyediakannya untuk LinkedIn, X, dan Pinterest. Nama kolom statistik Facebook belum dipastikan: dibaca longgar. - Gambar otomatis hanya untuk Instagram, Facebook, dan Pinterest. LinkedIn dan X dibuat teks saja (gambar bisa ditambah manual di halaman Gambar). - Belum ada: TikTok, YouTube, Discord (butuh video atau di luar kebutuhan UMKM), dan Reels/Story. MULTI-PENGGUNA: BYOK DAN MANAGED - Tiap pengguna punya data sendiri (klien, tugas, biaya, akun sosial, riwayat) dan tidak bisa melihat atau mengubah data pengguna lain. Masuk lewat login.php dengan email dan kata sandi. - Mode BYOK: pengguna mengisi kunci Anthropic, OpenAI (opsional), dan Tebar sendiri di Akun > Koneksi akun, lalu klik "Tes Koneksi" per kunci. Kunci disimpan terenkripsi (AES-256-CBC + HMAC, kunci dari 'kunci_enkripsi') dan hanya tampil tersamar. Kolom yang dikosongkan tidak menimpa kunci lama. Tugas BERHENTI bila kunci kosong, berstatus Error, atau biaya bulan ini mencapai batas anggaran pengguna. - Mode Managed: memakai kunci master Anthropic/OpenAI di config.php, selama jumlah tugas bulan ini (yang tidak ditolak) masih dalam kuota. Habis kuota = tugas berhenti dengan pesan jelas. Ada pagar biaya server per pengguna (batas_biaya_bulanan_usd). Kunci Tebar tetap milik pengguna, karena akun sosial terhubung ke Tebar pengguna itu. - Kunci salah (401), atau saldo/kuota habis (400/429/402 yang pesannya menyebut saldo, kredit, atau kuota) membuat status kunci menjadi Error dan tugas berhenti. Bila yang bermasalah kunci master, status pengguna tidak diubah dan pesannya meminta menghubungi admin. Batas kecepatan sementara (429 biasa) tidak menandai kunci Error. - Pendaftaran mandiri: register.php (tautan "Daftar" ada di halaman login). Pendaftar mengisi nama, email, dan kata sandi, lalu langsung masuk dan diarahkan ke Akun > Koneksi akun untuk mengisi kunci API. Akun baru selalu peran user, mode BYOK, kuota 0, jadi tidak memakai kunci master atau anggaran server. Pengaman: token CSRF, kolom jebakan untuk bot, form yang dikirim kurang dari 2 detik ditolak, maksimal 5 pendaftaran per jam per alamat IP. Tutup pendaftaran dengan menambah 'pendaftaran_dibuka' => false di config.php (tautan Daftar ikut hilang). Admin bisa mengubah mode pendaftar di halaman Pengguna. - Menu Pengguna (hanya admin): daftar pengguna, status kunci, jumlah klien/tugas/biaya bulan ini, tambah pengguna, atur ulang kata sandi (sesi lama pengguna itu otomatis tidak berlaku), ubah mode, kuota, dan aktif/nonaktif. Pengguna admin (id 1) tidak bisa dinonaktifkan. Tidak ada tampilan ubah peran; peran admin hanya untuk id 1. - Cron (worker, posting, hasil, planner) berjalan untuk semua pengguna aktif secara bergantian. - Bila tabel users belum ada, semua halaman menampilkan pesan agar migrasi_multiuser.php dijalankan. - Folder includes/ (crypto.php, auth_check.php) wajib ikut diunggah. Jangan hapus includes/.htaccess. - Jangan mengganti 'kunci_enkripsi' setelah ada kunci tersimpan: kunci pengguna jadi tidak bisa dibuka dan harus diisi ulang. CATATAN JUJUR Bagian multi-pengguna diuji dengan SQLite (migrasi, isolasi data, worker, halaman lewat HTTP) dan dengan kunci palsu ke server Anthropic asli (hanya menguji penolakan 401). DDL migrasi untuk MySQL asli BELUM pernah dijalankan di MySQL: CADANGKAN DATABASE SEBELUM migrasi_multiuser.php. Sudah diuji dengan database SQLite dan server Meta/Tebar tiruan. BELUM diuji dengan MySQL, Claude API, Meta, Tebar, dan OpenAI yang asli. Opsi per platform untuk Tebar (papan Pinterest, PDF LinkedIn) dibuat dari dokumentasi Tebar dan belum dicoba ke server Tebar yang asli. Mulailah dengan mode 'uji', lalu satu akun uji milik sendiri. Bila ada galat, kirim pesannya ke Claude. DAFTAR FILE Halaman web : login, logout, register, manifest, sw.js, offline.html (PWA), admin (papan tugas), klien, kalender, akun, gambar, performa (hasil), export_csv, denah (tampilan langsung dari data asli, plus mode simulasi) dan denah_data (data JSON untuk denah), index (halaman awal, langsung ke denah), menu_lib (menu atas yang sama di semua halaman) Perintah CLI: worker, planner, posting, hasil, buat_hash, buat_kunci Inti : db, ai_client, tugas_service, planner_service, panduan_konten, gambar_service, openai_gambar, pustaka_service, gambar_otomatis, posting_service, tebar_service, platform_service, hasil_service, hasil_analisis, web_lib Multi-user : pengguna (halaman admin), pengguna_service, tes_api, akun_kartu_api, migrasi_multiuser, includes/crypto.php, includes/auth_check.php Contoh : config_sample.php TAMPILAN BARU (perapian menu, Denah, dan Tugas) - Setelah login, halaman pertama adalah Denah. Alamat utama (index.php) juga langsung ke Denah. - Menu atas sama di semua halaman, urutannya: Denah, Tugas, Kalender, Hasil, Klien, Biaya, Akun. Tombol hijau "+ Tugas Baru" ada di kanan. Di menu Tugas ada angka bila ada tugas menunggu persetujuan atau berhenti (merah bila ada yang berhenti). - Ekspor CSV pindah ke halaman Tugas dan halaman Hasil sebagai tombol kecil. - Denah: satu baris atas (judul, sakelar Langsung/Simulasi, ringkasan). Penjelasan ada di ikon (i). Kertas di papan bisa diklik ke tugasnya, meja agen bisa diklik (tugas terakhir dan token hari ini), tombol "+ Tugas baru" ada di pojok kanan bawah ilustrasi. Panel bawah 2x2 dengan tautan "Lihat selengkapnya". - Tugas: 4 kartu ringkasan, 4 tab (Perlu Tindakan, Proses AI, Selesai & Tayang, Semua), pencarian (judul, klien, nomor), filter klien dan tanggal dibuat. Tautan lama seperti admin.php?status=menunggu_setuju tetap jalan. - Tidak ada migrasi database baru untuk bagian ini. File baru: index.php dan menu_lib.php. Jangan timpa config.php. PERAPIAN TAHAP 2 (semua halaman) - Tugas: 4 kartu ringkasan sekaligus jadi penyaring (Perlu persetujuan, Sedang dikerjakan AI, Terjadwal tayang, Selesai bulan ini) dan tombol Semua tugas. Lencana dibedakan: Terjadwal (biru, ada tanggal dan jam), Sudah tayang (hijau), Gagal tayang (merah). Teks panjang diringkas 3 baris, form jadwal dilipat. Form Tugas baru punya kolom Rencana tayang (opsional) dan bisa terisi dari tautan (?klien=ID&tanggal=YYYY-MM-DD). - Kalender: sakelar sembunyikan minggu lewat yang kosong, progres target dan keterangan warna di atas, tombol "+ Buat" di hari kosong, warna per platform, tanda centang untuk yang sudah tayang. - Hasil: 4 kartu ringkasan, penjelasan skor di ikon (i), Ekspor CSV satu baris dengan filter, tombol "Sinkronkan sekarang" (menjalankan pengambilan hasil yang sama dengan php hasil.php; cron tetap dipakai). - Klien: daftar di atas, form tambah klien dilipat, kartu klien dengan progres, peringatan pustaka foto kosong, tombol Lihat Tugas dan + Buat Tugas, penghitung karakter catatan brand, pilihan Paket mengisi target posting otomatis (12/20/30). - Biaya: rata-rata biaya per tugas, bar anggaran bertumpuk (teks vs foto AI), tabel pemakaian per agen, tautan billing Anthropic dan OpenAI. Batas anggaran dan kurs sekarang diubah tiap pengguna di halaman Akun (kartu "Kunci API AI Anda"). - Akun: dua sub-tab (Antrean & status posting, Koneksi akun). Antrean urut dari yang perlu dicek, lalu jadwal terdekat. Platform yang sudah terhubung diberi lencana hijau, token Meta manual dilipat, platform belum aktif diringkas satu baris dengan syaratnya di ikon (i). - Tidak ada migrasi database baru. Jangan timpa config.php. PERAPIAN TAHAP 3 (header seragam, pendaftaran) - Bar putih berjudul "Kantor AI" di atas menu dihapus di semua halaman. Menu atas sekarang satu komponen yang sama dan lebarnya sama (1040 px, seperti Denah), jadi isi halaman ikut selebar itu. - "+ Tugas Baru" dan kotak profil (nama, BYOK/Managed, Keluar) ada dalam satu kelompok di kanan menu, sebaris dengan tab menu di layar tablet dan desktop. Di HP (lebar 640 px ke bawah) semua tab menu terlihat sekaligus (tersusun 2 sampai 3 baris, tanpa digeser), lalu kelompok kanan di baris sendiri. - Judul halaman tetap ada untuk pembaca layar (tersembunyi secara visual). gambar.php tetap punya header sendiri karena itu halaman turunan dari sebuah tugas. APLIKASI DI HP (PWA) DAN "TETAP MASUK" - Situs bisa dipasang di layar utama Android seperti aplikasi: buka di Chrome, lalu muncul ajakan "Pasang Kantor AI" di bawah layar (atau menu Chrome > Pasang aplikasi / Tambahkan ke layar utama). Tampil layar penuh tanpa kotak alamat, dengan ikon "AI". Tekan lama ikonnya untuk jalan pintas: Tugas Baru, Tugas, Kalender. - Syarat: situs HARUS lewat HTTPS. Folder aplikasi wajib berisi manifest.php, sw.js, offline.html, dan folder icons/. - Aplikasi tetap butuh internet. Tanpa sinyal yang tampil hanya halaman "Tidak ada koneksi". Halaman dan data sengaja TIDAK disimpan di HP (service worker hanya menyimpan ikon dan font), jadi tidak ada data klien yang tertinggal bila HP dipakai bergantian. - Di iPhone (Safari): Bagikan > Tambah ke Layar Utama. Ajakan otomatis hanya ada di Chrome Android. - Mengganti ikon atau nama aplikasi: ubah file di icons/ dan manifest.php. Bila daftar file statis di sw.js berubah, naikkan VERSI di sw.js. - Di halaman login dan daftar ada kotak "Tetap masuk di perangkat ini". Bila dicentang, sesi bertahan 30 hari (dan otomatis tercentang di aplikasi yang sudah terpasang). Bila tidak, sesi berakhir setelah 12 jam tanpa kegiatan. Keluar menghapus keduanya. Sesi disimpan di folder includes/sesi/ (tertutup dari web). Pastikan folder includes/ bisa ditulis. PENGATURAN GAMBAR PER PENGGUNA - Halaman Akun > Koneksi punya kartu "Pengaturan gambar otomatis": gambar otomatis hidup/mati, jumlah slide (1-10), foto AI hidup/mati, batas foto AI per bulan (0 = tanpa batas) dan kualitas foto AI (Hemat/Sedang/Tinggi). Setiap pengguna punya pengaturan sendiri. - Sebelum pernah disimpan, yang dipakai adalah nilai bawaan dari config.php (auto_gambar, auto_gambar_slide, auto_foto_ai, auto_foto_ai_maks_bulan, openai_kualitas), jadi perilaku lama tidak berubah. Tombol "Kembalikan ke bawaan" menghapus pengaturan pengguna. - Kolom barunya ditambahkan ke tabel user_settings oleh migrasi_multiuser.php (aman dijalankan ulang). Bila lupa, kolom ditambahkan otomatis saat halaman Akun dibuka (butuh izin ALTER TABLE; bila tidak ada izin, kartu menampilkan pesan). - Foto AI tetap memakai kunci OpenAI milik pengguna (BYOK) dan tetap dibatasi anggaran bulanan. FORMAT GAMBAR: AI MEMILIH 1 GAMBAR ATAU CAROUSEL - Ada tiga format: "Otomatis (AI memilih)", "1 gambar", dan "Carousel". Bawaannya Otomatis. - Otomatis: AI membaca caption. Pesan tunggal (kutipan, pengumuman, promo singkat) jadi 1 gambar. Langkah, daftar, atau tips jadi carousel. "Jumlah slide karusel" di halaman Akun menjadi BATAS ATAS untuk pilihan AI. Mengisi 1 sama dengan selalu 1 gambar (seperti sebelumnya). - 1 gambar: selalu sampul saja, AI judul slide tidak dipanggil (hemat). Carousel: jumlah slide sesuai pengaturan (minimal 2). - Pinterest selalu 1 gambar, Instagram dan Facebook paling banyak 10 slide, apa pun formatnya. - Format bawaan diatur di Akun > Pengaturan gambar otomatis. Tiap tugas bisa menimpanya: saat membuat tugas baru (kolom "Format gambar"), atau di halaman Gambar tugas itu (pilihan dipakai saat menekan "Susun gambar otomatis"). Pilihan "Ikut pengaturan Akun" menghapus penimpaan. - Kolom baru (user_settings.auto_gambar_format dan tugas.format_gambar) ditambahkan oleh migrasi_multiuser.php (aman diulang) atau otomatis saat halaman dibuka. Di config.php nilai bawaannya 'auto_gambar_format' (boleh dikosongkan). - Format Otomatis menambah satu panggilan AI kecil (sama seperti judul slide), tercatat di riwayat biaya. SUMBER SAMPUL - Di Akun > Pengaturan gambar otomatis ada pilihan "Sumber sampul": Bergantian : sampul memutar antara polos, foto pustaka klien (bila ada), dan foto AI (bila dinyalakan). Ini bawaannya. Selalu foto AI : tiap tugas membuat satu foto AI untuk sampul (berbayar). Kotak "Buat foto AI otomatis" ikut tercentang sendiri. Selalu foto pustaka: sampul memakai foto dari pustaka klien. Selalu polos : sampul teks + warna saja, tanpa foto. - Hanya sampul (slide 1) yang bisa berfoto. Slide ke-2 dan seterusnya selalu polos. - Bila sumber yang dipilih tidak tersedia (pustaka kosong, kunci OpenAI belum valid, batas foto AI per bulan tercapai, anggaran habis, atau OpenAI menolak), sampul dibuat polos dan alasannya ditulis di riwayat tugas ("Gambar otomatis siap: ..., (alasan)"). - Nilai bawaan di config.php: 'auto_sampul_sumber'. Kolom baru user_settings.sampul_sumber ditambahkan oleh migrasi_multiuser.php atau otomatis.