diff --git a/app/Http/Controllers/MaintenanceController.php b/app/Http/Controllers/MaintenanceController.php index 6e8f6ee..45ef637 100644 --- a/app/Http/Controllers/MaintenanceController.php +++ b/app/Http/Controllers/MaintenanceController.php @@ -7,11 +7,14 @@ use App\Models\Department; use App\Models\DocumentType; use App\Models\SchoolClass; use App\Models\Student; +use App\Models\StudentAchievement; use App\Models\StudentDocument; +use App\Models\StudentExit; +use App\Models\StudentGraduation; +use App\Models\StudentTransfer; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Storage; use Illuminate\View\View; @@ -28,6 +31,10 @@ class MaintenanceController extends Controller 'student_parents' => 'Orang Tua / Wali', 'student_documents' => 'Dokumen Siswa + file storage', 'student_academic_histories' => 'Histori Akademik Siswa', + 'student_achievements' => 'Prestasi Siswa + file storage', + 'student_exits' => 'Arsip Siswa Keluar + file storage', + 'student_transfers' => 'Arsip Mutasi Siswa + file storage', + 'student_graduations' => 'Arsip Kelulusan Siswa + file storage', ]; public function index(): View @@ -42,8 +49,13 @@ class MaintenanceController extends Controller 'studentParents' => DB::table('student_parents')->count(), 'studentDocuments' => StudentDocument::withTrashed()->count(), 'studentAcademicHistories' => DB::table('student_academic_histories')->count(), + 'studentAchievements' => StudentAchievement::count(), + 'studentExits' => StudentExit::count(), + 'studentTransfers' => StudentTransfer::count(), + 'studentGraduations' => StudentGraduation::count(), ], 'targets' => $this->availableTargets, + 'resolvedTargetsPreview' => $this->buildResolvedTargetPreview(), ]); } @@ -76,6 +88,52 @@ class MaintenanceController extends Controller $resolvedTargets = $this->resolveTargets($targets->all()); DB::transaction(function () use ($resolvedTargets) { + if (in_array('student_achievements', $resolvedTargets, true)) { + StudentAchievement::query()->get()->each(function (StudentAchievement $achievement) { + foreach ([$achievement->certificate_file, $achievement->activity_photo] as $path) { + if ($path && Storage::disk('public')->exists($path)) { + Storage::disk('public')->delete($path); + } + } + }); + DB::table('student_achievements')->delete(); + } + + if (in_array('student_exits', $resolvedTargets, true)) { + StudentExit::query()->get()->each(function (StudentExit $studentExit) { + if ($studentExit->exit_letter_file_path && Storage::disk('public')->exists($studentExit->exit_letter_file_path)) { + Storage::disk('public')->delete($studentExit->exit_letter_file_path); + } + }); + DB::table('student_exits')->delete(); + } + + if (in_array('student_transfers', $resolvedTargets, true)) { + StudentTransfer::query()->get()->each(function (StudentTransfer $studentTransfer) { + if ($studentTransfer->transfer_letter_file_path && Storage::disk('public')->exists($studentTransfer->transfer_letter_file_path)) { + Storage::disk('public')->delete($studentTransfer->transfer_letter_file_path); + } + }); + DB::table('student_transfers')->delete(); + } + + if (in_array('student_graduations', $resolvedTargets, true)) { + StudentGraduation::query()->get()->each(function (StudentGraduation $graduation) { + foreach ([ + $graduation->skl_file_path, + $graduation->ijazah_file_path, + $graduation->transcript_file_path, + $graduation->ukk_certificate_file_path, + $graduation->lsp_certificate_file_path, + ] as $path) { + if ($path && Storage::disk('public')->exists($path)) { + Storage::disk('public')->delete($path); + } + } + }); + DB::table('student_graduations')->delete(); + } + if (in_array('students', $resolvedTargets, true)) { Student::withTrashed()->get()->each->forceDelete(); } @@ -122,6 +180,22 @@ class MaintenanceController extends Controller Storage::disk('public')->deleteDirectory('student-documents'); } + if (in_array('student_achievements', $resolvedTargets, true)) { + Storage::disk('public')->deleteDirectory('student-achievements'); + } + + if (in_array('student_exits', $resolvedTargets, true)) { + Storage::disk('public')->deleteDirectory('student-exit-letters'); + } + + if (in_array('student_transfers', $resolvedTargets, true)) { + Storage::disk('public')->deleteDirectory('student-transfer-letters'); + } + + if (in_array('student_graduations', $resolvedTargets, true)) { + Storage::disk('public')->deleteDirectory('student-graduation-documents'); + } + $labels = collect($resolvedTargets) ->map(fn ($target) => $this->availableTargets[$target] ?? $target) ->implode(', '); @@ -136,11 +210,26 @@ class MaintenanceController extends Controller $resolved = collect($targets); if ($resolved->contains('students')) { - $resolved = $resolved->merge(['student_documents', 'student_parents', 'student_academic_histories']); + $resolved = $resolved->merge([ + 'student_documents', + 'student_parents', + 'student_academic_histories', + 'student_achievements', + 'student_exits', + 'student_transfers', + 'student_graduations', + ]); } if ($resolved->contains('classes')) { - $resolved = $resolved->merge(['students', 'student_academic_histories']); + $resolved = $resolved->merge([ + 'students', + 'student_academic_histories', + 'student_achievements', + 'student_exits', + 'student_transfers', + 'student_graduations', + ]); } if ($resolved->contains('document_types')) { @@ -148,14 +237,46 @@ class MaintenanceController extends Controller } if ($resolved->contains('departments')) { - $resolved = $resolved->merge(['classes', 'students', 'student_academic_histories']); + $resolved = $resolved->merge([ + 'classes', + 'students', + 'student_academic_histories', + 'student_achievements', + 'student_exits', + 'student_transfers', + 'student_graduations', + ]); } if ($resolved->contains('academic_years')) { - $resolved = $resolved->merge(['classes', 'students', 'student_academic_histories']); + $resolved = $resolved->merge([ + 'classes', + 'students', + 'student_academic_histories', + 'student_achievements', + 'student_exits', + 'student_transfers', + 'student_graduations', + ]); } return $resolved->unique()->values()->all(); } + protected function buildResolvedTargetPreview(): array + { + return collect(array_keys($this->availableTargets)) + ->mapWithKeys(function (string $target) { + $resolved = $this->resolveTargets([$target]); + + return [ + $target => collect($resolved) + ->map(fn (string $resolvedTarget) => $this->availableTargets[$resolvedTarget] ?? $resolvedTarget) + ->values() + ->all(), + ]; + }) + ->all(); + } + } diff --git a/resources/views/maintenance/reset-data.blade.php b/resources/views/maintenance/reset-data.blade.php index 16156e5..d284d1b 100644 --- a/resources/views/maintenance/reset-data.blade.php +++ b/resources/views/maintenance/reset-data.blade.php @@ -1,78 +1,245 @@ - -
-
Catatan penting:
-
    -
  • Mas bisa memilih tabel/kelompok data tertentu saja.
  • -
  • Backend akan menambahkan dependensi yang wajib ikut dibersihkan supaya tidak bentrok foreign key.
  • -
  • Untuk dokumen siswa, file fisik di storage juga ikut dibersihkan.
  • -
  • Konfirmasi memakai password admin yang sedang login.
  • -
