Daftar Surat Masuk

Kelola dan monitor surat masuk

@if(auth()->user()->isOperator() || auth()->user()->isOperatorTU()) Tambah Surat Masuk @endif
Filter & Pencarian
@php // Hanya pilihan status yang disepakati; nilai value tetap kompatibel backend $currentStatus = request()->filled('status') ? request('status') : ''; $statusPilihanStandar = ['', 'perlu_aksi_saya', 'diproses', 'sudah_didisposisi', 'menunggu_tanggapan', 'selesai']; if (auth()->user()->isPAURMIN()) { array_splice($statusPilihanStandar, 2, 0, 'menunggu_verifikasi_kasmin'); } $statusLainAktif = $currentStatus !== '' && !in_array($currentStatus, $statusPilihanStandar, true) && $currentStatus !== 'disposisi_pangwapang_grup_sat'; @endphp
@php $currentPerPage = request('per_page', 10); @endphp
{{-- Tujuan Filter - Only for SETUM --}} @if(auth()->user()->isSETUM() && isset($tujuanList) && $tujuanList->count() > 0)
@endif
Reset @if(request()->hasAny(['search', 'status', 'bulan', 'tahun'])) Filter Aktif @endif
Menampilkan {{ $suratMasuks->firstItem() ?? 0 }} - {{ $suratMasuks->lastItem() ?? 0 }} dari {{ $suratMasuks->total() }} surat masuk
Export Excel Export PDF
Daftar Surat Masuk
@php // IDs yang ada di tabel (untuk cek apakah parent ada di tabel) $idsInTable = $suratMasuks->pluck('id')->toArray(); // Precompute parent IDs that have child surat dari DISPOSISI (bukan dari storeAgenda) // Child dari storeAgenda tidak dihitung sebagai "Sudah Didisposisi" $parentIdsInList = $suratMasuks->filter(fn($s) => $s->parent_surat_id && $s->is_from_disposisi)->pluck('parent_surat_id')->unique(); // Compute root parent ID for each surat and count ALL children per root // Termasuk storeAgenda children dan disposisi children $rootChildCount = []; foreach ($suratMasuks as $s) { if ($s->parent_surat_id) { $rootId = ($s->parentSurat && $s->parentSurat->parent_surat_id) ? $s->parentSurat->parent_surat_id : $s->parent_surat_id; $rootChildCount[$rootId] = ($rootChildCount[$rootId] ?? 0) + 1; } } // Compute which parents have ALL storeAgenda children disposisi'd // storeAgenda children = children with parent_surat_id but NOT is_from_disposisi $storeAgendaByParent = []; foreach ($suratMasuks as $s) { if ($s->parent_surat_id && !$s->is_from_disposisi) { $storeAgendaByParent[$s->parent_surat_id][] = $s->id; } } // IDs of storeAgenda children that have been disposisi'd (have is_from_disposisi grandchildren) $disposisidChildIds = $suratMasuks->filter(fn($s) => $s->parent_surat_id && $s->is_from_disposisi) ->pluck('parent_surat_id')->unique(); // Parent is "Sudah Didisposisi" ONLY if ALL storeAgenda children are disposisi'd $fullyDisposisiParentIds = collect(); foreach ($storeAgendaByParent as $parentId => $childIds) { $allDone = collect($childIds)->every(fn($id) => $disposisidChildIds->contains($id)); if ($allDone) { $fullyDisposisiParentIds->push($parentId); } } @endphp @forelse($suratMasuks as $index => $surat) @php // Determine URL and status based on user role and disposisi status $url = route('surat-masuk.show', $surat->id); $icon = 'eye'; $title = 'Lihat Detail'; $isMohonDiselesaikan = false; $isMohonTanggapan = false; $isPerluDilengkapi = false; $isSelesaiForUser = false; $isTeruskanKeSesIT = false; $isHiddenAction = false; $isPaurminPerluLengkapi = false; // General rule: jika tujuan surat BUKAN dirinya dan BUKAN superiornya // maka hide semua tombol aksi (view only) — KECUALI staf monitoring SMIN // (KASMIN/PAURMIN/operator SMIN) yang wajib punya akses baca/lihat detail $tujuanId = $surat->tujuan_akhir_id; $myId = auth()->id(); $mySuperiorId = auth()->user()->superior_id; $tujuanBukanUntukSaya = $tujuanId != $myId && $tujuanId != $mySuperiorId; if ($tujuanBukanUntukSaya) { if (!auth()->user()->isKASMIN() && !auth()->user()->isPAURMIN() && !auth()->user()->isOperatorSmin()) { $isHiddenAction = true; } } // PAURMIN SMIN: surat jalur SMIN→Pang/Wapang menunggu lembar disposisi if (auth()->user()->isPAURMIN() && $surat->isMenungguAgenda() && $surat->isSminPangwapangRoute()) { $isPaurminPerluLengkapi = true; $isPerluDilengkapi = true; $url = route('surat-masuk.show', $surat->id); $icon = 'clipboard-check'; $title = 'Lengkapi Lembar Disposisi'; } // KASMIN: surat menunggu verifikasi setelah diteruskan PAURMIN if (auth()->user()->isKASMIN() && $surat->isMenungguVerifikasiKasmin()) { $isMohonDiselesaikan = true; $url = route('surat-masuk.show', $surat->id); $icon = 'clipboard-data'; $title = 'Verifikasi Surat'; } // Check if user is TU IT (not TU Bagian) $isTUIT = auth()->user()->isTU() && strtoupper(auth()->user()->satuan ?? '') === 'IT' && !auth()->user()->isTUBagian(); // For TU/Operator TU: Cek semua disposisi yang ditujukan ke TU untuk surat ini if (auth()->user()->isTU() || auth()->user()->isOperatorTU()) { // Ambil disposisi untuk TU pada surat ini (TU sebagai penerima) $disposisiForTU = $surat->disposisi() ->whereHas('kepadaUsers', function($q) { $q->where('user_id', auth()->id()); }) ->where('status', '!=', 'selesai') ->latest() ->first(); if ($disposisiForTU) { // Ada disposisi untuk TU - tentukan apakah perlu lengkapi atau proses $pengirim = $disposisiForTU->dariUser; $userSatuan = auth()->user()->satuan; $pengirimSatuan = $pengirim->satuan ?? null; $isFromSuperior = $disposisiForTU->pengirim_id === auth()->user()->superior_id; $isFromSameSatuan = $pengirimSatuan === $userSatuan; $isFromPangwapang = $pengirim && ($pengirim->isPanglima() || $pengirim->isWakilPanglima()); // Logic: // 1. Dari pimpinan satuan sendiri (superior) atau satuan sama → Mohon Diselesaikan // 2. Dari satuan berbeda → Perlu Dilengkapi // 3. Dari Panglima/Wapang: // - Jika status_agenda = 'menunggu_agenda' → Perlu Dilengkapi // - Jika status_agenda = 'diagendakan' atau null → Mohon Diselesaikan if ($isFromSuperior || $isFromSameSatuan) { $isMohonDiselesaikan = true; $url = route('surat-masuk.show', $surat->id); $icon = 'clipboard-data'; $title = 'Proses Disposisi'; } elseif ($isFromPangwapang) { // Disposisi dari Panglima/Wapang ke TU // Hanya tampilkan aksi jika tujuan surat = superior TU (Wadansat/Dansat) // Jika tujuan = Panglima (bukan superior TU) → hide, TU tidak perlu aksi $isTujuanSuperior = $surat->tujuan_akhir_id == auth()->user()->superior_id; if ($isTujuanSuperior) { if ($disposisiForTU->status_agenda === 'menunggu_agenda') { $isPerluDilengkapi = true; $url = route('surat-masuk.show', $surat->id); $icon = 'eye'; $title = 'Lihat Detail Surat'; } else { $isMohonDiselesaikan = true; $url = route('surat-masuk.show', $surat->id); $icon = 'clipboard-data'; $title = 'Proses Disposisi'; } } // Jika bukan superior → general isHiddenAction sudah handle } else { // Dari satuan berbeda $isPerluDilengkapi = true; $url = route('surat-masuk.show', $surat->id); $icon = 'eye'; $title = 'Lihat Detail Surat'; } } // Cek surat dari disposisi yang ditujukan ke TU if (!$isMohonDiselesaikan && !$isMohonTanggapan && !$isPerluDilengkapi && !$isSelesaiForUser && $surat->is_from_disposisi && $surat->tujuan_akhir_id == auth()->id()) { if (in_array($surat->status, ['pending', 'diproses'])) { $isMohonDiselesaikan = true; $icon = 'clipboard-data'; $title = 'Proses Surat'; } elseif ($surat->status === 'selesai') { $isSelesaiForUser = true; } } // Jika surat perlu dilengkapi lembar disposisinya (surat baru, TU bukan penerima disposisi) // Hanya tampilkan "Perlu Dilengkapi" jika TU/Operator ini bertanggung jawab // TU: surat ditujukan ke diri sendiri atau superior (pimpinan) // Operator TU: surat ditujukan ke diri sendiri, superior (TU), atau grand-superior (pimpinan TU) // KECUALI jika user sendiri yang membuat surat (tampilkan "Sudah Dikirim" instead) if (!$isMohonDiselesaikan && !$isMohonTanggapan && !$isPerluDilengkapi && !$isSelesaiForUser && !$disposisiForTU) { if ($surat->status === 'menunggu_agenda' && $surat->created_by != auth()->id()) { $grandSuperiorId = auth()->user()->superior?->superior_id; $isResponsibleTU = $surat->tujuan_akhir_id == auth()->user()->superior_id || $surat->tujuan_akhir_id == auth()->id() || ($grandSuperiorId && $surat->tujuan_akhir_id == $grandSuperiorId); if ($isResponsibleTU) { // TU IT hanya teruskan ke SES IT, bukan lengkapi lembar disposisi if ($isTUIT) { $isTeruskanKeSesIT = true; } else { $isPerluDilengkapi = true; } $url = route('surat-masuk.show', $surat->id); $icon = 'eye'; $title = 'Lihat Detail Surat'; } } } } // Untuk semua user: Cek apakah user menerima disposisi untuk surat ini if (!$isPerluDilengkapi && !$isMohonDiselesaikan && !$isMohonTanggapan && !$isSelesaiForUser && !$isHiddenAction) { // Cek disposisi dimana user adalah penerima (semua status termasuk selesai) $disposisiForUser = $surat->disposisi() ->whereHas('kepadaUsers', function($q) { $q->where('user_id', auth()->id()); }) ->latest() ->first(); // Juga cek via tujuan_akhir_id (surat dari disposisi) $isDisposisiRecipient = ($disposisiForUser !== null) || ($surat->is_from_disposisi && $surat->tujuan_akhir_id == auth()->id()); if ($isDisposisiRecipient) { // Disposisi sudah selesai untuk user ini? $disposisiSelesai = $disposisiForUser && strtolower($disposisiForUser->status) === 'selesai'; // User sudah disposisi ke bawahan? $recipientAlreadyDisposisi = \App\Models\Disposisi::where('surat_masuk_id', $surat->id) ->where('pengirim_id', auth()->id()) ->exists(); if ($disposisiSelesai || $recipientAlreadyDisposisi) { // Disposisi sudah selesai atau sudah diteruskan → selesai untuk user ini $isSelesaiForUser = true; } elseif (in_array($surat->status, ['pending', 'diproses', 'diagendakan'])) { $recipientUser = auth()->user(); $recipientHasSubordinates = $recipientUser->hasSubordinates(); $recipientCanCreateDisposisi = $recipientUser->canCreateDisposisi(); if ($recipientHasSubordinates && $recipientCanCreateDisposisi) { // Punya 2 opsi: disposisi ke bawahan ATAU selesaikan $isMohonTanggapan = true; } else { // Hanya bisa selesaikan (tidak bisa disposisi lagi) $isMohonDiselesaikan = true; } $url = route('surat-masuk.show', $surat->id); $icon = 'clipboard-data'; $title = 'Proses Surat'; } elseif ($surat->status === 'selesai') { $isSelesaiForUser = true; } } } // Cek child surat: apakah semua disposisi chain sudah selesai if (!$isSelesaiForUser && !$isMohonDiselesaikan && !$isMohonTanggapan && !$isPerluDilengkapi && !$isHiddenAction) { $allDisposisiOnSurat = $surat->disposisi()->get(); if ($allDisposisiOnSurat->isNotEmpty()) { // Cari leaf disposisi (penerima yang tidak meneruskan lagi) $allPengirimIds = $allDisposisiOnSurat->pluck('pengirim_id')->unique(); $leafDisposisi = $allDisposisiOnSurat->filter(function($d) use ($allPengirimIds) { return !$d->kepadaUsers->pluck('id')->intersect($allPengirimIds)->isNotEmpty(); }); // Jika semua leaf disposisi selesai → surat ini selesai if ($leafDisposisi->isNotEmpty() && $leafDisposisi->every(fn($d) => strtolower($d->status) === 'selesai')) { $isSelesaiForUser = true; } } } // Row highlighting logic // Jika hidden action (surat bukan untuk diri/superior), force view-only if ($isHiddenAction) { $isPerluDilengkapi = false; $isMohonDiselesaikan = false; $isMohonTanggapan = false; $isTeruskanKeSesIT = false; $url = route('surat-masuk.show', $surat->id); $icon = 'eye'; $title = 'Lihat Detail'; } $rowClass = ''; if ($isTeruskanKeSesIT) { $rowClass = 'row-teruskan-ses-it'; } elseif ($isPerluDilengkapi) { $rowClass = 'row-perlu-dilengkapi'; } elseif ($isMohonDiselesaikan || $isMohonTanggapan) { $rowClass = 'table-warning bg-warning bg-opacity-10'; } elseif ($surat->is_kilat) { $rowClass = 'table-danger bg-danger bg-opacity-10'; } elseif ($surat->status === 'draft') { $rowClass = 'table-warning bg-warning bg-opacity-10'; } // Add parent-child visual grouping class $isChildRow = false; $childRootId = null; if ($surat->is_from_disposisi || ($surat->parent_surat_id && !$parentIdsInList->contains($surat->id))) { $childRootId = ($surat->parentSurat && $surat->parentSurat->parent_surat_id) ? $surat->parentSurat->parent_surat_id : $surat->parent_surat_id; // Hanya jadikan child row jika parent root ada di tabel if ($childRootId && in_array($childRootId, $idsInTable)) { $rowClass .= ' row-from-disposisi'; $isChildRow = true; } } elseif ($surat->parent_surat_id && $parentIdsInList->contains($surat->id)) { // Intermediate node (clone child that IS also a parent) $childRootId = $surat->parent_surat_id; if (in_array($childRootId, $idsInTable)) { $rowClass .= ' row-from-disposisi'; $isChildRow = true; } } elseif ($parentIdsInList->contains($surat->id) || isset($storeAgendaByParent[$surat->id])) { $rowClass .= ' row-parent-disposisi'; } $isParentRow = isset($rootChildCount[$surat->id]); $childCount = $rootChildCount[$surat->id] ?? 0; @endphp @empty @endforelse
No. Agenda Nomor Surat Tanggal Asal Perihal Tujuan Kategori Status Aksi
Tidak ada data surat masuk

@if(request()->hasAny(['search', 'status', 'bulan', 'tahun'])) Tidak ada data yang sesuai dengan filter yang dipilih. Reset filter @else Belum ada surat masuk yang ditambahkan. @endif

@if($suratMasuks->hasPages()) @endif
@push('styles') @endpush @push('scripts') @endpush