# Validasi Lokal PHP

Validasi dilakukan pada 18 Agustus 2026 menggunakan server PHP 8.3 lokal dengan document root `php-app/public` dan router `php-app/router.php`.

| Pemeriksaan | Hasil |
|---|---|
| Sintaks semua berkas PHP | Lulus melalui `php -l` |
| Regresi aplikasi | `pnpm test` lulus: 45 tes pada 12 berkas, termasuk bootstrap, sesi, serta parity audit PHP native |
| TypeScript aplikasi React pendamping | `pnpm exec tsc --noEmit` lulus |
| Build produksi React pendamping | `pnpm run build` lulus; peringatan ukuran chunk Vite tidak menghalangi build |
| Parity audit dan persetujuan | Sintaks `App.php`/`Database.php` serta 2 regresi parity lulus; ekspor CSV audit memakai filter aktif per sesi dan baris SKU antrean mendapat alias `itemSku` |
| Koneksi PDO ke TiDB Cloud | Lulus menggunakan CA sistem dan TLS |
| Beranda PHP | HTTP 200 serta ter-render dengan stylesheet |
| Company Profile PHP | HTTP 200 |
| Login teknisi lokal | Berhasil mengakses workspace operasional |
| Halaman yang dilindungi tanpa sesi | Mengalihkan ke login (HTTP 303) |
| Akses teknisi ke pelanggan/admin/ekspor Super Admin | Dialihkan dan tidak diizinkan |
| Respons visual publik desktop | Terverifikasi pada peramban dengan CSS termuat |
| Viewport seluler 375×812 | `innerWidth` dan `scrollWidth` sama-sama 375; hero serta paket masing-masing satu kolom 343 px; navigasi membungkus responsif |
| Preview PHP native | Tersedia pada `/preview-php`; peramban memverifikasi hero, tab interaktif stok/galeri/sesi, dan panel stok bergaya pada endpoint sementara PHP |
| Tab galeri preview | Klik tab “Galeri foto” berhasil mengganti panel menjadi album bukti dan mockup lightbox tanpa perpindahan halaman |
| Preview seluler 375×812 | `innerWidth` dan `scrollWidth` sama-sama 375; panel preview menjadi satu kolom 281 px dan navigasi membungkus tanpa overflow horizontal |
| Katalog dan galeri terkunci | Login teknisi dapat membuka katalog dengan filter kategori/status serta galeri dengan filter album; halaman galeri memuat dialog lightbox tanpa menulis data inventaris |
| Super Admin browser desktop | Login Super Admin PHP native berhasil menuju `/operasional`; antarmuka menampilkan kontrol katalog/transaksi, persetujuan stok, tagihan, audit, Company Profile, dan keluar sesi |
| Admin users & billing desktop | Super Admin dapat membuka `/admin/users` untuk formulir akun teknisi/pengaturan peran dan `/admin/billing` untuk formulir invoice/status pembayaran tanpa membuat data baru |
| Company Profile & audit desktop | Super Admin dapat membuka administrasi PDF/pesan/analitik Company Profile dan halaman audit dengan filter aktivitas/tanggal serta tautan ekspor CSV |
| Audit Super Admin seluler 375×812 | `innerWidth` dan `scrollWidth` sama-sama 375; filter audit tersusun satu kolom 297 px dan navigasi membungkus tanpa overflow horizontal |
| Portal pelanggan browser | Login `pelanggan.uji@mbiznetwork.test` berhasil menuju `/pelanggan` dan menampilkan kartu status langganan serta riwayat invoice sesuai data aktual yang tersedia, tanpa membuat atau mengubah data |
| Workspace teknisi browser | Login `teknisi.psb@mbiznetwork.test` berhasil menuju `/operasional`; teknisi melihat formulir pergerakan stok, unit tugas, kategori album bukti, unggahan foto, dan transaksi aktual tanpa kontrol administrasi Super Admin |
| Galeri teknisi browser | Teknisi dapat membuka `/operasional/galeri`, menggunakan filter barang/album, dan mendapat state kosong yang jelas saat belum ada bukti foto aktual |
| Company Profile publik browser | Halaman publik memuat identitas dokumen, area pratinjau, tautan unduh PDF, serta formulir kontak dengan pilihan departemen tanpa mengirim pesan baru |
| Company Profile seluler 375×812 | `innerWidth` dan `scrollWidth` sama-sama 375; formulir kontak dan panel dokumen tersusun satu kolom tanpa overflow horizontal |
| Workspace teknisi seluler 375×812 | Setelah pemuatan ulang pada viewport 375 px, `innerWidth` dan `scrollWidth` sama-sama 375; dashboard dan formulir stok memakai satu kolom responsif |
| Galeri teknisi seluler 375×812 | `innerWidth` dan `scrollWidth` sama-sama 375; filter galeri dan state kosong tampil tanpa overflow horizontal |
| Portal pelanggan seluler 375×812 | Login pelanggan berhasil dan `innerWidth`/`scrollWidth` sama-sama 375; status langganan serta riwayat invoice tersusun responsif tanpa overflow horizontal |
| Akses Super Admin seluler | Login ulang sebagai Super Admin berhasil dan workspace memuat kontrol katalog, persetujuan, dan pengingat tagihan sebelum verifikasi halaman tagihan khusus |
| Administrasi tagihan seluler 375×812 | `innerWidth` dan `scrollWidth` sama-sama 375; formulir invoice, catatan, dan tabel riwayat responsif tanpa overflow horizontal |
| Login teknisi untuk peningkatan UI | Akun teknisi uji berhasil masuk kembali ke workspace PHP native sebelum verifikasi katalog dan galeri interaktif |
| Katalog teknisi interaktif desktop | Halaman `/operasional/stok` memuat pencarian langsung, filter kategori/status, reset, jumlah hasil, serta akses cepat transaksi dan galeri; state kosong jelas saat tidak ada data inventaris aktual |
| Galeri teknisi interaktif desktop | Halaman `/operasional/galeri` memuat pencarian bukti, filter barang/album, reset, jumlah hasil, status pemuatan bertahap, dan struktur lightbox; state kosong jelas saat belum ada bukti aktual |
| Sesi teknisi untuk validasi seluler | Autentikasi teknisi berhasil dipulihkan setelah pergantian viewport untuk pengujian responsivitas katalog perangkat baru |
| Antarmuka teknisi seluler 375×812 | Katalog perangkat dan galeri bukti yang diperbarui sama-sama mencatat `innerWidth`/`scrollWidth` 375 tanpa overflow horizontal; stylesheet interaktif termuat dan kontrol pencarian aktif |
| Regresi antarmuka teknisi | Regresi serial lulus: 47 tes pada 13 berkas, termasuk 2 tes katalog/galeri teknisi; sintaks PHP, TypeScript, dan build produksi juga lulus |
| Formulir unggahan multi-foto teknisi | Setelah login teknisi, `/operasional/galeri` menampilkan batch upload dengan pemilih transaksi, input beberapa berkas, batas 5 foto JPEG/PNG/WebP maksimal 5 MB, dan akses ke filter galeri; tidak ada transaksi operasional aktual untuk diunggah saat validasi |
| Interaksi pemilih multi-foto | Browser menerima dua berkas uji secara lokal, menampilkan “2 foto dipilih. Siap diunggah.”, dan menetapkan `multiple` serta tipe JPEG/PNG/WebP tanpa membuat data operasional |
| Responsivitas dan regresi multi-foto | Batch upload galeri mempertahankan `scrollWidth` 375 pada viewport 375 px; 49 tes pada 14 berkas, sintaks PHP, TypeScript, dan build produksi lulus |
| Pengelolaan foto bukti | Tabel foto bukti memiliki metadata `displayOrder` dan `note`; penghapusan, catatan, serta urutan hanya menerima pemilik unggahan atau Super Admin dan masing-masing menulis audit log |
| Drag-and-drop galeri | Peramban teknisi memuat skrip pengelolaan urutan, token CSRF, serta status “Seret pegangan foto…”; saat tidak ada bukti aktual, tidak ada foto/urutan produksi yang diubah |
| Validasi akhir pengelolaan foto | Viewport 375 px mempertahankan `scrollWidth` 375; 52 tes pada 15 berkas, sintaks PHP, TypeScript, dan build produksi lulus |
| Recycle bin dan album galeri | Soft delete menyimpan `deletedAt` dan `deletedBy`; pemilik unggahan atau Super Admin dapat memulihkan foto, sementara berkas S3 tetap dipertahankan dan setiap aksi masuk audit log |
| Pengelompokan dan urutan album | Galeri menampilkan kelompok album dan ringkasan per album; skrip drag-and-drop hanya mengizinkan kartu aktif pada album yang sama untuk bertukar posisi |
| Validasi akhir recycle bin | Browser teknisi menampilkan recycle bin dan status urutan album, viewport 375 px tetap tanpa overflow; 53 tes pada 15 berkas, sintaks PHP, TypeScript, dan build produksi lulus |
| Filter recycle bin | Teknisi melihat pencarian nama foto/barang/SKU/album/catatan serta tanggal dihapus mulai/sampai; filter mempertahankan nilai parameter dan tidak menampilkan panel ekspor Super Admin |
| Riwayat dan ekspor pemulihan | Super Admin melihat riwayat pemulihan dan tautan CSV/PDF yang meneruskan kata kunci serta rentang tanggal aktif; endpoint ekspor memerlukan peran admin |
| Validasi akhir filter dan ekspor | Sintaks PHP, TypeScript, build, serta 54 tes pada 15 berkas lulus; tautan CSV dan PDF diverifikasi di browser dengan filter aktif |
| Pratinjau dan pagination recycle bin | Halaman Super Admin memuat skrip pratinjau recycle bin dan memperlihatkan ringkasan pagination “Menampilkan 0 dari 0 riwayat”; kontrol halaman hanya tampil saat riwayat melampaui 20 baris agar tampilan tetap ringkas |
| Retensi otomatis 30 hari | Job aktif `mbiz-recycle-bin-retention` terdaftar pada jadwal `0 0 3 * * *` UTC; callback hanya menerima task UID yang disimpan di `recycleBinRetentionSettings`, memproses maksimum 500 foto kedaluwarsa per eksekusi, dan mencatat audit batch tanpa menghapus objek penyimpanan secara langsung |
| Validasi akhir pratinjau, pagination, dan retensi | Sintaks PHP, TypeScript, build, serta 56 tes pada 15 berkas lulus; filter recycle bin dan panel Super Admin diverifikasi di browser pada viewport desktop |
| Pencarian audit pemulihan foto | Super Admin dapat membuka `/admin/audit-evidence` dan mencari riwayat pemulihan melalui nama berkas atau album; pencarian memakai metadata audit dan album transaksi tanpa menulis data operasional |
| Pengaturan retensi Super Admin | Halaman `/operasional/recycle-bin-settings` tervalidasi dengan sesi Super Admin; retensi dibatasi 7–365 hari dan ambang peringatan 1–60 hari yang harus lebih pendek dari retensi; konfigurasi saat ini 30 hari dengan peringatan 3 hari |
| Peringatan penghapusan internal | Callback terjadwal mengidentifikasi foto dalam jendela peringatan dan menyimpan satu alert per foto/pemilik secara idempoten; alert tampil pada galeri pemilik, dapat ditandai dibaca, dan dihapus jika foto dipulihkan atau dipurge |
| Validasi akhir pencarian dan retensi terkelola | Sesi uji Super Admin berhasil memuat panel retensi dan pencarian audit; job `mbiz-recycle-bin-retention` tetap aktif; 59 tes pada 15 berkas, TypeScript, build produksi, dan sintaks PHP lulus |
| Ekspor CSV pencarian audit pemulihan | Sesi Super Admin memuat tombol “Ekspor CSV hasil” pada `/admin/audit-evidence?q=album`; endpoint mengembalikan CSV dengan nama berkas audit pemulihan dan meneruskan kata kunci aktif |
| Badge peringatan navigasi | Navigasi karyawan menghitung alert recycle bin yang belum dibaca dan hanya menampilkan lencana ketika jumlahnya positif; tidak ada data foto uji yang dibuat untuk memaksa lencana muncul |
| Ringkasan notifikasi internal | Konfigurasi ringkasan internal aktif pada retensi 30 hari dan peringatan 3 hari; job `mbiz-recycle-bin-retention` aktif dengan task UID terikat; log pengiriman masih kosong karena belum ada alert aktual yang memenuhi kriteria |
| Validasi akhir pelaporan peringatan | 62 tes pada 15 berkas, TypeScript, build produksi, serta sintaks PHP lulus; rute CSV, panel pengaturan/riwayat ringkasan Super Admin, konfigurasi database, dan status job diverifikasi tanpa mengubah data operasional |
| Tindakan massal peringatan | Pemilik peringatan dapat menggunakan tombol “Tandai semua dibaca”; pembaruan dibatasi oleh `userId`, mencatat audit aktivitas, dan tidak memengaruhi peringatan pengguna lain |
| Filter riwayat ringkasan | Super Admin dapat memfilter riwayat delivery internal menjadi terkirim, menunggu, atau gagal; parameter `delivery_status=failed` tervalidasi pada sesi PHP lokal dan menampilkan state kosong yang jelas tanpa membuat data uji |
| Tautan detail foto | Detail peringatan menyertakan tautan ke kartu foto recycle bin yang memakai anchor stabil berdasarkan ID bukti; tautan tetap berada pada alur galeri berizin dan tidak mengekspos URL penyimpanan langsung |
| Validasi akhir pengelolaan notifikasi | 65 tes pada 15 berkas, TypeScript, build produksi, serta sintaks PHP lulus; panel filter Super Admin diverifikasi dengan sesi lokal tanpa mengubah data operasional |
| Pagination riwayat pengiriman | Riwayat ringkasan internal memakai 10 baris per halaman dan mempertahankan `delivery_status`; sesi Super Admin memverifikasi filter `failed` bersama parameter halaman tanpa membuat data pengiriman uji |
| Pemulihan langsung dari peringatan | Setiap detail peringatan menyediakan tombol “Pulihkan foto” yang memakai aksi pemulihan dan kontrol izin pemilik/Super Admin yang sama dengan recycle bin; peringatan terkait dihapus ketika pemulihan berhasil |
| Validasi akhir pagination dan pemulihan | 67 tes pada 15 berkas, TypeScript, build produksi, serta sintaks PHP lulus; state kosong filter dan parameter halaman tervalidasi pada sesi PHP lokal tanpa mengubah data operasional |
| Dialog konfirmasi pemulihan | Detail peringatan memuat dialog native sebelum formulir pemulihan dikirim; pengguna dapat membatalkan atau mengonfirmasi pemulihan foto yang dipilih tanpa melewati kontrol izin server-side |
| Ekspor CSV riwayat pengiriman | Super Admin dapat mengunduh CSV riwayat ringkasan dengan filter `delivery_status` yang sama dengan panel; sesi lokal memverifikasi tautan berfilter, header CSV, dan nama berkas tanpa membuat data pengiriman uji |
| Validasi akhir konfirmasi dan ekspor | 69 tes pada 15 berkas, TypeScript, build produksi, serta sintaks PHP lulus; markup dialog dan endpoint ekspor Super Admin diverifikasi pada sesi PHP lokal |

Pengujian tidak menambah data inventaris, invoice, ataupun mengirim pesan kepada pelanggan.