+ @php + $statCards = [ + ['label' => 'Tahun', 'value' => $stats['academicYears'], 'icon' => 'fa-solid fa-calendar-days', 'accent' => 'slate'], + ['label' => 'Jurusan', 'value' => $stats['departments'], 'icon' => 'fa-solid fa-layer-group', 'accent' => 'indigo'], + ['label' => 'Kelas', 'value' => $stats['classes'], 'icon' => 'fa-solid fa-school', 'accent' => 'sky'], + ['label' => 'Jenis Dokumen', 'value' => $stats['documentTypes'], 'icon' => 'fa-solid fa-file-lines', 'accent' => 'violet'], + ['label' => 'Siswa', 'value' => $stats['students'], 'icon' => 'fa-solid fa-user-graduate', 'accent' => 'rose'], + ['label' => 'Ortu/Wali', 'value' => $stats['studentParents'], 'icon' => 'fa-solid fa-people-roof', 'accent' => 'amber'], + ['label' => 'Dokumen', 'value' => $stats['studentDocuments'], 'icon' => 'fa-solid fa-folder-open', 'accent' => 'emerald'], + ['label' => 'Histori', 'value' => $stats['studentAcademicHistories'], 'icon' => 'fa-solid fa-clock-rotate-left', 'accent' => 'cyan'], + ['label' => 'Prestasi', 'value' => $stats['studentAchievements'], 'icon' => 'fa-solid fa-trophy', 'accent' => 'yellow'], + ['label' => 'Keluar', 'value' => $stats['studentExits'], 'icon' => 'fa-solid fa-right-from-bracket', 'accent' => 'orange'], + ['label' => 'Mutasi', 'value' => $stats['studentTransfers'], 'icon' => 'fa-solid fa-arrow-right-arrow-left', 'accent' => 'fuchsia'], + ['label' => 'Kelulusan', 'value' => $stats['studentGraduations'], 'icon' => 'fa-solid fa-award', 'accent' => 'teal'], + ]; + + $accentClasses = [ + 'slate' => 'border-slate-200 bg-gradient-to-br from-white via-slate-50 to-slate-100/70 text-slate-700 shadow-slate-200/50 ring-slate-100', + 'indigo' => 'border-indigo-200 bg-gradient-to-br from-white via-indigo-50/60 to-indigo-100/60 text-indigo-700 shadow-indigo-100/50 ring-indigo-100', + 'sky' => 'border-sky-200 bg-gradient-to-br from-white via-sky-50/60 to-sky-100/60 text-sky-700 shadow-sky-100/50 ring-sky-100', + 'violet' => 'border-violet-200 bg-gradient-to-br from-white via-violet-50/60 to-violet-100/60 text-violet-700 shadow-violet-100/50 ring-violet-100', + 'rose' => 'border-rose-200 bg-gradient-to-br from-white via-rose-50/60 to-rose-100/60 text-rose-700 shadow-rose-100/50 ring-rose-100', + 'amber' => 'border-amber-200 bg-gradient-to-br from-white via-amber-50/60 to-amber-100/60 text-amber-700 shadow-amber-100/50 ring-amber-100', + 'emerald' => 'border-emerald-200 bg-gradient-to-br from-white via-emerald-50/60 to-emerald-100/60 text-emerald-700 shadow-emerald-100/50 ring-emerald-100', + 'cyan' => 'border-cyan-200 bg-gradient-to-br from-white via-cyan-50/60 to-cyan-100/60 text-cyan-700 shadow-cyan-100/50 ring-cyan-100', + 'yellow' => 'border-yellow-200 bg-gradient-to-br from-white via-yellow-50/60 to-yellow-100/60 text-yellow-700 shadow-yellow-100/50 ring-yellow-100', + 'orange' => 'border-orange-200 bg-gradient-to-br from-white via-orange-50/60 to-orange-100/60 text-orange-700 shadow-orange-100/50 ring-orange-100', + 'fuchsia' => 'border-fuchsia-200 bg-gradient-to-br from-white via-fuchsia-50/60 to-fuchsia-100/60 text-fuchsia-700 shadow-fuchsia-100/50 ring-fuchsia-100', + 'teal' => 'border-teal-200 bg-gradient-to-br from-white via-teal-50/60 to-teal-100/60 text-teal-700 shadow-teal-100/50 ring-teal-100', + ]; + + $selectedTargets = old('targets', []); + @endphp + +
+
+
+
+
+ + Zona Sensitif +
+

Reset data selektif untuk bersih-bersih aplikasi

+

Gunakan halaman ini saat Mas memang ingin mengosongkan data tertentu tanpa mengutak-atik struktur aplikasi. Sistem akan menambahkan dependensi penting agar proses hapus tidak mentok foreign key dan file storage terkait ikut dibersihkan.

+
+
+
+
Target Tersedia
+
{{ count($targets) }}
+
+
+
Perlu Konfirmasi
+
Password admin aktif
+
+
+
+ +
+
+
Aman dari relasi putus
+
Dependensi wajib dibersihkan otomatis supaya data yatim tidak tertinggal.
+
+
+
Tidak ada undo dari UI
+
Kalau sudah diproses, pemulihan harus lewat backup atau input ulang data.
+
+
+
Storage ikut dibersihkan
+
Dokumen dan lampiran terkait target reset akan ikut dihapus dari disk publik.
+
+
+
Pilih seperlunya
+
Mas bisa kosongkan satu area saja tanpa harus reset semuanya sekaligus.
+
+
-
-
Tahun
{{ $stats['academicYears'] }}
-
Jurusan
{{ $stats['departments'] }}
-
Kelas
{{ $stats['classes'] }}
-
Jenis Dokumen
{{ $stats['documentTypes'] }}
-
Siswa
{{ $stats['students'] }}
-
Ortu/Wali
{{ $stats['studentParents'] }}
-
Dokumen
{{ $stats['studentDocuments'] }}
-
Histori
{{ $stats['studentAcademicHistories'] }}
+
+ @foreach ($statCards as $card) + @php + $cardClasses = $accentClasses[$card['accent']] ?? $accentClasses['slate']; + @endphp +
+
+
+
{{ $card['label'] }}
+
{{ $card['value'] }}
+
+
+ +
+
+
+ @endforeach
-
- @csrf + + + @csrf -
-
Pilih data yang ingin dikosongkan
-
+
+
+
Pilih target reset
+
Gunakan pilihan ini dengan hati-hati. Beberapa target akan menarik dependensi tambahan secara otomatis.
+
+
+ + +
+ + +
+
+
+ +
@foreach ($targets as $key => $label) -