diff --git a/app/Http/Controllers/HistoryKegiatanController.php b/app/Http/Controllers/HistoryKegiatanController.php deleted file mode 100644 index 31a4c77..0000000 --- a/app/Http/Controllers/HistoryKegiatanController.php +++ /dev/null @@ -1,66 +0,0 @@ -get(); - return Inertia::render('admin/kegiatan/index_history_kegiatan', ['historykegiatan' => $historykegiatan]); - } catch (\Exception $e) { - Log::error('Error fetching History Kegiatan: ' . $e->getMessage()); - return back()->with('error', 'Something went wrong.'); - } - } - - public function store(HistoryKegiatanRequest $request) - { - try { - $historykegiatan = HistoryKegiatan::withTrashed() - ->where('NamaHistoryKegiatan', $request->NamaHistoryKegiatan) - ->first(); - - if ($historykegiatan) { - $historykegiatan->restore(); - return redirect()->route('admin.historykegiatan.index')->with('success', 'History Kegiatan berhasil dikembalikan.'); - } - - HistoryKegiatan::create($request->validated()); - - return redirect()->route('admin.historykegiatan.index')->with('success', 'History Kegiatan berhasil dibuat.'); - } catch (\Exception $e) { - Log::error('Error creating History Kegiatan: ' . $e->getMessage()); - return back()->with('error', 'Something went wrong.'); - } - } - - public function update(HistoryKegiatanRequest $request, HistoryKegiatan $historykegiatan) - { - try { - $historykegiatan->update($request->validated()); - return redirect()->route('admin.history$historykegiatan.index')->with('success', 'History Kegiatan berhasil diperbarui.'); - } catch (\Exception $e) { - Log::error('Error updating History Kegiatan: ' . $e->getMessage()); - return back()->with('error', 'Something went wrong.'); - } - } - - public function destroy(HistoryKegiatan $historykegiatan) - { - try { - $historykegiatan->delete(); - return redirect()->route('admin.histo$historykegiatan.index')->with('success', 'History Kegiatan berhasil dihapus.'); - } catch (\Exception $e) { - Log::error('Error deleting History Kegiatan: ' . $e->getMessage()); - return back()->with('error', 'Something went wrong.'); - } - } -} diff --git a/app/Http/Controllers/HistoryPerusahaanController.php b/app/Http/Controllers/HistoryPerusahaanController.php index f78f46a..6437b81 100644 --- a/app/Http/Controllers/HistoryPerusahaanController.php +++ b/app/Http/Controllers/HistoryPerusahaanController.php @@ -3,12 +3,12 @@ namespace App\Http\Controllers; use App\Http\Requests\HistoryPerusahaanRequest; -use App\Models\HistoryKegiatan; use App\Models\HistoryPerusahaan; use App\Models\Kabupaten; use App\Models\Kecamatan; use App\Models\Kelurahan; use App\Models\Perusahaan; +use App\Models\RefHistoryKegiatan; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; @@ -19,7 +19,7 @@ class HistoryPerusahaanController extends Controller public function index() { try{ - $historyPerusahaan = HistoryPerusahaan::with(['perusahaan', 'historyKegiatan', 'kelurahan.kecamatan.kabupaten'])->orderBy('created_at', 'desc')->get(); + $historyPerusahaan = HistoryPerusahaan::with(['perusahaan', 'refhistoryKegiatan', 'kelurahan.kecamatan.kabupaten'])->orderBy('created_at', 'desc')->get(); // Eager load companies with their relationships $perusahaan = Perusahaan::with('kelurahan.kecamatan.kabupaten')->get() @@ -32,7 +32,7 @@ class HistoryPerusahaanController extends Controller return Inertia::render('admin/history_perusahaan/index_history_perusahaan', [ 'historyPerusahaan' => $historyPerusahaan, 'perusahaan' => $perusahaan, - 'historyKegiatan' => HistoryKegiatan::all(), + 'refhistoryKegiatan' => RefHistoryKegiatan::all(), 'kabupaten' => Kabupaten::all(), 'kecamatan' => Kecamatan::all(), 'kelurahan' => Kelurahan::all(), @@ -77,13 +77,13 @@ class HistoryPerusahaanController extends Controller { $perusahaan = Perusahaan::with('historyPerusahaan')->findOrFail($perusahaanId); - $historyKegiatan = HistoryKegiatan::all(); + $refhistoryKegiatan = RefHistoryKegiatan::all(); - $historyPerusahaan = HistoryPerusahaan::with('historyKegiatan')->where('PerusahaanId', $perusahaanId)->get(); + $historyPerusahaan = HistoryPerusahaan::with('refhistoryKegiatan')->where('PerusahaanId', $perusahaanId)->get(); return Inertia::render('admin/history_perusahaan/detail_history_perusahaan', [ 'perusahaan' => $perusahaan, - 'historyKegiatan' => $historyKegiatan, + 'refhistoryKegiatan' => $refhistoryKegiatan, 'historyPerusahaan' => $historyPerusahaan, ]); } @@ -100,7 +100,7 @@ public function update(Request $request, $historyPerusahaanId) 'PerusahaanId' => 'required|integer', 'NomorHistory' => 'required|string', 'TanggalHistory' => 'required|date', - 'HistoryKegiatanId' => 'required|integer', + 'RefHistoryKegiatanId' => 'required|integer', 'KeteranganHistory' => 'nullable|string', 'DokumenHistory' => 'nullable|file|mimes:pdf', ]); diff --git a/app/Http/Controllers/Pelaporan/AL/ALController.php b/app/Http/Controllers/Pelaporan/AL/ALController.php new file mode 100644 index 0000000..82c1feb --- /dev/null +++ b/app/Http/Controllers/Pelaporan/AL/ALController.php @@ -0,0 +1,524 @@ + + */ +class ALController extends Controller +{ + const ID_REFPELAPORAN = 2; + + /** + * Menampilkan halaman laporan + */ + public function laporan($idPelaporan) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + // Load models + $pelaporan = Pelaporan::findOrFail($idPelaporan); + + // Set breadcrumb data + $breadcrumb = $this->_generateBreadcrumb('Pelaporan'); + + // Get editable status + $editable = $this->_isEditable($idPelaporan, 'AL') && Gate::allows('pelaporan.edit'); + + // Check IPAL Komunal status + $ipalKomunal = $this->_getIpalKomunalStatus($idPelaporan); + $lampiranSk = 0; + $verifikasiSk = ''; + $ketSk = ''; + + if ($ipalKomunal) { + if ($ipalKomunal->tersambung == 'Iya') { + $sk = Lampiran::getKomponenByKode('SK'); + if ($sk) { + $lampiranSk = $this->_cekLampiranSk($idPelaporan, $sk->id) ? 1 : 0; + } + } + + // Verifikasi surat kerjasama + $idKomponenSk = Lampiran::getKomponenByKode('SK')->id; + $komponenSk = Ipal::getNilaiKomponen([ + 'idmcpelaporan' => $idPelaporan, + 'idrefkomponen' => $idKomponenSk + ]); + + if (!$editable && $komponenSk) { + if ($komponenSk->verifikasi !== null) { + $verifikasiSk = $komponenSk->verifikasi == '1' ? 'Approved' : 'Not Approved'; + } + $ketSk = $komponenSk->keterangan; + } + } + + // Prepare data for view + $data = [ + 'breadcrumb' => $breadcrumb, + 'NamaPerusahaan' => $pelaporan->perusahaan, + 'Tahun' => $pelaporan->tahun, + 'periode' => $pelaporan->periode, + 'editable' => $editable, + 'lampiran_sk' => $lampiranSk, + 'verifikasi_sk' => $verifikasiSk, + 'ipal_komunal' => $ipalKomunal ? $ipalKomunal->tersambung : '', + 'ket_sk' => $ketSk, + 'idmcpelaporan' => $idPelaporan, + 'catatan' => Komponen::getCatatan($idPelaporan, self::ID_REFPELAPORAN) + ]; + + return view('pelaporan.al', $data); + } + + /** + * Function to load al table + */ + public function table($idPelaporan) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + // Load pelaporan data + $pelaporan = Pelaporan::findOrFail($idPelaporan); + + // Get reference data + $getData = Komponen::getDataRef(self::ID_REFPELAPORAN); + $dataTable = $getData['data']; + $rowspan1 = $getData['total_rows'] + 1; + + // Get nilai komponen + $nilaiKomponen = Komponen::getNilaiKomponen($idPelaporan, self::ID_REFPELAPORAN); + + // Get nilai komponen A6 and A7 + $komponenCodes = ['A6', 'A7']; + $nilaiData = []; + + foreach ($komponenCodes as $code) { + $nilaiData['nilai_' . $code] = ''; + $idRefKomponen = Ipal::getIdRefKomponen($code); + $filter = [ + 'idmcpelaporan' => $idPelaporan, + 'idrefkomponen' => $idRefKomponen + ]; + + $nilaiKomponenValue = Ipal::getNilaiKomponen($filter); + if ($nilaiKomponenValue) { + $nilaiData['nilai_' . $code] = $nilaiKomponenValue->nilai; + } + } + + // Get nilai syarat teknis + $kodeSyaratTeknis = ['A1', 'A2', 'A3', 'A4', 'A5']; + $nilaiSyaratTeknis = []; + + foreach ($kodeSyaratTeknis as $kode) { + $idKomponen = Ipal::getIdRefKomponen($kode); + $komponenSyaratTeknis = Ipal::getNilaiKomponen([ + 'idmcpelaporan' => $idPelaporan, + 'idmcipal' => null, + 'idrefkomponen' => $idKomponen + ]); + + $nilaiSyaratTeknis[$kode] = $komponenSyaratTeknis ? $komponenSyaratTeknis->nilai : 0; + } + + // Update nilai SPL + $this->_updateNilaiSpl($idPelaporan); + $spl = number_format($pelaporan->spl_al, 2, '.', ' '); + + $splAl = Ipal::getNilaiSpl($idPelaporan); + $spl2 = $splAl ? number_format($splAl->nilaispl, 2, '.', ' ') : 0; + + // Prepare data for view + $data = array_merge($nilaiData, [ + 'data_table' => $dataTable, + 'rowspan_1' => $rowspan1, + 'nilai_komponen' => $nilaiKomponen, + 'nilai_syarat_teknis' => $nilaiSyaratTeknis, + 'spl' => $spl, + 'spl_2' => $spl2, + 'idmcpelaporan' => $idPelaporan, + 'idrefpelaporan' => self::ID_REFPELAPORAN + ]); + + return view('pelaporan.al_table', $data); + } + + /** + * Display SPL data + */ + public function spl($idPelaporan) + { + // Load pelaporan data + $pelaporan = Pelaporan::findOrFail($idPelaporan); + $spl = Ipal::getNilaiSpl($idPelaporan); + + // Prepare data for view + $data = [ + 'NamaPerusahaan' => $pelaporan->perusahaan, + 'Tahun' => $pelaporan->tahun, + 'periode' => $pelaporan->periode, + 'spl' => $spl + ]; + + return view('pelaporan.spl_al', $data); + } + + /** + * Check if there are attachments + */ + public function cekAdaLampiran($idPelaporan) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + $response = Lampiran::cekAdaLampiran($idPelaporan, self::ID_REFPELAPORAN); + return response()->json($response); + } + + /** + * Check for surat kerjasama + */ + public function cekSuratKerjasama($idPelaporan) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + $sk = Lampiran::getKomponenByKode('SK'); + if ($sk) { + $lampiranSk = $this->_cekLampiranSk($idPelaporan, $sk->id); + $response = ['lampiran' => $lampiranSk ? true : false]; + } else { + $response = ['lampiran' => false]; + } + + return response()->json($response); + } + + /** + * Save AL data + */ + public function simpan(Request $request, $idPelaporan) + { + // Check authorization + if (!Gate::allows('pelaporan.view') || !Gate::allows('pelaporan.edit')) { + abort(403); + } + + $dataCatatan = $request->input('catatan'); + $dataHasil = []; + + if ($request->has('hasil')) { + foreach ($request->input('hasil') as $row => $value) { + $dataHasil[$row] = $value; + } + } + + if (!empty($dataHasil)) { + Komponen::updateHasil($idPelaporan, self::ID_REFPELAPORAN, $dataHasil); + } + + // Update SKL nilai if provided + if ($request->has('skl-nilai')) { + $nilaiSkl = $request->input('skl-nilai'); + Pelaporan::updateNilaiSkl($idPelaporan, self::ID_REFPELAPORAN, $nilaiSkl); + Pelaporan::updateAvgSkl($idPelaporan); + } + + // Update status IPAL Komunal + $statusIpalKomunal = $request->input('ipal_komunal', 'Tidak'); + $this->_updateStatusIpalKomunal($idPelaporan, $statusIpalKomunal); + + // Save catatan + Komponen::simpanCatatan($idPelaporan, self::ID_REFPELAPORAN, $dataCatatan); + + // Update mcpelaporan_date + Pelaporan::updateTanggalPelaporan([ + 'id_mcpelaporan' => $idPelaporan, + 'id_refpelaporan' => self::ID_REFPELAPORAN + ], now()->toDateString()); + + // Update table mcverifikasi + $filter = [ + 'idmcpelaporan' => $idPelaporan, + 'idrefpelaporan' => self::ID_REFPELAPORAN + ]; + + $dataUpdate = [ + 'verifikasi' => 1, + 'tanggal' => now()->format('Y-m-d H:i:s'), + 'oleh' => Auth::id() + ]; + + Pelaporan::updateStatusVerifikasi($filter, $dataUpdate); + + // Log activity + $pelaporan = Pelaporan::findOrFail($idPelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . + ' - Periode ' . $pelaporan->periode; + + Log::info('LOG_EDIT', ['message' => $aktivitas, 'module' => 'pelaporan']); + + $response = [ + 'message' => 'Data Pengelolaan Air Limbah berhasil disimpan', + 'status' => 'success' + ]; + + return response()->json($response); + } + + /** + * Export data to PDF + */ + public function exportPdf($idPelaporan) + { + // Check authorization + if (!Gate::allows('pelaporan.export')) { + abort(403); + } + + // Load pelaporan data + $pelaporan = Pelaporan::findOrFail($idPelaporan); + + // Prepare data for PDF + $getData = Komponen::getDataRef(self::ID_REFPELAPORAN); + $dataTable = $getData['data']; + $rowspan1 = $getData['total_rows'] + 1; + $nilaiKomponen = Komponen::getNilaiKomponen($idPelaporan, self::ID_REFPELAPORAN); + $catatan = Komponen::getCatatan($idPelaporan, self::ID_REFPELAPORAN); + + // Get IPAL Komunal status + $ipalKomunal = $this->_getIpalKomunalStatus($idPelaporan); + $lampiranSk = 0; + $komponenSk = null; + + if ($ipalKomunal) { + $statusIpalKomunal = $ipalKomunal->tersambung; + // Check lampiran surat kerjasama + $sk = Lampiran::getKomponenByKode('SK'); + if ($sk) { + $lampiranSk = $this->_cekLampiranSk($idPelaporan, $sk->id); + if ($lampiranSk) { + $komponenSk = Ipal::getNilaiKomponen([ + 'idmcpelaporan' => $idPelaporan, + 'idrefkomponen' => $sk->id + ]); + $lampiranSk = 1; + } + } + } else { + $statusIpalKomunal = 'Tidak'; + } + + // Get syarat teknis values + $syaratTeknis = ['A1', 'A2', 'A3', 'A4', 'A5']; + $nilaiSyaratTeknis = []; + + foreach ($syaratTeknis as $kode) { + $idKomponen = Ipal::getIdRefKomponen($kode); + $komponenSyaratTeknis = Ipal::getNilaiKomponen([ + 'idmcpelaporan' => $idPelaporan, + 'idmcipal' => null, + 'idrefkomponen' => $idKomponen + ]); + + $nilaiSyaratTeknis[$kode] = $komponenSyaratTeknis ? $komponenSyaratTeknis->nilai : 0; + } + + // Get SKL and SPL values + $skl = Pelaporan::getNilaiSkl($idPelaporan, self::ID_REFPELAPORAN); + $spl = $ipalKomunal && $ipalKomunal->tersambung == 'Iya' ? 100 : number_format($pelaporan->spl_al, 2, '.', ' '); + + // Generate PDF + $pdf = PDF::loadView('pelaporan.al_pdf', [ + 'NamaPerusahaan' => $pelaporan->perusahaan, + 'Tahun' => $pelaporan->tahun, + 'periode' => $pelaporan->periode, + 'data_table' => $dataTable, + 'rowspan_1' => $rowspan1, + 'nilai_komponen' => $nilaiKomponen, + 'catatan' => $catatan, + 'ipal_komunal' => $statusIpalKomunal, + 'lampiran_sk' => $lampiranSk, + 'komponen_sk' => $komponenSk, + 'skl' => $skl, + 'spl' => $spl, + 'nilai_syarat_teknis' => $nilaiSyaratTeknis + ]); + + return $pdf->download('Laporan_al_' . $pelaporan->perusahaan . '_' . $pelaporan->tahun . '_' . $pelaporan->periode . '.pdf'); + } + + /** + * Update nilai SPL + */ + private function _updateNilaiSpl($idPelaporan) + { + $allIpal = Ipal::getData($idPelaporan); + $jmlParam = 0; + $memenuhiBakuMutu = 0; + $memenuhiBatasEmisi = 0; + + foreach ($allIpal as $ipal) { + $params = IpalParameter::getData($ipal->id); + $jmlParam += count($params); + + $allHasilUji = Ipal::getAllHasilUjiBy([ + 'idmcipal' => $ipal->id, + 'nilai !=' => null + ]); + + // Check each hasil uji against bakumutu + foreach ($allHasilUji as $hasilUji) { + $param = IpalParameter::getOneBy(['id' => $hasilUji->idmcipal_parameter]); + + if ($hasilUji->nilai == '*') { + $memenuhiBakuMutu++; + } elseif ($hasilUji->debit != null && $param->bakumutu_jenis != 'Positif/Negatif' && $param->batasemisi) { + if ($hasilUji->bebanemisi <= $param->batasemisi) { + $memenuhiBatasEmisi++; + } + } else { + if ($param->bakumutu_jenis == 'Angka Tunggal') { + if ($hasilUji->nilai <= $param->bakumutu_nilai1) { + $memenuhiBakuMutu++; + } + } elseif ($param->bakumutu_jenis == 'Rentang Angka') { + if ($hasilUji->nilai >= $param->bakumutu_nilai1 && $hasilUji->nilai <= $param->bakumutu_nilai2) { + $memenuhiBakuMutu++; + } + } elseif ($param->bakumutu_jenis == 'Positif/Negatif') { + if (strtolower($hasilUji->nilai) == strtolower($param->bakumutu_nilai1)) { + $memenuhiBakuMutu++; + } + } + } + } + } + + $totalParam = $jmlParam * 3; + $melebihiBakuMutuEmisi = $totalParam - $memenuhiBakuMutu - $memenuhiBatasEmisi; + $nilaiSpl = $totalParam ? 100 - (($melebihiBakuMutuEmisi / $totalParam) * 100) : 0; + + // Save or update nilai SPL + $splAl = Ipal::getNilaiSpl($idPelaporan); + + if ($splAl) { + $data = [ + 'diuji' => $totalParam, + 'melebihi' => $melebihiBakuMutuEmisi, + 'nilaispl' => $nilaiSpl + ]; + Ipal::updateNilaiSpl($idPelaporan, $data); + } else { + $data = [ + 'idmcpelaporan' => $idPelaporan, + 'diuji' => $totalParam, + 'melebihi' => $melebihiBakuMutuEmisi, + 'nilaispl' => $nilaiSpl + ]; + Ipal::insertNilaiSpl($data); + } + } + + /** + * Generate breadcrumb + */ + private function _generateBreadcrumb($module) + { + // Implementation of breadcrumb generation + return ['Home' => route('home'), 'Pelaporan' => route('pelaporan.index')]; + } + + /** + * Check if report is editable + */ + private function _isEditable($idPelaporan, $module) + { + // Implementation to check if report is editable + return Pelaporan::checkEditable($idPelaporan, $module); + } + + /** + * Get Ipal Komunal status + */ + private function _getIpalKomunalStatus($idPelaporan) + { + return Spl_AL::getStatusMcKomunal($idPelaporan); + } + + /** + * Check Lampiran SK + */ + private function _cekLampiranSk($idPelaporan, $skId) + { + return LampiranAL::cekLampiranSk($idPelaporan, $skId); + } + + /** + * Update status IPAL Komunal + */ + private function _updateStatusIpalKomunal($idPelaporan, $status) + { + // Update IPAL komunal status + Spl_AL::updateStatusMcKomunal($idPelaporan, $status); + + // If connected to IPAL komunal and has SK + if ($status == 'Iya') { + $sk = Lampiran::getKomponenByKode('SK'); + if ($sk) { + $lampiranSk = $this->_cekLampiranSk($idPelaporan, $sk->id); + if ($lampiranSk) { + Pelaporan::updateNilaiSkl($idPelaporan, 2, 100); + Pelaporan::updateAvgSkl($idPelaporan); + Pelaporan::updateNilaiSpl($idPelaporan, 2, 100); + Pelaporan::updateAvgSpl($idPelaporan); + return; + } + } + } + + // Otherwise, calculate regular SPL value + $spl = Ipal::getNilaiSpl($idPelaporan); + + if ($spl) { + Pelaporan::updateNilaiSpl($idPelaporan, 2, $spl->nilaispl); + } else { + Pelaporan::updateNilaiSpl($idPelaporan, 2, 0); + } + + Pelaporan::updateAvgSpl($idPelaporan); + } +} diff --git a/app/Http/Controllers/Pelaporan/AL/IpalController.php b/app/Http/Controllers/Pelaporan/AL/IpalController.php new file mode 100644 index 0000000..525cd3a --- /dev/null +++ b/app/Http/Controllers/Pelaporan/AL/IpalController.php @@ -0,0 +1,1318 @@ + + */ +class IpalController extends Controller +{ + /** + * Display a listing of IPAL data. + * + * @param int $idPelaporan + * @return \Illuminate\Http\Response + */ + public function data($idPelaporan) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + // Load models and data + $pelaporan = Pelaporan::findOrFail($idPelaporan); + + // Prepare data for view + $data = [ + 'PelaporanId' => $idPelaporan, + 'NamaPerusahaan' => $pelaporan->perusahaan, + 'Tahun' => $pelaporan->tahun, + 'Periode' => $pelaporan->periode, + 'Editable' => Pelaporan::checkEditable($idPelaporan, 'AL') && Gate::allows('pelaporan.edit'), + ]; + + // Get IPAL komunal status + $ipalKomunal = Spl_AL::getStatusMcKomunal($idPelaporan); + $data['IpalKomunal'] = $ipalKomunal ? $ipalKomunal->tersambung : 'Tidak'; + + // Check if IPAL data exists and create from reference if not + $dataIpal = Ipal::getData($idPelaporan); + + if (!$dataIpal) { + $refIpal = Ipal::getRefIpal($pelaporan->idrefperusahaan); + + if ($refIpal) { + foreach ($refIpal as $row) { + $insertData = [ + 'PelaporanId' => $idPelaporan, + 'RefIpalId' => $row->id, + 'Nomor' => $row->nomor, + 'Nama' => $row->nama, + 'Lampiran' => $row->lampiran, + 'IzinTerbit' => $row->izin_terbit, + 'IzinHabis' => $row->izin_habis, + 'Sumber' => $row->sumber, + 'Kapasitas' => $row->kapasitas, + 'Teknologi' => $row->teknologi, + 'BadanAir' => $row->badanair + ]; + + Ipal::insertMcIpal($insertData); + } + } + } + + return view('pelaporan.ipal.index', $data); + } + + /** + * Get data for datatable. + * + * @param int $idPelaporan + * @return \Illuminate\Http\JsonResponse + */ + public function getData($idPelaporan) + { + $dataIpal = Ipal::getData($idPelaporan); + + $data = []; + foreach ($dataIpal as $row) { + $data[] = [ + $row->nomor, + $row->nama, + 0, + 0, + 0, + 0, + $row->id + ]; + } + + $response = [ + 'data' => $data, + 'recordsTotal' => count($data) + ]; + + return response()->json($response); + } + + /** + * Add new IPAL. + * + * @param int $idPelaporan + * @param Request $request + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function addIpal(Request $request, $idPelaporan) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + if ($request->has('action')) { + try { + $pelaporan = Pelaporan::findOrFail($idPelaporan); + $idrefperusahaan = $pelaporan->idrefperusahaan; + + if ($request->filled('nomor') && $request->filled('nama')) { + DB::beginTransaction(); + + try { + $dataRefIpal = [ + 'PerusahaanId' => $idrefperusahaan, + 'Nomor' => $request->input('nomor'), + 'Nama' => $request->input('nama'), + 'Lampiran' => '', + 'IzinTerbit' => '0000-00-00', + 'IzinHabis' => '0000-00-00', + 'Sumber' => '', + 'Kapasitas' => 0, + 'Teknologi' => '', + 'BadanAir' => '', + 'IsPublish' => '0' + ]; + + $idRefIpal = Ipal::insertRefIpal($dataRefIpal); + $dataMcIpal = [ + 'PelaporanId' => $idPelaporan, + 'RefIpalId' => $idRefIpal, + 'Nomor' => $request->input('nomor'), + 'Nama' => $request->input('nama'), + 'Lampiran' => '', + 'IzinTerbit' => '0000-00-00', + 'IzinHabis' => '0000-00-00', + 'Sumber' => '', + 'Kapasitas' => 0, + 'Teknologi' => '', + 'BadanAir' => '' + ]; + Ipal::insertMcIpal($dataMcIpal); + + $this->_updateRerataSyaratTeknis($idPelaporan); + $this->_updateNilaiA6($idPelaporan); + $this->_updateNilaiA7($idPelaporan); + $this->_updateNilaiSpl($idPelaporan); + + if (!$this->_cekIpalKomunal($idPelaporan)) { + $this->_updateNilaiSkl($idPelaporan); + } + + // Log activity + $perusahaan = Pelaporan::getPerusahaan($idrefperusahaan); + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . + ' - Periode ' . $pelaporan->periode . ' - Nama IPAL ' . $dataMcIpal['Nama']; + + DB::commit(); + + Log::info('LOG_CREATE', ['message' => $aktivitas, 'module' => 'pelaporan']); + + $response = ['message' => 'Data IPAL Berhasil Disimpan', 'status' => 'success']; + return response()->json($response); + + } catch (\Exception $e) { + DB::rollBack(); + Log::error('Error adding IPAL: ' . $e->getMessage(), [ + 'pelaporan_id' => $idPelaporan, + 'module' => 'pelaporan' + ]); + + $response = ['message' => 'Gagal menyimpan data IPAL: ' . $e->getMessage(), 'status' => 'error']; + return response()->json($response); + } + } else { + $response = ['message' => 'Nomor atau Nama IPAL belum diisi', 'status' => 'error']; + return response()->json($response); + } + } catch (\Exception $e) { + Log::error('Error processing IPAL request: ' . $e->getMessage(), [ + 'pelaporan_id' => $idPelaporan, + 'module' => 'pelaporan' + ]); + + $response = ['message' => 'Terjadi kesalahan saat memproses data: ' . $e->getMessage(), 'status' => 'error']; + return response()->json($response); + } + } else { + $data['PelaporanId'] = $idPelaporan; + return view('pelaporan.ipal.index', $data); + } + } + + /** + * Edit IPAL. + * + * @param Request $request + * @param int $idMcIpal + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function edit(Request $request, $idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + if ($request->has('action')) { + if ($request->filled('nomor') && $request->filled('nama')) { + $data = [ + 'Nomor' => $request->input('Nomor'), + 'Nama' => $request->input('nNama') + ]; + + Ipal::editMcIpal($idMcIpal, $data); + + if ($request->has('ref_save')) { + $idRefIpal = Ipal::getOneBy(['id' => $idMcIpal])->idrefipal; + Ipal::editRefIpal($idRefIpal, $data); + } + + // Log activity + $idmcpelaporan = Ipal::getOneBy(['id' => $idMcIpal])->idmcpelaporan; + $pelaporan = Pelaporan::findOrFail($idmcpelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . + ' - Periode ' . $pelaporan->periode . ' - Nama IPAL ' . $data['nama']; + + Log::info('LOG_EDIT', ['message' => $aktivitas, 'module' => 'pelaporan']); + + $response = ['message' => 'Data IPAL berhasil diubah', 'status' => 'success']; + } else { + $response = ['message' => 'Nomor atau Nama IPAL belum diisi', 'status' => 'error']; + } + + return response()->json($response); + } else { + $dataIpal = Ipal::getOneBy(['id' => $idMcIpal]); + + $data = [ + 'idmcipal' => $idMcIpal, + 'nomor' => $dataIpal->nomor, + 'nama' => $dataIpal->nama + ]; + + return view('pelaporan.ipal.edit_ipal', $data); + } + } + + /** + * Delete IPAL. + * + * @param Request $request + * @param int $idMcIpal + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function delete(Request $request, $idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + if ($request->has('action')) { + $idRefIpal = Ipal::getOneBy(['id' => $idMcIpal])->idrefipal; + + // Get data for logging + $idmcpelaporan = Ipal::getOneBy(['id' => $idMcIpal])->idmcpelaporan; + $pelaporan = Pelaporan::findOrFail($idmcpelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $namaIpal = Ipal::getOneBy(['id' => $idMcIpal])->nama; + + // Delete IPAL + Ipal::deleteMcIpal($idMcIpal); + + if ($request->has('ref_delete')) { + Ipal::disableRefIpal($idRefIpal); + } + + // Delete IPAL parameters, hasil uji and lampiran + IpalParameter::deleteMcIpalParam(['idmcipal' => $idMcIpal]); + Ipal::deleteHasilUji(['idmcipal' => $idMcIpal]); + Ipal::deleteLampiranHasilUji(['idmcipal' => $idMcIpal]); + + // Delete nilai komponen for syarat teknis + Ipal::deleteNilaiKomponen(['idmcipal' => $idMcIpal]); + + // Delete lampiran for komponen syarat teknis + Lampiran::deleteFile(['idmcipal' => $idMcIpal]); + + // Delete lampiran files + $notAllowedChar = [' ', '.', '/', '-', ',', ':']; + $noInduk = $perusahaan->nomorinduk; + $tahun = $pelaporan->tahun; + $periode = strtolower(str_replace($notAllowedChar, '_', $pelaporan->periode)); + $urlLampiran = 'data_perusahaan/' . $noInduk . '/lampiran' . '/' . 'al' . '/' . $tahun . '_' . $periode . '/' . str_replace($notAllowedChar, '_', $namaIpal) . '/'; + + $this->_recursiveRmdir(storage_path('app/public/' . $urlLampiran)); + + // Update values + $this->_updateRerataSyaratTeknis($idmcpelaporan); + $this->_updateNilaiA6($idmcpelaporan); + $this->_updateNilaiA7($idmcpelaporan); + $this->_updateNilaiSpl($idmcpelaporan); + + if (!$this->_cekIpalKomunal($idmcpelaporan)) { + $this->_updateNilaiSkl($idmcpelaporan); + } + + // Log activity + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . + ' - Periode ' . $pelaporan->periode . ' - Nama IPAL ' . $namaIpal; + + Log::info('LOG_DELETE', ['message' => $aktivitas, 'module' => 'pelaporan']); + + $response = ['message' => 'Data IPAL berhasil dihapus', 'status' => 'success']; + return response()->json($response); + } else { + $dataIpal = Ipal::getOneBy(['id' => $idMcIpal]); + + $data = [ + 'idmcipal' => $idMcIpal, + 'nomor' => $dataIpal->nomor, + 'nama' => $dataIpal->nama + ]; + + return view('pelaporan.ipal.delete_ipal', $data); + } + } + + /** + * Edit persyaratan teknis. + * + * @param Request $request + * @param int $idMcIpal + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function syaratTeknis(Request $request, $idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $idmcpelaporan = $ipal->idmcpelaporan; + $pelaporan = Pelaporan::findOrFail($idmcpelaporan); + + $data = [ + 'nama_ipal' => $ipal->nama, + 'idmcipal' => $idMcIpal + ]; + + if ($request->has('action')) { + $dataHasil = $request->input('hasil'); + + if ($dataHasil) { + foreach ($dataHasil as $refkomponen => $refhasil) { + $nilai = Ipal::getNilaiByIdRefHasil($refhasil); + + $filter = [ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $refkomponen, + 'idmcipal' => $idMcIpal + ]; + + $dataUpdate = [ + 'idrefhasil' => $refhasil, + 'nilai' => $nilai + ]; + + Ipal::updateNilaiSyaratTeknis($filter, $dataUpdate); + } + + $this->_updateRerataSyaratTeknis($idmcpelaporan); + $this->_updateNilaiSkl($idmcpelaporan); + } + + $response = ['message' => 'Persyaratan Teknis berhasil Disimpan', 'status' => 'success']; + return response()->json($response); + } else { + $idrefpelaporan = 2; + + $dataTable = Komponen::getDataRef($idrefpelaporan); + unset($dataTable['data'][0]); + unset($dataTable['data'][3]); + + $daftarKomponen = []; + foreach ($dataTable['data'] as $key => $c) { + foreach ($c['komponen'] as $kex => $x) { + $daftarKomponen[] = $kex; + } + } + + $allNilaiKomponen = []; + foreach ($daftarKomponen as $komponen) { + $idkomponen = Ipal::getIdRefKomponen($komponen); + $filterKomponen = [ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $idkomponen, + 'idmcipal' => $idMcIpal + ]; + + $nilaiKomponen = Ipal::getNilaiKomponen($filterKomponen); + $allNilaiKomponen[$komponen] = $nilaiKomponen; + } + + $data['nilai_komponen'] = $allNilaiKomponen; + $data['rowspan_1'] = $dataTable['total_rows'] + 1; + $data['data_table'] = $dataTable['data']; + $data['idmcpelaporan'] = $idmcpelaporan; + $data['idrefpelaporan'] = $idrefpelaporan; + + return view('pelaporan.ipal.syarat_teknis', $data); + } + } + + /** + * Add data pendukung. + * + * @param Request $request + * @param int $idMcIpal + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function addDataPendukung(Request $request, $idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + if ($request->has('action')) { + $validator = Validator::make($request->all(), [ + 'nomor' => 'required|string', + 'lintang' => 'required|string', + 'bujur' => 'required|string' + ]); + + if ($validator->passes()) { + $data = [ + 'nomor' => $request->input('nomor'), + 'izin_terbit' => $request->filled('izin_terbit') ? date('Y-m-d', strtotime($request->input('izin_terbit'))) : '0000-00-00', + 'izin_habis' => $request->filled('izin_habis') ? date('Y-m-d', strtotime($request->input('izin_habis'))) : '0000-00-00', + 'kapasitas' => $request->input('kapasitas'), + 'sumber' => $request->input('sumber'), + 'teknologi' => $request->input('teknologi'), + 'badanair' => $request->input('badanair'), + 'debit_maksimum' => $request->input('debitmax') == '' ? null : $request->input('debitmax'), + 'lintang' => $request->input('lintang') == '' ? null : $request->input('lintang'), + 'bujur' => $request->input('bujur') == '' ? null : $request->input('bujur') + ]; + + $pathLampiran = ''; + if ($request->hasFile('lampiran')) { + $pathLampiran = $this->_uploadFile($idMcIpal, $request->file('lampiran')); + + if ($pathLampiran != 'max filesize exceeded') { + $data['lampiran'] = $pathLampiran; + } + } + + Ipal::editMcIpal($idMcIpal, $data); + + if ($request->has('ref_save')) { + $idRefIpal = Ipal::getOneBy(['id' => $idMcIpal])->idrefipal; + Ipal::editRefIpal($idRefIpal, $data); + } + + // Log activity + $idmcpelaporan = Ipal::getOneBy(['id' => $idMcIpal])->idmcpelaporan; + $pelaporan = Pelaporan::findOrFail($idmcpelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $namaIpal = Ipal::getOneBy(['id' => $idMcIpal])->nama; + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . + ' - Periode ' . $pelaporan->periode . ' - Data Pendukung IPAL ' . $namaIpal; + + Log::info('LOG_EDIT', ['message' => $aktivitas, 'module' => 'pelaporan']); + + if ($pathLampiran == 'max filesize exceeded') { + $response = ['message' => 'Ukuran file lampiran melebihi 20 MB. Lampiran tidak tersimpan.', 'status' => 'error']; + } else { + $response = ['message' => 'Berhasil menambah data pendukung', 'status' => 'success']; + } + + return response()->json($response); + } else { + return response()->json([ + 'error' => [ + 'type' => 'validation', + 'messages' => $validator->errors() + ] + ]); + } + } else { + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $data = [ + 'nama_lampiran' => '', + 'data_ipal' => $ipal, + 'idmcipal' => $idMcIpal + ]; + + if ($ipal) { + $lampiranPath = $ipal->lampiran; + + if ($lampiranPath && File::exists(public_path($lampiranPath))) { + $listLampiranPath = explode('/', $lampiranPath); + $namaLampiran = end($listLampiranPath); + $data['nama_lampiran'] = $namaLampiran; + $data['url_lampiran'] = url($lampiranPath); + $data['ukuran_lampiran'] = $this->_formatBytes(File::size(public_path($lampiranPath))); + } + } + + return view('pelaporan.ipal.add_data_pendukung', $data); + } + } + + /** + * Delete lampiran data pendukung. + * + * @param Request $request + * @param int $idMcIpal + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function deleteLampiranDataPendukung(Request $request, $idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + $data['idmcipal'] = $idMcIpal; + + if ($request->has('action')) { + $dataIpal = Ipal::getOneBy(['id' => $idMcIpal]); + + Ipal::editMcIpal($idMcIpal, ['lampiran' => '']); + + if ($request->has('ref_delete')) { + $idRefIpal = Ipal::getOneBy(['id' => $idMcIpal])->idrefipal; + Ipal::editRefIpal($idRefIpal, ['lampiran' => '']); + } + + $response = ['message' => 'Lampiran data pendukung berhasil dihapus', 'status' => 'success']; + return response()->json($response); + } else { + return view('pelaporan.ipal.delete_lampiran_data_pendukung', $data); + } + } + + /** + * Show hasil uji form. + * + * @param int $idMcIpal + * @return \Illuminate\Http\Response + */ + public function hasilUji($idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($ipal->idmcpelaporan); + + $data = [ + 'idmcipal' => $idMcIpal, + 'nama_ipal' => $ipal->nama + ]; + + $listParam = IpalParameter::getData($idMcIpal); + + $nilaiHasilUji = []; + $bebanEmisi = []; + + foreach ($listParam as $row) { + $nilai = Ipal::getNilaiHasilUji($pelaporan->idrefperusahaan, $pelaporan->tahun, $row->idrefipal_parameter); + $hasilUji = []; + $bebanEmisiParameter = []; + + if ($row->bakumutu_nilai2) { + $bakumutu = $row->bakumutu_nilai1 . ' - ' . $row->bakumutu_nilai2; + } else { + $bakumutu = $row->bakumutu_nilai1; + } + + $hasilUji = []; + $hasilUji['bakumutu'] = $bakumutu; + + foreach ($nilai as $item) { + $hasilUji[$item->bulan] = $item->nilai; + $bebanEmisiParameter[$item->bulan] = $item->bebanemisi; + } + + $nilaiHasilUji[$row->id] = $hasilUji; + $bebanEmisi[$row->id] = $bebanEmisiParameter; + } + + $lampiranExists = []; + $debit = []; + + for ($i = 1; $i <= 12; $i++) { + $allLampiran = Ipal::getLampiranHasilUji([ + 'b.idrefipal' => $ipal->idrefipal, + 'a.idrefperusahaan' => $pelaporan->idrefperusahaan, + 'a.bulan' => $this->_mcMonth($i), + 'a.tahun' => $pelaporan->tahun + ]); + + $lampiranExists[$i-1] = false; + + if ($allLampiran) { + foreach ($allLampiran as $lampiran) { + if (File::exists($lampiran->dokumen)) { + $lampiranExists[$i-1] = true; + break; + } + } + } + + $debit[$i] = Ipal::getDebitBy([ + 'b.idrefipal' => $ipal->idrefipal, + 'a.idrefperusahaan' => $pelaporan->idrefperusahaan, + 'a.bulan' => $this->_mcMonth($i), + 'a.tahun' => $pelaporan->tahun + ]); + } + + $data['periode'] = $pelaporan->idrefperiodepelaporan; + $data['tahun'] = $pelaporan->tahun; + $data['params'] = $listParam; + $data['hasiluji'] = $nilaiHasilUji; + $data['bebanemisi'] = $bebanEmisi; + $data['lampiran'] = $lampiranExists; + $data['debit'] = $debit; + $data['debitmax'] = $ipal->debit_maksimum ? $ipal->debit_maksimum : 0; + + $hasilUjiEmpty = true; + if ($ipal && $ipal->lintang && $ipal->bujur) { + $hasilUjiEmpty = false; + } + + $data['hasil_uji_empty'] = $hasilUjiEmpty; + + return view('pelaporan.ipal.hasil_uji', $data); + } + + /** + * Save hasil uji. + * + * @param Request $request + * @param int $idMcIpal + * @return \Illuminate\Http\JsonResponse + */ + public function saveHasilUji(Request $request, $idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $periode = Pelaporan::findOrFail($ipal->idmcpelaporan)->idrefperiodepelaporan; + + $params = Ipal::getNamaParam($idMcIpal); + + $bulanAwal = (($periode - 1) * 3) + 1; + + $nilaiParam = $request->input('param'); + $debit = $request->input('debit'); + $nilaiExist = false; + + foreach ($params as $row) { + for ($i = 0; $i < 3; $i++) { + $bulan = $bulanAwal + $i; + + $nilai = null; + if (isset($nilaiParam[$row->id][$bulan]) && $nilaiParam[$row->id][$bulan] != '') { + $nilai = $nilaiParam[$row->id][$bulan]; + $nilaiExist = true; + } + + $bebanEmisi = null; + if ($nilai !== null && is_numeric($nilai) && isset($debit[$bulan]) && $debit[$bulan] && $row->batasemisi !== null) { + $bebanEmisi = ($debit[$bulan] * $nilai) / 1000; + } + + $data = [ + 'nilai' => $nilai, + 'debit' => (isset($debit[$bulan]) && $debit[$bulan] != '') ? $debit[$bulan] : null, + 'bebanemisi' => $bebanEmisi + ]; + + Ipal::updateHasilUji($row->id, $this->_mcMonth($bulan), $data); + } + } + + $this->_updateNilaiA6($ipal->idmcpelaporan); + $this->_updateNilaiA7($ipal->idmcpelaporan); + $this->_updateNilaiSpl($ipal->idmcpelaporan); + + if (!$this->_cekIpalKomunal($ipal->idmcpelaporan)) { + $this->_updateNilaiSkl($ipal->idmcpelaporan); + } + + // Update mcverifikasi table + if ($nilaiExist) { + $filter = [ + 'idmcpelaporan' => $ipal->idmcpelaporan, + 'idrefpelaporan' => 2 + ]; + + $dataUpdate = [ + 'verifikasi' => 1, + 'tanggal' => now()->format('Y-m-d H:i:s'), + 'oleh' => Auth::id() + ]; + + Pelaporan::updateStatusVerifikasi($filter, $dataUpdate); + } + + // Log activity + $idmcpelaporan = Ipal::getOneBy(['id' => $idMcIpal])->idmcpelaporan; + $pelaporan = Pelaporan::findOrFail($idmcpelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $namaIpal = $ipal->nama; + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . + ' - Periode ' . $pelaporan->periode . ' - Nama IPAL ' . $namaIpal . ' - Data Hasil Uji Lab'; + + Log::info('LOG_EDIT', ['message' => $aktivitas, 'module' => 'pelaporan']); + + $response = ['message' => 'Data Hasil Uji Berhasil Disimpan', 'status' => 'success']; + return response()->json($response); + } + + /** + * Check lampiran hasil uji. + * + * @param int $idMcIpal + * @param int $bulan + * @return \Illuminate\Http\JsonResponse + */ + public function cekLampiranHasilUji($idMcIpal, $bulan) + { + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($ipal->idmcpelaporan); + $idrefperusahaan = $pelaporan->idrefperusahaan; + + $allLampiran = Ipal::getLampiranHasilUji([ + 'a.idmcipal' => $idMcIpal, + 'a.idrefperusahaan' => $idrefperusahaan, + 'a.bulan' => $this->_mcMonth($bulan) + ]); + + $response = ['lampiran' => false]; + + if ($allLampiran) { + foreach ($allLampiran as $lampiran) { + if (File::exists($lampiran->dokumen)) { + $response['lampiran'] = true; + break; + } + } + } + + return response()->json($response); + } + + /** + * Synchronize IPAL data. + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function sinkronisasiIpal(Request $request) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + $idmcpelaporan = $request->input('id'); + + $allIpal = Ipal::getData($idmcpelaporan); + $pelaporan = Pelaporan::findOrFail($idmcpelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $allRefIpal = Ipal::getRefIpal($pelaporan->idrefperusahaan); + + // Delete all mcipal + $notAllowedChar = [' ', '.', '/', '-', ',', ':']; + $noInduk = $perusahaan->nomorinduk; + $tahun = $pelaporan->tahun; + $periode = strtolower(str_replace($notAllowedChar, '_', $pelaporan->periode)); + $bulanAwal = (($pelaporan->idrefperiodepelaporan - 1) * 3) + 1; + + foreach ($allIpal as $ipal) { + $idmcipal = $ipal->id; + + // Delete ipal parameter, nilai hasiluji dan lampiran hasil uji + IpalParameter::deleteMcIpalParam(['idmcipal' => $idmcipal]); + Ipal::deleteHasilUji(['idmcipal' => $idmcipal]); + Ipal::deleteLampiranHasilUji(['idmcipal' => $idmcipal]); + + // Delete nilai komponen-komponen syarat teknis + Ipal::deleteNilaiKomponen(['idmcipal' => $idmcipal]); + + // Delete lampiran komponen-komponen syarat teknis + Lampiran::deleteFile(['idmcipal' => $idmcipal]); + + // Delete lampiran files + $namaIpal = Ipal::getOneBy(['id' => $idmcipal])->nama; + $urlLampiran = 'data_perusahaan/' . $noInduk . '/lampiran' . '/' . 'al' . '/' . $tahun . '_' . $periode . '/' . str_replace($notAllowedChar, '_', $namaIpal) . '/'; + + $this->_recursiveRmdir(storage_path('app/public/' . $urlLampiran)); + + Ipal::deleteMcIpal($idmcipal); + } + + // Add mcipal from refipal + $allRefIpal = Ipal::getRefIpal($pelaporan->idrefperusahaan); + foreach ($allRefIpal as $refipal) { + // Add ipal + $insertData = [ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefipal' => $refipal->id, + 'nomor' => $refipal->nomor, + 'nama' => $refipal->nama, + 'lampiran' => $refipal->lampiran, + 'izin_terbit' => $refipal->izin_terbit, + 'izin_habis' => $refipal->izin_habis, + 'sumber' => $refipal->sumber, + 'kapasitas' => $refipal->kapasitas, + 'teknologi' => $refipal->teknologi, + 'badanair' => $refipal->badanair + ]; + + $idmcipal = Ipal::insertMcIpal($insertData); + + // Add parameter ipal + $refipalParam = IpalParameter::getRefIpalParam($refipal->id); + foreach ($refipalParam as $row) { + $dataMcIpalParam = [ + 'idmcipal' => $idmcipal, + 'idrefipal_parameter' => $row->id, + 'nama' => $row->nama, + 'satuan' => $row->satuan, + 'bakumutu_jenis' => $row->bakumutu_jenis, + 'bakumutu_nilai1' => $row->bakumutu_nilai1, + 'bakumutu_nilai2' => $row->bakumutu_nilai2, + 'batasemisi' => $row->batasemisi + ]; + + $idmcipalParam = IpalParameter::insertMcIpalParam($dataMcIpalParam); + + // Insert data to mchasiluji_al + $dataHasilUji = []; + for ($i = 0; $i < 3; $i++) { + $dataHasilUji[] = [ + 'idmcipal' => $idmcipal, + 'tahun' => $pelaporan->tahun, + 'idrefperusahaan' => $pelaporan->idrefperusahaan, + 'idmcipal_parameter' => $idmcipalParam, + 'bulan' => $this->_mcMonth($bulanAwal + $i) + ]; + } + + Ipal::insertHasilUji($dataHasilUji); + } + } + + $this->_updateRerataSyaratTeknis($idmcpelaporan); + $this->_updateNilaiA6($idmcpelaporan); + $this->_updateNilaiA7($idmcpelaporan); + $this->_updateNilaiSpl($idmcpelaporan); + + if (!$this->_cekIpalKomunal($idmcpelaporan)) { + $this->_updateNilaiSkl($idmcpelaporan); + } + + $response = ['message' => 'Sinkronisasi Berhasil', 'status' => 'success']; + return response()->json($response); + } + + /** + * Update nilai A6. + * + * @param int $idmcpelaporan + * @return void + */ + private function _updateNilaiA6($idmcpelaporan) + { + $pelaporan = Pelaporan::findOrFail($idmcpelaporan); + $allIpal = Ipal::getData($idmcpelaporan); + + $periode = $pelaporan->idrefperiodepelaporan; + $bulanAwal = (($periode - 1) * 3) + 1; + $jmlNilaiIpal = 0; + + foreach ($allIpal as $row) { + $jmlNilaiParam = 0; + for ($i = 0; $i < 3; $i++) { + $filter = [ + 'idmcipal' => $row->id, + 'bulan' => $this->_mcMonth($bulanAwal + $i), + 'nilai !=' => 'NULL' + ]; + + $hasilUji = Ipal::getHasilUjiBy($filter); + + if ($hasilUji) { + $jmlNilaiParam += 100; + } + } + + $nilaiIpal = $jmlNilaiParam / 3; + $jmlNilaiIpal += $nilaiIpal; + } + + $nilaiA6 = count($allIpal) ? $jmlNilaiIpal / count($allIpal) : 0; + $idrefkomponen = Ipal::getIdRefKomponen('A6'); + + $filter = [ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $idrefkomponen + ]; + + if (Ipal::getNilaiKomponen($filter)) { + $data = ['nilai' => $nilaiA6]; + Ipal::updateNilaiKomponen($filter, $data); + } else { + $data = [ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $idrefkomponen, + 'idrefhasil' => 0, + 'nilai' => $nilaiA6 + ]; + + Ipal::insertNilaiKomponen($data); + } + } + + /** + * Update nilai A7. + * + * @param int $idmcpelaporan + * @return void + */ + private function _updateNilaiA7($idmcpelaporan) + { + $nilaiA7 = Ipal::getNilaiA7($idmcpelaporan); + $idrefkomponen = Ipal::getIdRefKomponen('A7'); + + $filter = [ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $idrefkomponen + ]; + + if (Ipal::getNilaiKomponen($filter)) { + $data = ['nilai' => $nilaiA7]; + Ipal::updateNilaiKomponen($filter, $data); + } else { + $data = [ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $idrefkomponen, + 'idrefhasil' => 0, + 'nilai' => $nilaiA7 + ]; + + Ipal::insertNilaiKomponen($data); + } + } + + /** + * Update nilai SPL. + * + * @param int $idmcpelaporan + * @return void + */ + private function _updateNilaiSpl($idmcpelaporan) + { + $allIpal = Ipal::getData($idmcpelaporan); + $jmlParam = 0; + $memenuhiBakumutu = 0; + $memenuhiBatasEmisi = 0; + + foreach ($allIpal as $ipal) { + $params = IpalParameter::getData($ipal->id); + $jmlParam += count($params); + + $allHasilUji = Ipal::getAllHasilUjiBy([ + 'idmcipal' => $ipal->id, + 'nilai !=' => null + ]); + + // Check all hasil uji against bakumutu + foreach ($allHasilUji as $hasilUji) { + $param = IpalParameter::getOneBy(['id' => $hasilUji->idmcipal_parameter]); + + if ($hasilUji->nilai == '*') { + $memenuhiBakumutu++; + } elseif ($hasilUji->debit != null && $param->bakumutu_jenis != 'Positif/Negatif' && $param->batasemisi) { + if ($hasilUji->bebanemisi <= $param->batasemisi) { + $memenuhiBatasEmisi++; + } + } else { + if ($param->bakumutu_jenis == 'Angka Tunggal') { + if ($hasilUji->nilai <= $param->bakumutu_nilai1) { + $memenuhiBakumutu++; + } + } elseif ($param->bakumutu_jenis == 'Rentang Angka') { + if ($hasilUji->nilai >= $param->bakumutu_nilai1 && $hasilUji->nilai <= $param->bakumutu_nilai2) { + $memenuhiBakumutu++; + } + } elseif ($param->bakumutu_jenis == 'Positif/Negatif') { + if (strtolower($hasilUji->nilai) == strtolower($param->bakumutu_nilai1)) { + $memenuhiBakumutu++; + } + } + } + } + } + + $totalParam = $jmlParam * 3; + $melebihiBakumutuEmisi = $totalParam - $memenuhiBakumutu - $memenuhiBatasEmisi; + $nilaiSpl = $totalParam ? 100 - (($melebihiBakumutuEmisi / $totalParam) * 100) : 0; + + if (Ipal::getNilaiSpl($idmcpelaporan)) { + $data = [ + 'diuji' => $totalParam, + 'melebihi' => $melebihiBakumutuEmisi, + 'nilaispl' => $nilaiSpl + ]; + + Ipal::updateNilaiSpl($idmcpelaporan, $data); + } else { + $data = [ + 'idmcpelaporan' => $idmcpelaporan, + 'diuji' => $totalParam, + 'melebihi' => $melebihiBakumutuEmisi, + 'nilaispl' => $nilaiSpl + ]; + + Ipal::insertNilaiSpl($data); + } + + Pelaporan::updateNilaiSpl($idmcpelaporan, 2, $nilaiSpl); + Pelaporan::getAvgSpl($idmcpelaporan); + } + + /** + * Check if IPAL is komunal. + * + * @param int $idmcpelaporan + * @return bool + */ + private function _cekIpalKomunal($idmcpelaporan) + { + $ipalKomunal = Spl_AL::getStatusMcKomunal($idmcpelaporan); + + if ($ipalKomunal && $ipalKomunal->tersambung == 'Iya') { + $sk = Lampiran::getKomponenByKode('SK'); + + if ($sk) { + $lampiranSk = Spl_AL::cekLampiranSk($idmcpelaporan, $sk->id); + + if ($lampiranSk) { + return true; + } + } + } + + return false; + } + + /** + * Update nilai SKL. + * + * @param int $idmcpelaporan + * @return void + */ + private function _updateNilaiSkl($idmcpelaporan) + { + $totalNilai1 = 0; + $totalNilai2 = 0; + $totalNilai3 = 0; + $kelompok1 = ['A1', 'A2', 'A3', 'A4']; + $kelompok2 = ['A5']; + $kelompok3 = ['A6', 'A7', 'A8', 'A9', 'A10']; + + for ($i = 1; $i <= 10; $i++) { + $komponen = 'A' . $i; + $idrefkomponen = Ipal::getIdRefKomponen($komponen); + + $nilaiKomponen = Ipal::getNilaiKomponen([ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $idrefkomponen, + 'idmcipal' => null + ]); + + if ($nilaiKomponen) { + if (in_array($komponen, $kelompok1)) { + $totalNilai1 += $nilaiKomponen->nilai; + } elseif (in_array($komponen, $kelompok2)) { + $totalNilai2 += $nilaiKomponen->nilai; + } else { + $totalNilai3 += $nilaiKomponen->nilai; + } + } + } + + $skl = (15 * ($totalNilai1 / count($kelompok1)) / 100) + + (15 * ($totalNilai2 / count($kelompok2)) / 100) + + (70 * ($totalNilai3 / count($kelompok3)) / 100); + + Pelaporan::updateNilaiSkl($idmcpelaporan, 2, $skl); + Pelaporan::updateAvgSkl($idmcpelaporan); + } + + /** + * Update rerata syarat teknis. + * + * @param int $idmcpelaporan + * @return void + */ + private function _updateRerataSyaratTeknis($idmcpelaporan) + { + $daftarKomponen = ['A1', 'A2', 'A3', 'A4', 'A5']; + + foreach ($daftarKomponen as $komponen) { + $idkomponen = Ipal::getIdRefKomponen($komponen); + + // Calculate average for each component + $nilaiKomponen = Ipal::getNilaiSyaratTeknis([ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $idkomponen, + 'idmcipal !=' => null + ]); + + $jmlNilai = 0; + foreach ($nilaiKomponen as $row) { + $jmlNilai += $row->nilai; + } + + $jmlIpal = count(Ipal::getData($idmcpelaporan)); + $rerataNilai = $jmlIpal ? $jmlNilai / $jmlIpal : 0; + + // Update average for each component + $filter = [ + 'idmcpelaporan' => $idmcpelaporan, + 'idrefkomponen' => $idkomponen, + 'idmcipal' => null + ]; + + $dataUpdate = [ + 'idrefhasil' => 0, + 'nilai' => $rerataNilai + ]; + + Ipal::updateNilaiSyaratTeknis($filter, $dataUpdate); + } + } + + /** + * Upload file. + * + * @param int $idMcIpal + * @param \Illuminate\Http\UploadedFile $file + * @return string + */ + private function _uploadFile($idMcIpal, $file) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + $dataIpal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($dataIpal->idmcpelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + + $notAllowedChar = [' ', '.', '/', '-', ',', ':']; + + $noInduk = $perusahaan->nomorinduk; + $tahun = $pelaporan->tahun; + $periode = strtolower(str_replace($notAllowedChar, '_', $pelaporan->periode)); + $noIpal = $dataIpal->nomor; + + $dirUpload = 'data_perusahaan/' . $noInduk . '/lampiran' . '/' . 'al' . '/' . 'A6' . '/' . $tahun . '_' . $periode . '/data_pendukung' . '/' . $noIpal . '/'; + + // Create directory if it doesn't exist + if (!Storage::disk('public')->exists($dirUpload)) { + Storage::disk('public')->makeDirectory($dirUpload, 0777, true); + } + + $filesize = $file->getSize(); + + // If filesize > 20 MB + if ($filesize / pow(1024, 2) > 20) { + return 'max filesize exceeded'; + } + + $name = $file->getClientOriginalName(); + $ext = $file->getClientOriginalExtension(); + $baseName = pathinfo($name, PATHINFO_FILENAME); + $newName = $baseName . '_' . date('Ymd_His') . '.' . $ext; + + // Delete old file if exists + if ($dataIpal->lampiran && Storage::disk('public')->exists($dataIpal->lampiran)) { + Storage::disk('public')->delete($dataIpal->lampiran); + } + + // Store new file + $path = $file->storeAs($dirUpload, $newName, 'public'); + + return $path; + } + + /** + * Recursively remove directory. + * + * @param string $dir + * @return void + */ + private function _recursiveRmdir($dir) + { + if (is_dir($dir)) { + $objects = scandir($dir); + foreach ($objects as $object) { + if ($object != "." && $object != "..") { + if (filetype($dir . "/" . $object) == "dir") { + $this->_recursiveRmdir($dir . "/" . $object); + } else { + unlink($dir . "/" . $object); + } + } + } + reset($objects); + rmdir($dir); + } + } + + /** + * Format bytes to human readable format. + * + * @param int $bytes + * @param int $precision + * @return string + */ + private function _formatBytes($bytes, $precision = 2) + { + $units = ['B', 'KB', 'MB', 'GB', 'TB']; + $bytes = max($bytes, 0); + $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); + $pow = min($pow, count($units) - 1); + + $bytes /= pow(1024, $pow); + + return round($bytes, $precision) . ' ' . $units[$pow]; + } + + /** + * Convert month number to name. + * + * @param int $monthNum + * @return string + */ + private function _mcMonth($monthNum) + { + $months = [ + 1 => 'January', + 2 => 'February', + 3 => 'March', + 4 => 'April', + 5 => 'May', + 6 => 'June', + 7 => 'July', + 8 => 'August', + 9 => 'September', + 10 => 'October', + 11 => 'November', + 12 => 'December' + ]; + + return $months[$monthNum] ?? ''; + } +} diff --git a/app/Http/Controllers/Pelaporan/AL/IpalParameterController.php b/app/Http/Controllers/Pelaporan/AL/IpalParameterController.php new file mode 100644 index 0000000..8351c7c --- /dev/null +++ b/app/Http/Controllers/Pelaporan/AL/IpalParameterController.php @@ -0,0 +1,746 @@ + + */ +class IpalParameterController extends Controller +{ + /** + * Display parameter table + * + * @param int $idMcIpal + * @return \Illuminate\Http\Response + */ + public function table($idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + // Get IPAL data + $ipal = Ipal::getOneBy(['IpalId' => $idMcIpal]); + + $data = [ + 'IpalId' => $idMcIpal, + 'NamaIpal' => $ipal->nama + ]; + + // If mcipal_parameter is empty, fill it based on refipal_parameter + $parameter = IpalParameter::getOneBy(['IpalId' => $idMcIpal]); + + if (!$parameter) { + $refIpalParam = IpalParameter::getRefIpalParam($ipal->idrefipal); + + if ($refIpalParam) { + foreach ($refIpalParam as $row) { + $dataMcIpalParam = [ + 'IpalId' => $idMcIpal, + 'RefIpalParameterId' => $row->id, + 'Nama' => $row->nama, + 'Satuan' => $row->satuan, + 'BakuMutuJenis' => $row->bakumutu_jenis, + 'BakuMutuNilai1' => $row->bakumutu_nilai1, + 'BakuMutuNilai2' => $row->bakumutu_nilai2, + 'BatasEmisi' => $row->batasemisi + ]; + + $idMcIpalParam = IpalParameter::insertMcIpalParam($dataMcIpalParam); + + // Insert data to mchasiluji_al + $this->_insertHasilUji($idMcIpal, $idMcIpalParam); + } + + $this->_updateNilaiA6($ipal->idmcpelaporan); + $this->_updateNilaiA7($ipal->idmcpelaporan); + $this->_updateNilaiSpl($ipal->idmcpelaporan); + + if (!$this->_cekIpalKomunal($ipal->idmcpelaporan)) { + $this->_updateNilaiSkl($ipal->idmcpelaporan); + } + } + } + + return view('pelaporan.ipal.parameter.index', $data); + } + + /** + * Function to get data for datatable + * + * @param int $idMcIpal + * @return \Illuminate\Http\JsonResponse + */ + public function getData($idMcIpal) + { + $dataParameter = IpalParameter::getData($idMcIpal); + + $data = []; + $no = 1; + + foreach ($dataParameter as $row) { + if ($row->bakumutu_nilai2) { + $bakumutu = $row->bakumutu_nilai1 . ' - ' . $row->bakumutu_nilai2; + } else { + $bakumutu = $row->bakumutu_nilai1; + } + + $data[] = [ + $no, + $row->nama, + $row->satuan, + $bakumutu, + ($row->batasemisi != NULL ? floatval($row->batasemisi) : ''), + $row->id + ]; + + $no++; + } + + $response = [ + 'data' => $data, + 'recordsTotal' => count($data) + ]; + + return response()->json($response); + } + + /** + * Function to add new parameter + * + * @param int $idMcIpal + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function add(Request $request, $idMcIpal) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + if ($request->has('action')) { + $response = $this->_insertUpdate($idMcIpal, 'insert', $request); + + $ipal = Ipal::getOneBy(['IpalId' => $idMcIpal]); + + $this->_updateNilaiA6($ipal->idmcpelaporan); + $this->_updateNilaiA7($ipal->idmcpelaporan); + $this->_updateNilaiSpl($ipal->idmcpelaporan); + + if (!$this->_cekIpalKomunal($ipal->idmcpelaporan)) { + $this->_updateNilaiSkl($ipal->idmcpelaporan); + } + + return response()->json($response); + } + + $data['IpalId'] = $idMcIpal; + return view('pelaporan.ipal.parameter.add', $data); + } + + /** + * Function to edit parameter + * + * @param Request $request + * @param int $idMcIpalParam + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function edit(Request $request, $idMcIpalParam) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + if ($request->has('action')) { + $response = $this->_insertUpdate($idMcIpalParam, 'update', $request); + return response()->json($response); + } else { + $data['param'] = IpalParameter::getOneBy(['id' => $idMcIpalParam]); + return view('pelaporan.ipal.parameter.edit', $data); + } + } + + /** + * Function to delete parameter + * + * @param Request $request + * @param int $idMcIpalParam + * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse + */ + public function delete(Request $request, $idMcIpalParam) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + if ($request->has('action')) { + $idRefIpalParam = IpalParameter::getOneBy(['id' => $idMcIpalParam])->idrefipal_parameter; + + // Data for logging + $ipalParameter = IpalParameter::getOneBy(['id' => $idMcIpalParam]); + $idMcIpal = $ipalParameter->idmcipal; + $idMcPelaporan = Ipal::getOneBy(['id' => $idMcIpal])->idmcpelaporan; + $pelaporan = Pelaporan::findOrFail($idMcPelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $namaIpal = Ipal::getOneBy(['id' => $idMcIpal])->nama; + $namaIpalParameter = $ipalParameter->nama; + + // Delete ipal parameter and hasiluji from database + IpalParameter::deleteMcIpalParam(['id' => $idMcIpalParam]); + Ipal::deleteHasilUji(['idmcipal_parameter' => $idMcIpalParam]); + + if ($request->input('ref_delete')) { + IpalParameter::disableRefIpalParam($idRefIpalParam); + } + + $this->_updateNilaiA6($idMcPelaporan); + $this->_updateNilaiA7($idMcPelaporan); + $this->_updateNilaiSpl($idMcPelaporan); + + if (!$this->_cekIpalKomunal($idMcPelaporan)) { + $this->_updateNilaiSkl($idMcPelaporan); + } + + // Log activity + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . ' - Periode ' . + $pelaporan->periode . ' - Nama IPAL ' . $namaIpal . ' - Parameter Uji Lab ' . + $namaIpalParameter; + Log::info('LOG_DELETE', ['message' => $aktivitas, 'module' => 'pelaporan']); + + $response = ['message' => 'Parameter Berhasil Dihapus', 'status' => 'success']; + return response()->json($response); + } else { + $param = IpalParameter::getOneBy(['id' => $idMcIpalParam]); + $ipal = Ipal::getOneBy(['id' => $param->idmcipal]); + + $data = [ + 'idmcipal_param' => $idMcIpalParam, + 'nomor_ipal' => $ipal->nomor, + 'nama_ipal' => $ipal->nama, + 'nama_param' => $param->nama + ]; + + return view('pelaporan.ipal.parameter.delete', $data); + } + } + + /** + * Function to insert into or update table mcipal_parameter and refipal_parameter + * + * @param int $id if insert then $id = $idmcipal if update then $id = $idmcipal_parameter + * @param string $action insert or update + * @param Request $request + * @return array $response + */ + private function _insertUpdate($id, $action, Request $request) + { + $post = $request->all(); + + if ($post['nama'] !== "" && $post['satuan'] !== "") { + if ($post['bakumutu'] == 1) { + $bakumutuJenis = 'Angka Tunggal'; + $bakumutuNilai1 = $post['angka_tunggal']; + $bakumutuNilai2 = ''; + + if (!is_numeric($bakumutuNilai1)) { + $response = ['message' => 'Data belum lengkap', 'status' => 'error']; + return $response; + } + + if (!(isset($post['batasemisi']) && $post['batasemisi'])) { + $response = ['message' => 'Beban pencemaran maksimum wajib diisi', 'status' => 'error']; + return $response; + } + } else if ($post['bakumutu'] == 2) { + $bakumutuJenis = 'Rentang Angka'; + $bakumutuNilai1 = $post['nilai1']; + $bakumutuNilai2 = $post['nilai2']; + + if (!(is_numeric($bakumutuNilai1) && is_numeric($bakumutuNilai2))) { + $response = ['message' => 'Data belum lengkap', 'status' => 'error']; + return $response; + } + + if (!(isset($post['batasemisi']) && $post['batasemisi'])) { + $response = ['message' => 'Beban pencemaran maksimum wajib diisi', 'status' => 'error']; + return $response; + } + } else if ($post['bakumutu'] == 3) { + $bakumutuJenis = 'Positif/Negatif'; + $bakumutuNilai1 = $post['bakumutu_3']; + $bakumutuNilai2 = ''; + + if (!$bakumutuNilai1) { + $response = ['message' => 'Data belum lengkap', 'status' => 'error']; + return $response; + } + } else if ($post['bakumutu'] == 4) { + $bakumutuJenis = 'Tanpa Baku Mutu'; + $bakumutuNilai1 = '-'; + $bakumutuNilai2 = ''; + } + + $dataRefIpalParam = [ + 'nama' => $post['nama'], + 'satuan' => $post['satuan'], + 'bakumutu_jenis' => $bakumutuJenis, + 'bakumutu_nilai1' => $bakumutuNilai1, + 'bakumutu_nilai2' => $bakumutuNilai2, + 'batasemisi' => (($post['bakumutu'] == 3 || $post['batasemisi'] === '') ? NULL : $post['batasemisi']) + ]; + + $dataMcIpalParam = $dataRefIpalParam; + + if ($action == 'insert') { + $idRefIpal = Ipal::getOneBy(['id' => $id])->idrefipal; + $dataRefIpalParam['idrefipal'] = $idRefIpal; + $dataRefIpalParam['del'] = 'n'; + + $idRefIpalParam = IpalParameter::insertRefIpalParam($dataRefIpalParam); + + $dataMcIpalParam['idmcipal'] = $id; + $dataMcIpalParam['idrefipal_parameter'] = $idRefIpalParam; + + $idMcIpalParam = IpalParameter::insertMcIpalParam($dataMcIpalParam); + + // Insert data to mchasiluji_al + $this->_insertHasilUji($id, $idMcIpalParam); + + // Log activity + $idMcPelaporan = Ipal::getOneBy(['id' => $id])->idmcpelaporan; + $pelaporan = Pelaporan::findOrFail($idMcPelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $namaIpal = Ipal::getOneBy(['id' => $id])->nama; + $namaIpalParameter = $dataMcIpalParam['nama']; + + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . ' - Periode ' . + $pelaporan->periode . ' - Nama IPAL ' . $namaIpal . ' - Parameter Uji Lab ' . + $namaIpalParameter; + Log::info('LOG_CREATE', ['message' => $aktivitas, 'module' => 'pelaporan']); + } elseif ($action == 'update') { + IpalParameter::updateMcIpalParam($id, $dataMcIpalParam); + + if (isset($post['ref_save'])) { + $idRefIpalParam = IpalParameter::getOneBy(['id' => $id])->idrefipal_parameter; + IpalParameter::updateRefIpalParam($idRefIpalParam, $dataRefIpalParam); + } + + // Log activity + $ipalParameter = IpalParameter::getOneBy(['id' => $id]); + $idMcIpal = $ipalParameter->idmcipal; + $idMcPelaporan = Ipal::getOneBy(['id' => $idMcIpal])->idmcpelaporan; + $pelaporan = Pelaporan::findOrFail($idMcPelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $namaIpal = Ipal::getOneBy(['id' => $idMcIpal])->nama; + $namaIpalParameter = $ipalParameter->nama; + + $aktivitas = 'Pelaporan AL - ' . $perusahaan->nama . ' - Tahun ' . $pelaporan->tahun . ' - Periode ' . + $pelaporan->periode . ' - Nama IPAL ' . $namaIpal . ' - Parameter Uji Lab ' . + $namaIpalParameter; + Log::info('LOG_EDIT', ['message' => $aktivitas, 'module' => 'pelaporan']); + } + + $response = ['message' => 'Parameter Berhasil Disimpan', 'status' => 'success']; + } else { + $response = ['message' => 'Data belum lengkap', 'status' => 'error']; + } + + return $response; + } + + /** + * Insert hasil uji for new parameter + * + * @param int $idMcIpal + * @param int $idMcIpalParam + * @return void + */ + private function _insertHasilUji($idMcIpal, $idMcIpalParam) + { + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($ipal->idmcpelaporan); + + $dataHasilUji = []; + $bulan = 0; + + if ($pelaporan->idrefperiodepelaporan == 1) { + $bulan = 1; + } elseif ($pelaporan->idrefperiodepelaporan == 2) { + $bulan = 4; + } elseif ($pelaporan->idrefperiodepelaporan == 3) { + $bulan = 7; + } elseif ($pelaporan->idrefperiodepelaporan == 4) { + $bulan = 10; + } + + for ($i = 0; $i < 3; $i++) { + $dataHasilUji[] = [ + 'idmcipal' => $idMcIpal, + 'tahun' => $pelaporan->tahun, + 'idrefperusahaan' => $pelaporan->idrefperusahaan, + 'idmcipal_parameter' => $idMcIpalParam, + 'bulan' => $this->_mcMonth($bulan) + ]; + $bulan++; + } + + Ipal::insertHasilUji($dataHasilUji); + } + + /** + * Update nilai A6 + * + * @param int $idMcPelaporan + * @return void + */ + private function _updateNilaiA6($idMcPelaporan) + { + $pelaporan = Pelaporan::findOrFail($idMcPelaporan); + $allIpal = Ipal::getData($idMcPelaporan); + + $periode = $pelaporan->idrefperiodepelaporan; + $bulanAwal = (($periode - 1) * 3) + 1; + $jmlNilaiIpal = 0; + + foreach ($allIpal as $row) { + $jmlNilaiParam = 0; + for ($i = 0; $i < 3; $i++) { + $filter = [ + 'idmcipal' => $row->id, + 'bulan' => $this->_mcMonth($bulanAwal + $i), + 'nilai !=' => 'NULL' + ]; + $hasilUji = Ipal::getHasilUjiBy($filter); + + if ($hasilUji) { + $jmlNilaiParam += 100; + } + } + $nilaiIpal = $jmlNilaiParam / 3; + $jmlNilaiIpal += $nilaiIpal; + } + + if (count($allIpal)) { + $nilaiA6 = $jmlNilaiIpal / count($allIpal); + } else { + $nilaiA6 = 0; + } + + $idRefKomponen = Ipal::getIdRefKomponen('A6'); + + $filter = [ + 'idmcpelaporan' => $idMcPelaporan, + 'idrefkomponen' => $idRefKomponen + ]; + + if (Ipal::getNilaiKomponen($filter)) { + $data = ['nilai' => $nilaiA6]; + Ipal::updateNilaiKomponen($filter, $data); + } else { + $data = [ + 'idmcpelaporan' => $idMcPelaporan, + 'idrefkomponen' => $idRefKomponen, + 'idrefhasil' => 0, + 'nilai' => $nilaiA6 + ]; + Ipal::insertNilaiKomponen($data); + } + } + + /** + * Update nilai A7 + * + * @param int $idMcPelaporan + * @return void + */ + private function _updateNilaiA7($idMcPelaporan) + { + $pelaporan = Pelaporan::findOrFail($idMcPelaporan); + $allIpal = Ipal::getData($idMcPelaporan); + + $periode = $pelaporan->idrefperiodepelaporan; + $bulanAwal = (($periode - 1) * 3) + 1; + $jmlNilaiIpal = 0; + + foreach ($allIpal as $row) { + $jmlNilaiParam = 0; + $params = IpalParameter::getData($row->id); + $tambahNilai = false; + + for ($i = 0; $i < 3; $i++) { + foreach ($params as $param) { + $filter = [ + 'idmcipal_parameter' => $param->id, + 'bulan' => $this->_mcMonth($bulanAwal + $i) + ]; + $hasilUji = Ipal::getHasilUjiBy($filter); + $tambahNilai = false; + + if ($hasilUji->nilai) { + if ($hasilUji->nilai == '*') { + $tambahNilai = true; + } elseif ($hasilUji->debit != NULL && $param->bakumutu_jenis != 'Positif/Negatif') { + if ($hasilUji->bebanemisi > $param->batasemisi) { + $tambahNilai = false; + break; + } else { + $tambahNilai = true; + } + } else { + if ($param->bakumutu_jenis == 'Angka Tunggal') { + if ($hasilUji->nilai > $param->bakumutu_nilai1) { + $tambahNilai = false; + break; + } + } elseif ($param->bakumutu_jenis == 'Rentang Angka') { + if ($hasilUji->nilai < $param->bakumutu_nilai1 || $hasilUji->nilai > $param->bakumutu_nilai2) { + $tambahNilai = false; + break; + } + } elseif ($param->bakumutu_jenis == 'Positif/Negatif') { + if (strtolower($hasilUji->nilai) != strtolower($param->bakumutu_nilai1)) { + $tambahNilai = false; + break; + } + } + + $tambahNilai = true; + } + } else { + $tambahNilai = false; + break; + } + } + + if ($tambahNilai) { + $jmlNilaiParam += 100; + } + } + $nilaiIpal = $jmlNilaiParam / 3; + $jmlNilaiIpal += $nilaiIpal; + } + + if (count($allIpal)) { + $nilaiA7 = $jmlNilaiIpal / count($allIpal); + } else { + $nilaiA7 = 0; + } + + $idRefKomponen = Ipal::getIdRefKomponen('A7'); + + $filter = [ + 'idmcpelaporan' => $idMcPelaporan, + 'idrefkomponen' => $idRefKomponen + ]; + + + if (Ipal::getNilaiKomponen($filter)) { + $data = ['nilai' => $nilaiA7]; + Ipal::updateNilaiKomponen($filter, $data); + } else { + $data = [ + 'idmcpelaporan' => $idMcPelaporan, + 'idrefkomponen' => $idRefKomponen, + 'idrefhasil' => 0, + 'nilai' => $nilaiA7 + ]; + + Ipal::insertNilaiKomponen($data); + } + } + + /** + * Update nilai SPL + * + * @param int $idMcPelaporan + * @return void + */ + private function _updateNilaiSpl($idMcPelaporan) + { + $allIpal = Ipal::getData($idMcPelaporan); + $jmlParam = 0; + $memenuhiBakumutu = 0; + $memenuhiBatasEmisi = 0; + + foreach ($allIpal as $ipal) { + $params = IpalParameter::getData($ipal->id); + $jmlParam += count($params); + + $allHasilUji = Ipal::getAllHasilUjiBy([ + 'idmcipal' => $ipal->id, + 'nilai !=' => NULL + ]); + + // Check all hasil uji against bakumutu + foreach ($allHasilUji as $hasilUji) { + $param = IpalParameter::getOneBy(['id' => $hasilUji->idmcipal_parameter]); + + if ($hasilUji->nilai == '*') { + $memenuhiBakumutu++; + } elseif ($hasilUji->debit != NULL && $param->bakumutu_jenis != 'Positif/Negatif') { + if ($hasilUji->bebanemisi <= $param->batasemisi) { + $memenuhiBatasEmisi++; + } + } else { + if ($param->bakumutu_jenis == 'Angka Tunggal') { + if ($hasilUji->nilai <= $param->bakumutu_nilai1) { + $memenuhiBakumutu++; + } + } elseif ($param->bakumutu_jenis == 'Rentang Angka') { + if ($hasilUji->nilai >= $param->bakumutu_nilai1 && $hasilUji->nilai <= $param->bakumutu_nilai2) { + $memenuhiBakumutu++; + } + } elseif ($param->bakumutu_jenis == 'Positif/Negatif') { + if (strtolower($hasilUji->nilai) == strtolower($param->bakumutu_nilai1)) { + $memenuhiBakumutu++; + } + } elseif ($param->bakumutu_jenis == 'Tanpa Baku Mutu') { + $memenuhiBakumutu++; + } + } + } + } + + $totalParam = $jmlParam * 3; + $melebihiBakumutuEmisi = $totalParam - $memenuhiBakumutu - $memenuhiBatasEmisi; + + if ($totalParam) { + $nilaiSpl = 100 - (($melebihiBakumutuEmisi / $totalParam) * 100); + } else { + $nilaiSpl = 0; + } + + if (Ipal::getNilaiSpl($idMcPelaporan)) { + $data = [ + 'diuji' => $totalParam, + 'melebihi' => $melebihiBakumutuEmisi, + 'nilaispl' => $nilaiSpl + ]; + Ipal::updateNilaiSpl($idMcPelaporan, $data); + } else { + $data = [ + 'idmcpelaporan' => $idMcPelaporan, + 'diuji' => $totalParam, + 'melebihi' => $melebihiBakumutuEmisi, + 'nilaispl' => $nilaiSpl + ]; + Ipal::insertNilaiSpl($data); + } + + Pelaporan::updateNilaiSpl($idMcPelaporan, 2, $nilaiSpl); + Pelaporan::getAvgSpl($idMcPelaporan); + } + + /** + * Check if IPAL is komunal + * + * @param int $idMcPelaporan + * @return bool + */ + private function _cekIpalKomunal($idMcPelaporan) + { + $ipalKomunal = Spl_AL::getStatusMcKomunal($idMcPelaporan); + + if ($ipalKomunal) { + if ($ipalKomunal->tersambung == 'Iya') { + $sk = Lampiran::getKomponenByKode('SK'); + if ($sk) { + $lampiranSk = Spl_AL::cekLampiranSk($idMcPelaporan, $sk->id); + if ($lampiranSk) { + return true; + } + } + } + } + + return false; + } + + /** + * Update nilai SKL + * + * @param int $idMcPelaporan + * @return void + */ + private function _updateNilaiSkl($idMcPelaporan) + { + $totalNilai1 = 0; + $totalNilai2 = 0; + $totalNilai3 = 0; + $kelompok1 = ['A1', 'A2', 'A3', 'A4']; + $kelompok2 = ['A5']; + $kelompok3 = ['A6', 'A7', 'A8', 'A9', 'A10']; + + for ($i = 1; $i <= 10; $i++) { + $komponen = 'A' . $i; + $idRefKomponen = Ipal::getIdRefKomponen($komponen); + + $nilaiKomponen = Ipal::getNilaiKomponen([ + 'idmcpelaporan' => $idMcPelaporan, + 'idrefkomponen' => $idRefKomponen, + 'idmcipal' => NULL + ]); + + if ($nilaiKomponen) { + if (in_array($komponen, $kelompok1)) { + $totalNilai1 += $nilaiKomponen->nilai; + } elseif (in_array($komponen, $kelompok2)) { + $totalNilai2 += $nilaiKomponen->nilai; + } else { + $totalNilai3 += $nilaiKomponen->nilai; + } + } + } + + $skl = (15 * ($totalNilai1 / count($kelompok1)) / 100) + + (15 * ($totalNilai2 / count($kelompok2)) / 100) + + (70 * ($totalNilai3 / count($kelompok3)) / 100); + + Pelaporan::updateNilaiSkl($idMcPelaporan, 2, $skl); + Pelaporan::updateAvgSkl($idMcPelaporan); + } + + /** + * Convert month number to name + * + * @param int $monthNum + * @return string + */ + private function _mcMonth($monthNum) + { + $months = [ + 1 => 'January', + 2 => 'February', + 3 => 'March', + 4 => 'April', + 5 => 'May', + 6 => 'June', + 7 => 'July', + 8 => 'August', + 9 => 'September', + 10 => 'October', + 11 => 'November', + 12 => 'December' + ]; + + return $months[$monthNum] ?? ''; + } +} diff --git a/app/Http/Controllers/Pelaporan/AL/LampiranHasilUjiController.php b/app/Http/Controllers/Pelaporan/AL/LampiranHasilUjiController.php new file mode 100644 index 0000000..905d21d --- /dev/null +++ b/app/Http/Controllers/Pelaporan/AL/LampiranHasilUjiController.php @@ -0,0 +1,265 @@ + + */ +class LampiranHasilUjiController extends Controller +{ + /** + * Display and edit attachment form + * + * @param int $idMcIpal + * @param string $bulan + * @return \Illuminate\Http\Response + */ + public function edit($idMcIpal, $bulan) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + // Get IPAL and pelaporan data + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($ipal->idmcpelaporan); + + // Determine if upload is allowed in current period + $blnAwal = (($pelaporan->idrefperiodepelaporan - 1) * 3) + 1; + $blnAkhir = $blnAwal + 3; + $editable = Pelaporan::checkEditable($ipal->idmcpelaporan, 'al') && Gate::allows('pelaporan.edit'); + + if (($bulan >= $blnAwal && $bulan <= $blnAkhir) && $editable) { + $enableUpload = 1; + } else { + $enableUpload = 0; + } + + $data = [ + 'idmcipal' => $idMcIpal, + 'tahun' => $pelaporan->tahun, + 'periode' => $pelaporan->periode, + 'nama_ipal' => $ipal->nama, + 'bulan' => $this->_mcMonth($bulan), + 'enableUpload' => $enableUpload + ]; + + return view('pelaporan.ipal.lampiran', $data); + } + + /** + * Upload files via dropzone + * + * @param Request $request + * @param int $idMcIpal + * @param string $bulan + * @return void + */ + public function uploadFile(Request $request, $idMcIpal, $bulan) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + // Get IPAL and pelaporan data + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($ipal->idmcpelaporan); + + // Get upload directory + $dirUpload = $this->_getDirectory($pelaporan->id, $idMcIpal, 'al', 'A6', $bulan); + + // Create directory if it doesn't exist + if (!Storage::disk('public')->exists($dirUpload)) { + Storage::disk('public')->makeDirectory($dirUpload, 0777, true); + } + + // Handle file uploads + if ($request->hasFile('file')) { + $files = $request->file('file'); + + foreach ($files as $file) { + $name = $file->getClientOriginalName(); + $ext = $file->getClientOriginalExtension(); + $baseName = pathinfo($name, PATHINFO_FILENAME); + $newName = $baseName . '_' . date('Ymd_His') . '.' . $ext; + + $filePath = $file->storeAs($dirUpload, $newName, 'public'); + $fullPath = storage_path('app/public/' . $filePath); + + // Set file permissions + chmod($fullPath, 0777); + + // Save file data to database + $data = [ + 'idmcipal' => $idMcIpal, + 'tahun' => $pelaporan->tahun, + 'idrefperusahaan' => $pelaporan->idrefperusahaan, + 'bulan' => $bulan, + 'dokumen' => $fullPath, + 'tanggalunggah' => Carbon::now()->format('Y-m-d H:i:s') + ]; + + Ipal::saveLampiranHasilUji($data); + } + } + } + + /** + * List all uploaded files for dropzone + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function listFiles(Request $request) + { + // Check authorization + if (!(Gate::allows('pelaporan.view') || Gate::allows('verifikasi.view'))) { + abort(403); + } + + // Get parameters from request + $idMcIpal = $request->input('idmcipal'); + $bulan = $request->input('bulan'); + + // Get IPAL and pelaporan data + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($ipal->idmcpelaporan); + + $result = []; + + // Get all attachments + $allLampiran = Ipal::getLampiranHasilUji([ + 'b.idrefipal' => $ipal->idrefipal, + 'a.idrefperusahaan' => $pelaporan->idrefperusahaan, + 'a.bulan' => $bulan, + 'a.tahun' => $pelaporan->tahun + ]); + + foreach ($allLampiran as $lampiran) { + if (File::exists($lampiran->dokumen)) { + $pathExplode = explode('/', $lampiran->dokumen); + $obj = [ + 'name' => end($pathExplode), + 'size' => File::size($lampiran->dokumen), + 'path' => $lampiran->dokumen + ]; + $result[] = $obj; + } + } + + return response()->json($result); + } + + /** + * Delete files from dropzone + * + * @param Request $request + * @return void + */ + public function deleteFile(Request $request) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + // Get parameters from request + $idMcIpal = $request->input('idmcipal'); + $bulan = $request->input('bulan'); + $fileName = $request->input('fileName'); + + // Get IPAL data + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + + // Get upload directory + $dirUpload = storage_path('app/public/') . $this->_getDirectory($ipal->idmcpelaporan, $idMcIpal, 'al', 'A6', $bulan); + + // Delete file + $fullPath = $dirUpload . basename($fileName); + if (File::exists($fullPath)) { + File::delete($fullPath); + } + + // Delete from database + $filter = [ + 'idmcipal' => $idMcIpal, + 'bulan' => $bulan, + 'dokumen' => $dirUpload . basename($fileName) + ]; + + Ipal::deleteLampiranHasilUji($filter); + } + + /** + * Get directory for file storage + * + * @param int $idMcPelaporan + * @param int $idMcIpal + * @param string $kodeRefPelaporan + * @param string $kodeKomponen + * @param string $bulan + * @return string + */ + private function _getDirectory($idMcPelaporan, $idMcIpal, $kodeRefPelaporan, $kodeKomponen, $bulan) + { + $pelaporan = Pelaporan::findOrFail($idMcPelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + + $notAllowedChar = [' ', '.', '/', '-', ',', ':']; + + $noInduk = $perusahaan->nomorinduk; + $noIpal = $ipal->nomor; + $tahun = $pelaporan->tahun; + $periode = strtolower(str_replace($notAllowedChar, '_', $pelaporan->periode)); + + $dirUpload = 'data_perusahaan/' . $noInduk . '/lampiran' . '/' . $kodeRefPelaporan . '/' . + $kodeKomponen . '/' . $tahun . '_' . $periode . '/lampiran_hasiluji' . '/' . + $bulan . '/' . $noIpal . '/'; + + return $dirUpload; + } + + /** + * Convert month number to name + * + * @param int $monthNum + * @return string + */ + private function _mcMonth($monthNum) + { + $months = [ + 1 => 'January', + 2 => 'February', + 3 => 'March', + 4 => 'April', + 5 => 'May', + 6 => 'June', + 7 => 'July', + 8 => 'August', + 9 => 'September', + 10 => 'October', + 11 => 'November', + 12 => 'December' + ]; + + return $months[$monthNum] ?? ''; + } +} diff --git a/app/Http/Controllers/Pelaporan/AL/LampiranSyaratTeknisController.php b/app/Http/Controllers/Pelaporan/AL/LampiranSyaratTeknisController.php new file mode 100644 index 0000000..5b90bee --- /dev/null +++ b/app/Http/Controllers/Pelaporan/AL/LampiranSyaratTeknisController.php @@ -0,0 +1,319 @@ + + */ +class LampiranSyaratTeknisController extends Controller +{ + /** + * Display and edit technical requirements attachment form + * + * @param int $idMcIpal + * @param string $kodeKomponen + * @return \Illuminate\Http\Response + */ + public function edit($idMcIpal, $kodeKomponen) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + // Get models data + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($ipal->idmcpelaporan); + + $data = [ + 'nama_ipal' => $ipal->nama, + 'idmcipal' => $idMcIpal, + 'editable' => Pelaporan::checkEditable($ipal->idmcpelaporan, 'al') && Gate::allows('pelaporan.edit'), + 'kode_komponen' => $kodeKomponen, + 'nama_komponen' => Lampiran::getKomponenByKode($kodeKomponen)->nama + ]; + + return view('pelaporan.ipal.lampiran_syarat_teknis', $data); + } + + /** + * Upload files via dropzone + * + * @param Request $request + * @param int $idMcIpal + * @param string $kodeKomponen + * @return void + */ + public function uploadFile(Request $request, $idMcIpal, $kodeKomponen) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + // Get IPAL data + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + + // Get upload directory + $dirUpload = $this->_getDirectory($idMcIpal, $kodeKomponen); + + // Create directory if it doesn't exist + if (!Storage::disk('public')->exists($dirUpload)) { + Storage::disk('public')->makeDirectory($dirUpload, 0777, true); + } + + // Handle file uploads + if ($request->hasFile('file')) { + $files = $request->file('file'); + + foreach ($files as $file) { + $name = $file->getClientOriginalName(); + $ext = $file->getClientOriginalExtension(); + $baseName = pathinfo($name, PATHINFO_FILENAME); + $newName = $baseName . '_' . date('Ymd_His') . '.' . $ext; + + $filePath = $file->storeAs($dirUpload, $newName, 'public'); + $fullPath = storage_path('app/public/' . $filePath); + + // Set file permissions + chmod($fullPath, 0777); + + // Save file data to database + if ($kodeKomponen != 'A5') { + $idRefKomponen = Lampiran::getKomponenByKode($kodeKomponen)->id; + $insert = [ + 'PelapranId' => $ipal->idmcpelaporan, + 'IpalId' => $idMcIpal, + 'KomponenId' => $idRefKomponen, + 'Dokumen' => $fullPath, + 'TanggalUnggah' => Carbon::now()->format('Y-m-d H:i:s') + ]; + + Lampiran::saveFile($insert); + } else { + // For A5, update IPAL's lampiran field + if ($ipal->lampiran && File::exists($ipal->lampiran)) { + File::delete($ipal->lampiran); + } + Ipal::editMcIpal($idMcIpal, ['Lamapiran' => $fullPath]); + } + } + } + } + + /** + * List all uploaded files for dropzone + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function listFiles(Request $request) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + // Get parameters from request + $idMcIpal = $request->input('idmcipal'); + $kodeKomponen = $request->input('kode_komponen'); + $idRefKomponen = Lampiran::getKomponenByKode($kodeKomponen)->id; + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + + $result = []; + + // Get all attachments + if ($kodeKomponen != 'A5') { + $allLampiran = Lampiran::getLampiran([ + 'idmcipal' => $idMcIpal, + 'idrefkomponen' => $idRefKomponen + ]); + + foreach ($allLampiran as $lampiran) { + if (File::exists($lampiran->dokumen)) { + $pathExplode = explode('/', $lampiran->dokumen); + $obj = [ + 'name' => end($pathExplode), + 'size' => File::size($lampiran->dokumen), + 'path' => $lampiran->dokumen + ]; + $result[] = $obj; + } + } + } else { + // For A5, get from IPAL's lampiran field + $lampiran = $ipal->lampiran; + if ($lampiran && File::exists($lampiran)) { + $pathExplode = explode('/', $lampiran); + $obj = [ + 'name' => end($pathExplode), + 'size' => File::size($lampiran), + 'path' => $lampiran + ]; + $result[] = $obj; + } + } + + return response()->json($result); + } + + /** + * Delete files from dropzone + * + * @param Request $request + * @return void + */ + public function deleteFile(Request $request) + { + // Check authorization + if (!Gate::allows('pelaporan.edit')) { + abort(403); + } + + // Get parameters from request + $filePath = $request->input('filePath'); + $idMcIpal = $request->input('idmcipal'); + $kodeKomponen = $request->input('kode_komponen'); + + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $idRefKomponen = Lampiran::getKomponenByKode($kodeKomponen)->id; + + if ($kodeKomponen != 'A5') { + // Delete file physically + if (File::exists($filePath)) { + File::delete($filePath); + } + + // Delete from database + $filter = [ + 'idmcipal' => $idMcIpal, + 'idrefkomponen' => $idRefKomponen, + 'dokumen' => $filePath + ]; + + Lampiran::deleteFile($filter); + } else { + // For A5, clear IPAL's lampiran field + if ($ipal->lampiran && File::exists($ipal->lampiran)) { + File::delete($ipal->lampiran); + } + Ipal::editMcIpal($idMcIpal, ['lampiran' => '']); + } + + return response()->json(['success' => true]); + } + + /** + * Check if attachments exist + * + * @param int $idMcIpal + * @param string $kodeKomponen + * @return \Illuminate\Http\JsonResponse + */ + public function cekAdaLampiran($idMcIpal, $kodeKomponen) + { + // Check authorization + if (!Gate::allows('pelaporan.view')) { + abort(403); + } + + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + + if ($kodeKomponen == 'all') { + $filter = [ + 'idmcpelaporan' => $ipal->idmcpelaporan, + 'idmcipal' => $idMcIpal + ]; + + $allLampiran = Lampiran::getLampiran($filter); + $idA5 = Lampiran::getKomponenByKode('A5')->id; + + $lampiranExists = []; + + foreach ($allLampiran as $lampiran) { + if ($lampiran->idrefkomponen != $idA5) { + if (File::exists($lampiran->dokumen)) { + if (!in_array($lampiran->idrefkomponen, $lampiranExists)) { + array_push($lampiranExists, $lampiran->idrefkomponen); + } + } + } + } + + if ($ipal->lampiran && File::exists($ipal->lampiran)) { + array_push($lampiranExists, $idA5); + } + + $response = $lampiranExists; + } else { + $idRefKomponen = Lampiran::getKomponenByKode($kodeKomponen)->id; + + $response = ['lampiran' => false, 'refkomponen' => $idRefKomponen]; + + if ($kodeKomponen != 'A5') { + $filter = [ + 'idmcpelaporan' => $ipal->idmcpelaporan, + 'idmcipal' => $idMcIpal, + 'idrefkomponen' => $idRefKomponen + ]; + $allLampiran = Lampiran::getLampiran($filter); + + if ($allLampiran) { + foreach ($allLampiran as $lampiran) { + if (File::exists($lampiran->dokumen)) { + $response['lampiran'] = true; + break; + } + } + } + } else { + if ($ipal->lampiran && File::exists($ipal->lampiran)) { + $response['lampiran'] = true; + } + } + } + + return response()->json($response); + } + + /** + * Get directory for file storage + * + * @param int $idMcIpal + * @param string $kodeKomponen + * @return string + */ + private function _getDirectory($idMcIpal, $kodeKomponen) + { + $ipal = Ipal::getOneBy(['id' => $idMcIpal]); + $pelaporan = Pelaporan::findOrFail($ipal->idmcpelaporan); + $perusahaan = Pelaporan::getPerusahaan($pelaporan->idrefperusahaan); + + $notAllowedChar = [' ', '.', '/', '-', ',', ':']; + + $noInduk = $perusahaan->nomorinduk; + $tahun = $pelaporan->tahun; + $periode = strtolower(str_replace($notAllowedChar, '_', $pelaporan->periode)); + $kodeRefPelaporan = 'al'; + $ipalName = str_replace($notAllowedChar, '_', $ipal->nama); + + $dirUpload = 'data_perusahaan/' . $noInduk . '/lampiran' . '/' . $kodeRefPelaporan . '/' . + $tahun . '_' . $periode . '/' . $ipalName . '/' . $kodeKomponen . '/'; + + return $dirUpload; + } +} diff --git a/app/Http/Controllers/PelaporanALController.php b/app/Http/Controllers/PelaporanALController.php index e5136c2..d5443eb 100644 --- a/app/Http/Controllers/PelaporanALController.php +++ b/app/Http/Controllers/PelaporanALController.php @@ -2,19 +2,141 @@ namespace App\Http\Controllers; +use App\Models\Pelaporan; +use App\Models\PeriodePelaporan; +use App\Models\Perusahaan; +use Exception; +use Illuminate\Database\QueryException; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Inertia\Inertia; class PelaporanALController extends Controller { - public function index() + + public function index(){ + try { + // Mendapatkan data perusahaan dan periode pelaporan + $companies = Perusahaan::all(); + $periodes = PeriodePelaporan::all(); + + // Mendapatkan pelaporan dengan relasi perusahaan dan periode + $pelaporan = Pelaporan::with(['Perusahaan', 'PeriodePelaporan'])->get(); + + return Inertia::render('admin/pelaporan/AL/index_AL', [ + 'companies' => $companies, + 'periodes' => $periodes, + 'pelaporan' => $pelaporan, + ]); + } catch (QueryException $e) { + Log::error('Error fetching data for PelaporanALController index: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan saat mengambil data laporan.'); + } catch (Exception $e) { + Log::error('Unexpected error in PelaporanALController index: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan tak terduga.'); + } + } + + // public function indexIpal() + // { + // try { + // return Inertia::render('admin/pelaporan/AL/index_AL_IPAL'); + // } catch (\Exception $e) { + // Log::error('Error rendering view: ' . $e->getMessage()); + // return back()->with('error', 'Something went wrong.'); + // } + // } + + public function indexIpal(){ + try { + // Data IPAL + $ipals = Pelaporan::all(); + + return Inertia::render('admin/pelaporan/AL/index_AL_IPAL', [ + 'ipals' => $ipals, + ]); + } catch (QueryException $e) { + Log::error('Error fetching data for IPAL in PelaporanALController indexIpal: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan saat mengambil data IPAL.'); + } catch (Exception $e) { + Log::error('Unexpected error in PelaporanALController indexIpal: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan tak terduga.'); + } + } + + public function store(Request $request) { try { - return Inertia::render('admin/pelaporan/AL/index_AL'); - } catch (\Exception $e) { - Log::error('Error rendering view: ' . $e->getMessage()); - return back()->with('error', 'Something went wrong.'); + // Validasi input + $request->validate([ + 'company_id' => 'required|exists:perusahaan,id', + 'period_id' => 'required|exists:periode_pelaporan,id', + 'tahun' => 'required|integer', + ]); + + // Membuat pelaporan baru + Pelaporan::create([ + 'PerusahaanId' => $request->company_id, + 'PeriodePelaporanId' => $request->period_id, + 'Tahun' => $request->tahun, + ]); + + return redirect()->route('pelaporan.index')->with('success', 'Pelaporan berhasil ditambahkan.'); + } catch (QueryException $e) { + Log::error('Error while storing Pelaporan: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan saat menambahkan pelaporan.'); + } catch (Exception $e) { + Log::error('Unexpected error while storing Pelaporan: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan tak terduga.'); + } + } + + public function update(Request $request, $id) + { + try { + // Validasi input + $request->validate([ + 'company_id' => 'required|exists:perusahaan,id', + 'period_id' => 'required|exists:periode_pelaporan,id', + 'tahun' => 'required|integer', + ]); + + // Menemukan pelaporan berdasarkan ID + $pelaporan = Pelaporan::findOrFail($id); + + // Mengupdate data pelaporan + $pelaporan->update([ + 'PerusahaanId' => $request->company_id, + 'PeriodePelaporanId' => $request->period_id, + 'Tahun' => $request->tahun, + ]); + + return redirect()->route('pelaporan.index')->with('success', 'Pelaporan berhasil diperbarui.'); + } catch (QueryException $e) { + Log::error('Error while updating Pelaporan: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan saat memperbarui pelaporan.'); + } catch (Exception $e) { + Log::error('Unexpected error while updating Pelaporan: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan tak terduga.'); + } + } + + public function destroy($id) + { + try { + // Menemukan pelaporan berdasarkan ID + $pelaporan = Pelaporan::findOrFail($id); + + // Menghapus pelaporan + $pelaporan->delete(); + + return redirect()->route('pelaporan.index')->with('success', 'Pelaporan berhasil dihapus.'); + } catch (QueryException $e) { + Log::error('Error while deleting Pelaporan: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan saat menghapus pelaporan.'); + } catch (Exception $e) { + Log::error('Unexpected error while deleting Pelaporan: ' . $e->getMessage()); + return back()->with('error', 'Terjadi kesalahan tak terduga.'); } } } diff --git a/app/Http/Controllers/PelaporanController.php b/app/Http/Controllers/PelaporanController.php index 08ca839..3181156 100644 --- a/app/Http/Controllers/PelaporanController.php +++ b/app/Http/Controllers/PelaporanController.php @@ -2,19 +2,43 @@ namespace App\Http\Controllers; +use App\Models\Pelaporan; +use App\Models\PeriodePelaporan; +use App\Models\Perusahaan; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use Inertia\Inertia; class PelaporanController extends Controller { - public function index() + // public function index() + // { + // try { + // return Inertia::render('admin/pelaporan/index_pelaporan'); + // } catch (\Exception $e) { + // Log::error('Error rendering view: ' . $e->getMessage()); + // return back()->with('error', 'Something went wrong.'); + // } + // } + + public function index(Request $request) { - try { - return Inertia::render('admin/pelaporan/index_pelaporan'); - } catch (\Exception $e) { - Log::error('Error rendering view: ' . $e->getMessage()); - return back()->with('error', 'Something went wrong.'); - } + // Ambil data perusahaan + $companies = Perusahaan::select('PerusahaanId', 'NamaPerusahaan')->get(); + + // Ambil data periode (misalnya Triwulan) + // Pastikan model PeriodePelaporan memiliki field 'NamaPeriode' atau 'Triwulan' + $periodes = PeriodePelaporan::select('PeriodePelaporanId', 'Nama')->get(); + + // Ambil data pelaporan lengkap dengan relasi perusahaan dan periode pelaporan + // (Sesuaikan nama relasinya dengan yang ada di model Pelaporan) + $pelaporan = Pelaporan::with(['perusahaan', 'periodePelaporan'])->get(); + + // Kirim data ke Inertia + return Inertia::render('admin/pelaporan/index_pelaporan', [ + 'companies' => $companies, + 'periodes' => $periodes, + 'pelaporan' => $pelaporan, + ]); } } diff --git a/app/Http/Controllers/PostController.php b/app/Http/Controllers/PostController.php index 1bb0424..fcd7d64 100644 --- a/app/Http/Controllers/PostController.php +++ b/app/Http/Controllers/PostController.php @@ -17,6 +17,15 @@ class PostController extends Controller public function index() { $posts = Post::with(['kategori', 'subkategori'])->latest()->get(); + + // Transform posts to include proper image URLs + $posts = $posts->map(function ($post) { + if ($post->ImagePost) { + $post->ImagePost = Storage::url($post->ImagePost); + } + return $post; + }); + $kategori = Kategori::all(); $subkategori = SubKategori::all(); @@ -56,7 +65,18 @@ class PostController extends Controller throw new \Exception('Invalid image file'); } - $data['ImagePost'] = $file->store('images/posts', 'public'); + Log::info('Uploading file to Minio', [ + 'filename' => $file->getClientOriginalName(), + 'mimetype' => $file->getMimeType(), + 'size' => $file->getSize() + ]); + + $data['ImagePost'] = $file->store('images/posts', 's3'); + + Log::info('File uploaded to Minio', [ + 'path' => $data['ImagePost'], + 'url' => Storage::url($data['ImagePost']) + ]); if ($data['ImagePost'] === false) { throw new \Exception('Failed to store image'); @@ -73,8 +93,8 @@ class PostController extends Controller } catch (\Exception $e) { DB::rollBack(); - if (isset($data['ImagePost']) && Storage::disk('public')->exists($data['ImagePost'])) { - Storage::disk('public')->delete($data['ImagePost']); + if (isset($data['ImagePost']) && Storage::disk('s3')->exists($data['ImagePost'])) { + Storage::disk('s3')->delete($data['ImagePost']); } Log::error('Error creating post: ' . $e->getMessage()); @@ -101,7 +121,7 @@ class PostController extends Controller return Inertia::render('admin/post/edit_post', [ 'posting' => [ ...$post->toArray(), - 'ImagePost' => $post->ImagePost ? '/storage/' . $post->ImagePost : null, + 'ImagePost' => $post->ImagePost ? Storage::url($post->ImagePost) : null, ], 'kategori' => Kategori::all(), 'subkategori' => SubKategori::all(), @@ -112,47 +132,61 @@ class PostController extends Controller } public function update(PostRequest $request, Post $post) -{ - try { - DB::beginTransaction(); - $data = $request->validated(); + { + try { + DB::beginTransaction(); + $data = $request->validated(); - // Update gambar hanya jika ada file baru yang diupload - if ($request->hasFile('ImagePost')) { - // Hapus gambar lama jika ada - if ($post->ImagePost && Storage::disk('public')->exists($post->ImagePost)) { - Storage::disk('public')->delete($post->ImagePost); + // Update gambar hanya jika ada file baru yang diupload + if ($request->hasFile('ImagePost')) { + // Hapus gambar lama jika ada + if ($post->ImagePost && Storage::disk('s3')->exists($post->ImagePost)) { + Log::info('Deleting old image from Minio', ['path' => $post->ImagePost]); + Storage::disk('s3')->delete($post->ImagePost); + } + + $file = $request->file('ImagePost'); + Log::info('Uploading new image to Minio', [ + 'filename' => $file->getClientOriginalName(), + 'mimetype' => $file->getMimeType(), + 'size' => $file->getSize() + ]); + + $data['ImagePost'] = $file->store('images/posts', 's3'); + + Log::info('New image uploaded to Minio', [ + 'path' => $data['ImagePost'], + 'url' => Storage::url($data['ImagePost']) + ]); + } else { + // Jika tidak ada file baru, jangan update field ImagePost + unset($data['ImagePost']); } - $data['ImagePost'] = $request->file('ImagePost')->store('images/posts', 'public'); - } else { - // Jika tidak ada file baru, jangan update field ImagePost - unset($data['ImagePost']); + + // Pastikan nilai is_publish dikonversi ke boolean + $data['IsPublish'] = filter_var($request->input('IsPublish'), FILTER_VALIDATE_BOOLEAN); + + $post->update($data); + DB::commit(); + + return redirect()->route('admin.post.index')->with('success', 'Post berhasil diperbarui.'); + } catch (\Exception $e) { + DB::rollBack(); + Log::error('Error updating Post: ' . $e->getMessage()); + Log::info('Form data received:', [ + 'IsPublish' => $request->input('IsPublish'), + 'IsPublishType' => gettype($request->input('IsPublish')), + 'hasFile' => $request->hasFile('ImagePost') + ]); + return back()->with('error', 'Terjadi kesalahan saat memperbarui post.'); } - - // Pastikan nilai is_publish dikonversi ke boolean - $data['IsPublish'] = filter_var($request->input('IsPublish'), FILTER_VALIDATE_BOOLEAN); - - $post->update($data); - DB::commit(); - - return redirect()->route('admin.post.index')->with('success', 'Post berhasil diperbarui.'); - } catch (\Exception $e) { - DB::rollBack(); - Log::error('Error updating Post: ' . $e->getMessage()); - Log::info('Form data received:', [ - 'IsPublish' => $request->input('IsPublish'), - 'IsPublishType' => gettype($request->input('IsPublish')), - 'hasFile' => $request->hasFile('ImagePost') - ]); - return back()->with('error', 'Terjadi kesalahan saat memperbarui post.'); } -} public function destroy(Post $post) { try { - Storage::disk('public')->delete($post->ImagePost); + Storage::disk('s3')->delete($post->ImagePost); $post->delete(); return redirect()->route('admin.post.index')->with('success', 'Post berhasil dihapus.'); diff --git a/app/Http/Controllers/RefHistoryKegiatanController.php b/app/Http/Controllers/RefHistoryKegiatanController.php new file mode 100644 index 0000000..a5cce05 --- /dev/null +++ b/app/Http/Controllers/RefHistoryKegiatanController.php @@ -0,0 +1,67 @@ +get(); + return Inertia::render('admin/kegiatan/index_refhistory_kegiatan', ['refhistorykegiatan' => $refhistorykegiatan]); + } catch (\Exception $e) { + Log::error('Error fetching Ref History Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function store(RefHistoryKegiatanRequest $request) + { + try { + $refhistorykegiatan = RefHistoryKegiatan::withTrashed() + ->where('NamaHistoryKegiatan', $request->NamaHistoryKegiatan) + ->first(); + + if ($refhistorykegiatan) { + $refhistorykegiatan->restore(); + return redirect()->route('admin.refhistorykegiatan.index')->with('success', 'Ref History Kegiatan berhasil dikembalikan.'); + } + + RefHistoryKegiatan::create($request->validated()); + + return redirect()->route('admin.refhistorykegiatan.index')->with('success', 'Ref History Kegiatan berhasil dibuat.'); + } catch (\Exception $e) { + Log::error('Error creating Ref History Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function update(RefHistoryKegiatanRequest $request, RefHistoryKegiatan $refhistorykegiatan) + { + try { + $refhistorykegiatan->update($request->validated()); + return redirect()->route('admin.refhistorykegiatan.index')->with('success', 'Ref History Kegiatan berhasil diperbarui.'); + } catch (\Exception $e) { + Log::error('Error updating Ref History Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } + + public function destroy(RefHistoryKegiatan $refhistorykegiatan) + { + try { + $refhistorykegiatan->delete(); + return redirect()->route('admin.refhistorykegiatan.index')->with('success', 'Ref History Kegiatan berhasil dihapus.'); + } catch (\Exception $e) { + Log::error('Error deleting Ref History Kegiatan: ' . $e->getMessage()); + return back()->with('error', 'Something went wrong.'); + } + } +} diff --git a/app/Http/Requests/HistoryPerusahaanRequest.php b/app/Http/Requests/HistoryPerusahaanRequest.php index 8447283..7bea344 100644 --- a/app/Http/Requests/HistoryPerusahaanRequest.php +++ b/app/Http/Requests/HistoryPerusahaanRequest.php @@ -23,7 +23,7 @@ class HistoryPerusahaanRequest extends FormRequest { return [ 'PerusahaanId' => 'required|integer', - 'HistoryKegiatanId' => 'required|integer', + 'RefHistoryKegiatanId' => 'required|integer', 'TanggalHistory' => 'required|date', 'NomorHistory' => 'nullable|string|max:100', 'KeteranganHistory' => 'nullable|string', diff --git a/app/Http/Requests/HistoryKegiatanRequest.php b/app/Http/Requests/RefHistoryKegiatanRequest.php similarity index 78% rename from app/Http/Requests/HistoryKegiatanRequest.php rename to app/Http/Requests/RefHistoryKegiatanRequest.php index 11d72db..79e1ad0 100644 --- a/app/Http/Requests/HistoryKegiatanRequest.php +++ b/app/Http/Requests/RefHistoryKegiatanRequest.php @@ -5,7 +5,7 @@ namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rule; -class HistoryKegiatanRequest extends FormRequest +class RefHistoryKegiatanRequest extends FormRequest { /** * Determine if the user is authorized to make this request. @@ -27,7 +27,7 @@ class HistoryKegiatanRequest extends FormRequest 'required', 'string', 'max:255', - Rule::unique('HistoryKegiatan', 'NamaHistoryKegiatan')->whereNull('deleted_at') // Abaikan data yang dihapus (soft delete) + Rule::unique('RefHistoryKegiatan', 'NamaHistoryKegiatan')->whereNull('deleted_at') // Abaikan data yang dihapus (soft delete) ], 'IsPublish' => 'boolean', ]; diff --git a/app/Models/Catatan.php b/app/Models/Catatan.php new file mode 100644 index 0000000..3325f1a --- /dev/null +++ b/app/Models/Catatan.php @@ -0,0 +1,40 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model RefPelaporan. + */ + public function refPelaporan() + { + return $this->belongsTo(RefPelaporan::class, 'RefPelaporanId', 'RefPelaporanId'); + } +} diff --git a/app/Models/Cerobong.php b/app/Models/Cerobong.php new file mode 100644 index 0000000..28ab5fe --- /dev/null +++ b/app/Models/Cerobong.php @@ -0,0 +1,52 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model RefCerobong. + */ + public function refCerobong() + { + return $this->belongsTo(RefCerobong::class, 'RefCerobongId', 'RefCerobongId'); + } +} diff --git a/app/Models/CerobongParameter.php b/app/Models/CerobongParameter.php new file mode 100644 index 0000000..b1286e7 --- /dev/null +++ b/app/Models/CerobongParameter.php @@ -0,0 +1,42 @@ +belongsTo(Cerobong::class, 'CerobongId', 'CerobongId'); + } + + /** + * Relasi ke model RefCerobongParameter. + */ + public function refCerobongParameter() + { + return $this->belongsTo(RefCerobongParameter::class, 'RefCerobongParameterId', 'RefCerobongParameterId'); + } +} diff --git a/app/Models/ChoicesLP.php b/app/Models/ChoicesLP.php new file mode 100644 index 0000000..beab1f6 --- /dev/null +++ b/app/Models/ChoicesLP.php @@ -0,0 +1,10 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/GroupHasil.php b/app/Models/GroupHasil.php new file mode 100644 index 0000000..ff320cf --- /dev/null +++ b/app/Models/GroupHasil.php @@ -0,0 +1,24 @@ +belongsTo(Hasil::class, 'HasilId', 'HasilId'); + } +} diff --git a/app/Models/GroupPerusahaan.php b/app/Models/GroupPerusahaan.php new file mode 100644 index 0000000..773775e --- /dev/null +++ b/app/Models/GroupPerusahaan.php @@ -0,0 +1,38 @@ +belongsTo(User::class, 'UserId', 'id'); + } + + + /** + * Relasi ke model Perusahaan. + */ + public function perusahaan() + { + return $this->hasMany(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/Hasil.php b/app/Models/Hasil.php new file mode 100644 index 0000000..9e362a8 --- /dev/null +++ b/app/Models/Hasil.php @@ -0,0 +1,20 @@ +belongsTo(Ipal::class, 'IpalId', 'IpalId'); + } + + /** + * Relasi ke model Perusahaan. + */ + public function perusahaan() + { + return $this->belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } + + /** + * Relasi ke model IpalParameter. + */ + public function ipalParameter() + { + return $this->belongsTo(IpalParameter::class, 'IpalParameterId', 'IpalParameterId'); + } +} diff --git a/app/Models/HasilUjiBS.php b/app/Models/HasilUjiBS.php new file mode 100644 index 0000000..900398a --- /dev/null +++ b/app/Models/HasilUjiBS.php @@ -0,0 +1,42 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model Lokasi. + */ + public function lokasi() + { + return $this->belongsTo(Lokasi::class, 'LokasiId', 'LokasiId'); + } +} diff --git a/app/Models/HasilUjiKDM.php b/app/Models/HasilUjiKDM.php new file mode 100644 index 0000000..9415d30 --- /dev/null +++ b/app/Models/HasilUjiKDM.php @@ -0,0 +1,37 @@ +belongsTo(IndikatorKdm::class, 'IndikatorKdmId', 'IndikatorKdmId'); + } + + /** + * Relasi ke model Perusahaan. + */ + public function perusahaan() + { + return $this->belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/HasilUjiLP.php b/app/Models/HasilUjiLP.php new file mode 100644 index 0000000..4eb6b98 --- /dev/null +++ b/app/Models/HasilUjiLP.php @@ -0,0 +1,41 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model Perusahaan. + */ + public function perusahaan() + { + return $this->belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/HasilUjiSTB.php b/app/Models/HasilUjiSTB.php new file mode 100644 index 0000000..e6135b1 --- /dev/null +++ b/app/Models/HasilUjiSTB.php @@ -0,0 +1,47 @@ +belongsTo(Cerobong::class, 'CerobongId', 'CerobongId'); + } + + /** + * Relasi ke model CerobongParameter. + */ + public function cerobongParameter() + { + return $this->belongsTo(CerobongParameter::class, 'CerobongParameterId', 'CerobongParameterId'); + } + + /** + * Relasi ke model Perusahaan. + */ + public function perusahaan() + { + return $this->belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/HasilUjiUA.php b/app/Models/HasilUjiUA.php new file mode 100644 index 0000000..884d6eb --- /dev/null +++ b/app/Models/HasilUjiUA.php @@ -0,0 +1,39 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model Lokasi. + */ + public function lokasi() + { + return $this->belongsTo(Lokasi::class, 'LokasiId', 'LokasiId'); + } +} diff --git a/app/Models/HasilUjiUAParamter.php b/app/Models/HasilUjiUAParamter.php new file mode 100644 index 0000000..55ea053 --- /dev/null +++ b/app/Models/HasilUjiUAParamter.php @@ -0,0 +1,37 @@ +belongsTo(HasilUjiUA::class, 'HasilUjiUAId', 'HasilUjiUAId'); + } + + /** + * Relasi ke model UdaraAmbienBakuMutu. + */ + public function udaraAmbienBakuMutu() + { + return $this->belongsTo(UdaraAmbienBakuMutu::class, 'UdaraAmbienBakuMutuId', 'UdaraAmbienBakuMutuId'); + } +} diff --git a/app/Models/HistoryKegiatan.php b/app/Models/HistoryKegiatan.php index 4df4d34..f09cf65 100644 --- a/app/Models/HistoryKegiatan.php +++ b/app/Models/HistoryKegiatan.php @@ -4,21 +4,37 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\SoftDeletes; class HistoryKegiatan extends Model { - use HasFactory; use SoftDeletes; + use HasFactory; protected $table = 'HistoryKegiatan'; - protected $dates = ['deleted_at']; - protected $primaryKey = 'HistoryKegiatanId'; protected $fillable = [ - 'HistoryKegiatanId', - 'NamaHistoryKegiatan', - 'IsPublish', + 'PerusahaanId', + 'RefHistoryKegiatanId', + 'Tanggal', + 'Nomor', + 'Keterangan', + 'Dokumen', ]; + + /** + * Relasi ke model Perusahaan. + */ + public function perusahaan() + { + return $this->belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } + + /** + * Relasi ke model RefHistoryKegiatan. + */ + public function refHistoryKegiatan() + { + return $this->belongsTo(RefHistoryKegiatan::class, 'RefHistoryKegiatanId', 'RefHistoryKegiatanId'); + } } diff --git a/app/Models/HistoryPerusahaan.php b/app/Models/HistoryPerusahaan.php index d8e024a..8aafa37 100644 --- a/app/Models/HistoryPerusahaan.php +++ b/app/Models/HistoryPerusahaan.php @@ -10,7 +10,7 @@ class HistoryPerusahaan extends Model protected $primaryKey = 'HistoryPerusahaanId'; protected $fillable = [ 'PerusahaanId', - 'HistoryKegiatanId', + 'RefHistoryKegiatanId', 'TanggalHistory', 'NomorHistory', 'KeteranganHistory', @@ -22,9 +22,9 @@ class HistoryPerusahaan extends Model return $this->belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); } - public function historyKegiatan() + public function refhistoryKegiatan() { - return $this->belongsTo(HistoryKegiatan::class, 'HistoryKegiatanId', 'HistoryKegiatanId'); + return $this->belongsTo(RefHistoryKegiatan::class, 'RefHistoryKegiatanId', 'RefHistoryKegiatanId'); } public function kelurahan() diff --git a/app/Models/IndikatorKdm.php b/app/Models/IndikatorKdm.php new file mode 100644 index 0000000..591b2e8 --- /dev/null +++ b/app/Models/IndikatorKdm.php @@ -0,0 +1,24 @@ +hasMany(HasilUjiKDM::class, 'IndikatorKdmId', 'IndikatorKdmId'); + } +} diff --git a/app/Models/Ipal.php b/app/Models/Ipal.php new file mode 100644 index 0000000..92a4529 --- /dev/null +++ b/app/Models/Ipal.php @@ -0,0 +1,56 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model RefIpal. + */ + public function refIpal() + { + return $this->belongsTo(RefIpal::class, 'RefIpalId', 'RefIpalId'); + } + + /** + * Relasi ke model IpalParameter. + */ + public function ipalParameters() + { + return $this->hasMany(IpalParameter::class, 'IpalId', 'IpalId'); + } +} diff --git a/app/Models/IpalParameter.php b/app/Models/IpalParameter.php new file mode 100644 index 0000000..4b7f3be --- /dev/null +++ b/app/Models/IpalParameter.php @@ -0,0 +1,42 @@ +belongsTo(Ipal::class, 'IpalId', 'IpalId'); + } + + /** + * Relasi ke model RefIpalParameter. + */ + public function refIpalParameter() + { + return $this->belongsTo(RefIpalParameter::class, 'RefIpalParameterId', 'RefIpalParameterId'); + } +} diff --git a/app/Models/IzinPihakKetiga.php b/app/Models/IzinPihakKetiga.php new file mode 100644 index 0000000..6945852 --- /dev/null +++ b/app/Models/IzinPihakKetiga.php @@ -0,0 +1,19 @@ +belongsTo(RefPelaporan::class, 'RefPelaporanId', 'RefPelaporanId'); + } + + /** + * Relasi ke model JenisKomponen. + */ + public function jenisKomponen() + { + return $this->belongsTo(JenisKomponen::class, 'JenisKomponenId', 'JenisKomponenId'); + } + + /** + * Relasi ke model GroupHasil. + */ + public function groupHasil() + { + return $this->belongsTo(GroupHasil::class, 'GroupHasilId', 'GroupHasilId'); + } +} diff --git a/app/Models/Komunal.php b/app/Models/Komunal.php new file mode 100644 index 0000000..3b50d6b --- /dev/null +++ b/app/Models/Komunal.php @@ -0,0 +1,28 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/LampiranAL.php b/app/Models/LampiranAL.php new file mode 100644 index 0000000..ca43d8a --- /dev/null +++ b/app/Models/LampiranAL.php @@ -0,0 +1,41 @@ +belongsTo(Ipal::class, 'IpalId', 'IpalId'); + } + + /** + * Relasi ke model Perusahaan. + */ + public function perusahaan() + { + return $this->belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/Lokasi.php b/app/Models/Lokasi.php new file mode 100644 index 0000000..9174e63 --- /dev/null +++ b/app/Models/Lokasi.php @@ -0,0 +1,38 @@ +belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/NilaiKomponen.php b/app/Models/NilaiKomponen.php new file mode 100644 index 0000000..559abdf --- /dev/null +++ b/app/Models/NilaiKomponen.php @@ -0,0 +1,69 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model Komponen. + */ + public function komponen() + { + return $this->belongsTo(Komponen::class, 'KomponenId', 'KomponenId'); + } + + /** + * Relasi ke model Hasil. + */ + public function hasil() + { + return $this->belongsTo(Hasil::class, 'HasilId', 'HasilId'); + } + + /** + * Relasi ke model Ipal. + */ + public function ipal() + { + return $this->belongsTo(Ipal::class, 'IpalId', 'IpalId'); + } + + /** + * Relasi ke model Cerobong. + */ + public function cerobong() + { + return $this->belongsTo(Cerobong::class, 'CerobongId', 'CerobongId'); + } +} diff --git a/app/Models/NilaiKomponenPihakKetiga.php b/app/Models/NilaiKomponenPihakKetiga.php new file mode 100644 index 0000000..132c0b0 --- /dev/null +++ b/app/Models/NilaiKomponenPihakKetiga.php @@ -0,0 +1,39 @@ +belongsTo(NilaiKomponen::class, 'NilaiKomponenId', 'NilaiKomponenId'); + } + + /** + * Relasi ke model IzinPihakKetiga. + */ + public function izinPihakKetiga() + { + return $this->belongsTo(IzinPihakKetiga::class, 'IzinPihakKetigaId', 'IzinPihakKetigaId'); + } +} diff --git a/app/Models/Pelaporan.php b/app/Models/Pelaporan.php new file mode 100644 index 0000000..9cfaf7e --- /dev/null +++ b/app/Models/Pelaporan.php @@ -0,0 +1,55 @@ +belongsTo(PeriodePelaporan::class, 'PeriodePelaporanId', 'PeriodePelaporanId'); + } + + /** + * Relasi ke Perusahaan. + */ + public function perusahaan() + { + return $this->belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/Pelaporan/ALmodel.php b/app/Models/Pelaporan/ALmodel.php new file mode 100644 index 0000000..5c7622c --- /dev/null +++ b/app/Models/Pelaporan/ALmodel.php @@ -0,0 +1,99 @@ +leftJoin('NilaiKomponen', 'NilaiKomponen.KomponenId', '=', 'Komponen.KomponenId') + ->where('Komponen.PelaporanId', 2) + ->where('Komponen.Kode', '!=', 'SK') + ->selectRaw('SUM(NilaiKomponen.Nilai) / COUNT(Komponen.KomponenId) AS skl') + ->value('skl'); + + if (isset($nilai_skl)) { + // Panggil metode update_nilai_skl dan update_avg_skl dari PelaporanModel (asumsi sudah dibuat) + Pelaporan::updateNilaiSkl($idmcpelaporan, 2, $nilai_skl); + Pelaporan::updateAvgSkl($idmcpelaporan); + } + } + + /** + * Sesuaikan SPL pelaporan. + * + * 1. Pelaporan.SPL_AL, disamakan dengan mcspl_al.nilaispl. + * 2. Pelaporan.SPL, dari rata-rata spl-nya. + */ + public static function sesuaikanSplPelaporan($idmcpelaporan) + { + $spl = DB::table('Spl_AL') + ->where('PelaporanId', $idmcpelaporan) + ->first(); + + if ($spl && $spl->nilaispl) { + Pelaporan::updateNilaiSpl($idmcpelaporan, 2, $spl->nilaispl); + Pelaporan::updateAvgSpl($idmcpelaporan); + } + } + + /** + * Ambil status Komunal berdasarkan idmcpelaporan. + */ + public static function getStatusMckomunal($idmcpelaporan) + { + return DB::table('Komunal') + ->where('PelaporanId', $idmcpelaporan) + ->first(); + } + + /** + * Update atau insert status mckomunal. + */ + public static function updateStatusMckomunal($idmcpelaporan, $status) + { + $existing = self::getStatusMckomunal($idmcpelaporan); + + if ($existing) { + DB::table('Komunal') + ->where('PelaporanId', $idmcpelaporan) + ->update(['Tersambung' => $status]); + } else { + DB::table('Komunal') + ->insert([ + 'PelaporanId' => $idmcpelaporan, + 'Tersambung' => $status, + ]); + } + } + + /** + * Cek lampiran surat kerjasama berdasarkan PelaporanId dan KomponenId. + */ + public static function cekLampiranSk($idmcpelaporan, $idrefkomponen) + { + return DB::table('Lampiran') + ->where([ + 'PelaporanId' => $idmcpelaporan, + 'KomponenId' => $idrefkomponen, + ])->first(); + } +} diff --git a/app/Models/Pelaporan/IPALmodel.php b/app/Models/Pelaporan/IPALmodel.php new file mode 100644 index 0000000..b2620da --- /dev/null +++ b/app/Models/Pelaporan/IPALmodel.php @@ -0,0 +1,29 @@ +get(); + } + + /** + * Get satu record berdasarkan filter + */ + public static function getOneBy(array $filter) + { + return self::where($filter)->first(); + } +} diff --git a/app/Models/Pelaporan/IPALparameter.php b/app/Models/Pelaporan/IPALparameter.php new file mode 100644 index 0000000..6ee37a8 --- /dev/null +++ b/app/Models/Pelaporan/IPALparameter.php @@ -0,0 +1,29 @@ +get(); + } + + /** + * Get satu record berdasarkan filter + */ + public static function getOneBy(array $filter) + { + return self::where($filter)->first(); + } +} diff --git a/app/Models/Pelaporan/Lampiran.php b/app/Models/Pelaporan/Lampiran.php new file mode 100644 index 0000000..dd48fd4 --- /dev/null +++ b/app/Models/Pelaporan/Lampiran.php @@ -0,0 +1,28 @@ +join('mcpelaporan', 'mcpelaporan.id', '=', 'mclampiran_sertifikat.idmcpelaporan') + ->where($filter) + ->where('mclampiran_sertifikat.is_deleted', 0) + ->first(); + } +} + + diff --git a/app/Models/Pelaporan/Pelaporan.php b/app/Models/Pelaporan/Pelaporan.php new file mode 100644 index 0000000..110335b --- /dev/null +++ b/app/Models/Pelaporan/Pelaporan.php @@ -0,0 +1,666 @@ +select('a.*', 'b.*', 'b.Nama as Periode') + ->join(self::PERIODE . ' as b', 'b.id', '=', 'a.PeriodePelaporanId') + ->orderByDesc('a.Tahun') + ->orderBy('a.PeriodePelaporanId') + ->get() + ->toArray(); + } + + /** + * Ambil nilai SKL berdasarkan id pelaporan dan id ref pelaporan. + */ + public static function getNilaiSkl($idmcpelaporan, $idrefpelaporan) + { + $kode = self::getPelaporanCode($idrefpelaporan); + $column = 'skl_' . $kode; + + $row = DB::table('Pelaporan') + ->where('PelaporanId', $idmcpelaporan) + ->first(); + + return $row ? ($row->$column ?? null) : null; + } + + /** + * Ambil nilai SPL berdasarkan id pelaporan dan id ref pelaporan. + */ + public static function getNilaiSpl($idmcpelaporan, $idrefpelaporan) + { + $kode = self::getPelaporanCode($idrefpelaporan); + if ($kode != 'il') { + $column = 'spl_' . $kode; + $row = DB::table('Pelaporan') + ->where('PelaporanId', $idmcpelaporan) + ->first(); + + return $row ? ($row->$column ?? null) : null; + } + return null; + } + + /** + * Ambil data pelaporan dengan filter. + * + * @param array $filter + * @return array + */ + public static function getDataBy(array $filter) + { + return DB::table('Pelaporan as a') + ->select('a.*', 'a.id as PelaporanId', 'b.*', 'b.nama as Periode') + ->where($filter) + ->join(self::PERIODE . ' as b', 'b.PelaporanId', '=', 'a.PeriodePelaporanId') + ->orderByDesc('a.Tahun') + ->orderBy('a.PeriodePelaporanId') + ->get() + ->toArray(); + } + + /** + * Ambil data untuk admin dengan filter, gabungan perusahaan. + * + * @param array $filter + * @return array + */ + public static function adminGetDataBy(array $filter) + { + return DB::table('Pelaporan as a') + ->select('a.*', 'a.PelaporanId as PelaporanId', 'b.*', 'b.Nama as Periode', 'c.Nama as NamaPerusahaan') + ->where($filter) + ->join(self::PERIODE . ' as b', 'b.id', '=', 'a.PeriodePelaporanId') + ->join(self::PERUSAHAAN . ' as c', 'c.id', '=', 'a.PerusahaanId') + ->orderByDesc('a.Tahun') + ->orderBy('a.PeriodePelaporanId') + ->get() + ->toArray(); + } + + /** + * Ambil id perusahaan berdasarkan idmcusers. + */ + public static function getIdPerusahaan($idmcusers) + { + $row = DB::table('GroupPerusahaan') + ->where('users', $idmcusers) + ->first(); + + return $row ? $row->idrefperusahaan : null; + } + + /** + * Ambil data perusahaan berdasarkan idrefperusahaan. + */ + public static function getPerusahaan($idrefperusahaan) + { + return DB::table('Perusahaan') + ->where('PerusahaanId', $idrefperusahaan) + ->first(); + } + + /** + * Ambil semua perusahaan, dengan opsional filter idrefverifikator dan status aktif. + */ + public static function getAllPerusahaan($idrefverifikator = null, $is_active = null) + { + $query = DB::table('Perusahaan'); + + if ($idrefverifikator && $idrefverifikator !== "1") { + $query->where('VerifikatorId', $idrefverifikator); + } + if ($is_active !== null && $is_active !== '') { + $query->where('IsPublish', $is_active); + } + + return $query->get()->toArray(); + } + + /** + * Ambil data user perusahaan berdasarkan idrefverifikator. + */ + public static function getDataUserPerusahaan($idrefverifikator) + { + $idrefusergroups_perusahaan = 4; + + return DB::table('users') + ->select('users.*') + ->join('GroupPerusahaan', 'GroupPerusahaan.UserId', '=', 'users.id') + ->join('Perusahaan', 'GroupPerusahaan.PerusahaanId', '=', 'Perusahaan.PerusahaanId') + ->where('users.UserGroupId', $idrefusergroups_perusahaan) + ->where('Perusahaan.VerifikatorId', $idrefverifikator) + ->get() + ->toArray(); + } + + /** + * Ambil data pelaporan berdasarkan ID. + */ + public static function getById($idpelaporan) + { + return self::_getQuery() + ->where('a.id', $idpelaporan) + ->first(); + } + + /** + * Mendapatkan kode pelaporan berdasarkan idrefpelaporan. + */ + public static function getPelaporanCode($idrefpelaporan) + { + $row = DB::table('Pelaporan') + ->select('Kode') + ->where('PelaporanId', $idrefpelaporan) + ->first(); + + return $row ? $row->kode : null; + } + + /** + * Mendapatkan semua kode pelaporan. + */ + public static function getAllPelaporanCode() + { + return DB::table('Pelaporan') + ->select('Kode') + ->get() + ->toArray(); + } + + /** + * Mendapatkan data referensi pelaporan berdasarkan kode. + */ + public static function getRefPelaporanByCode($code = '') + { + return DB::table('Pelaporan') + ->where('Kode', $code) + ->first(); + } + + /** + * Mendapatkan data pelaporan dari mcpelaporan by id. + */ + public static function getMclaporan($idpelaporan) + { + return DB::table('Pelaporan') + ->where('PelaporanId', $idpelaporan) + ->first(); + } + + /** + * Update atau insert tanggal pelaporan. + */ + public static function updateTanggalPelaporan(array $data, $date) + { + $exists = DB::table('PelaporanDate') + ->where($data) + ->exists(); + + if ($exists) { + return DB::table('PelaporanDate') + ->where($data) + ->update(['ReportDate' => $date]); + } else { + $data['ReportDate'] = $date; + return DB::table('PelaporanDate')->insert($data); + } + } + + /** + * Ambil pelaporan by range tanggal dan opsional refpelaporan. + */ + public static function getPelaporanByDate($start_date, $end_date, $refpelaporan = '') + { + $query = DB::table('PelaporanDate') + ->whereBetween('ReportDate', [$start_date, $end_date]); + + if ($refpelaporan) { + $query->where('RefPelaporanId', $refpelaporan); + } + + return $query->get()->toArray(); + } + + /** + * Ambil semua perusahaan yang ada (del = 'n'). + */ + public static function getAllPerusahaanExist() + { + return DB::table('Perusahaan') + ->where('IsPublish', '0') + ->get() + ->toArray(); + } + + /** + * Update nilai SKL di tabel mcpelaporan. + */ + public static function updateNilaiSkl($idpelaporan, $idrefpelaporan, $skl) + { + $kode = self::getPelaporanCode($idrefpelaporan); + $skl = $skl === null ? 0 : $skl; + + return DB::table('Pelaporan') + ->where('PelaporanId', $idpelaporan) + ->update(["skl_$kode" => $skl]); + } + + /** + * Update nilai SPL di tabel mcpelaporan. + */ + public static function updateNilaiSpl($idpelaporan, $idrefpelaporan, $spl) + { + $kode = self::getPelaporanCode($idrefpelaporan); + + return DB::table('Pelaporan') + ->where('PelaporanId', $idpelaporan) + ->update(["spl_$kode" => $spl]); + } + + /** + * Hitung rata-rata SKL untuk pelaporan tertentu. + */ + public static function getAvgSkl($idpelaporan) + { + $query = self::getMclaporan($idpelaporan); + if (!$query) return null; + + $periode = $query->idrefperiodepelaporan; + + if ($periode == 2 || $periode == 4) { + $codes = self::getAllPelaporanCode(); + $sum = 0; + $n = DB::table('Pelaporan')->count(); + + foreach ($codes as $code) { + $col = 'skl_' . $code->kode; + $sum += $query->$col ?? 0; + } + } else { + $sum = ($query->skl_al ?? 0) + ($query->skl_lb3 ?? 0) + ($query->skl_lp ?? 0); + $n = 3; + } + + return $n > 0 ? $sum / $n : null; + } + + /** + * Hitung rata-rata SPL untuk pelaporan tertentu. + */ + public static function getAvgSpl($idpelaporan) + { + $query = self::getMclaporan($idpelaporan); + if (!$query) return null; + + $periode = $query->idrefperiodepelaporan; + + if ($periode == 2 || $periode == 4) { + $codes = self::getAllPelaporanCode(); + $sum = 0; + $n = DB::table('Pelaporan')->count() - 2; + + foreach ($codes as $code) { + if ($code->kode != 'il' && $code->kode != 'kdm') { + $col = 'spl_' . $code->kode; + $sum += $query->$col ?? 0; + } + } + } else { + $sum = ($query->spl_al ?? 0) + ($query->spl_lb3 ?? 0) + ($query->spl_lp ?? 0); + $n = 3; + } + + return $n > 0 ? $sum / $n : null; + } + + /** + * Update rata-rata SKL pada pelaporan. + */ + public static function updateAvgSkl($idpelaporan) + { + $avg_skl = self::getAvgSkl($idpelaporan); + + return DB::table('Pelaporan') + ->where('PelaporanId', $idpelaporan) + ->update(['skl' => $avg_skl]); + } + + /** + * Update rata-rata SPL pada pelaporan. + */ + public static function updateAvgSpl($idpelaporan) + { + $avg_spl = self::getAvgSpl($idpelaporan); + + return DB::table('Pelaporan') + ->where('PelaporanId', $idpelaporan) + ->update(['spl' => $avg_spl]); + } + + /** + * Ambil satu data verifikasi berdasarkan filter. + */ + public static function getOneVerifikasi(array $filter) + { + return DB::table('Verifikasi') + ->where($filter) + ->first(); + } + + /** + * Ambil banyak data verifikasi berdasarkan filter. + */ + public static function getVerifikasi(array $filter) + { + return DB::table('Verifikasi') + ->where($filter) + ->get() + ->toArray(); + } + + /** + * Ambil data evaluasi berdasarkan filter. + */ + public static function getEvaluasi(array $filter) + { + return DB::table('Evaluasi') + ->where($filter) + ->first(); + } + + /** + * Ambil data tanda terima berdasarkan filter. + */ + public static function getTandaterima(array $filter) + { + return DB::table('TandaTerima') + ->where($filter) + ->first(); + } + + /** + * Perbaiki status verifikasi. + * + * @param array $filter + * @param array $data + */ + public static function fixStatusVerifikasi(array $filter, array $data) + { + $result = DB::table('Verifikasi') + ->join('Pelaporan', 'Verifikasi.PelaporanId', '=', 'Pelaporan.PelaporanId') + ->where('Verifikasi.Verif', 0) + ->where('Pelaporan.SKL', '>', 0) + ->select('Verifikasi.VerifikasiId') + ->get(); + + if ($result->isNotEmpty()) { + $data_id = []; + foreach ($result as $row) { + $array_data = $data; + $array_data['VerifikasiId'] = $row->id; + $array_data['Verifikasi'] = 1; + $data_id[] = $array_data; + } + // Laravel batch update requires package or raw query, simplified as loop update: + foreach ($data_id as $item) { + DB::table('Verifikasi') + ->where('VerifikasiId', $item['VerifikasiId']) + ->update(['Verif' => $item['Verif']] + $item); + } + } + } + + /** + * Update status verifikasi. + */ + public static function updateStatusVerifikasi(array $filter, array $data) + { + $verifikasi = self::getOneVerifikasi($filter); + + if ($verifikasi) { + if ($verifikasi->verifikasi < ($data['Verif'] ?? 0)) { + DB::table('Verifikasi') + ->where($filter) + ->update($data); + } + } else { + DB::table('Verifikasi')->insert(array_merge($filter, $data)); + } + } + + /** + * Insert pelaporan dan dapatkan ID baru. + */ + public static function insertPelaporan(array $data) + { + return DB::table('Pelaporan')->insertGetId($data); + } + + /** + * Insert data verifikasi. + */ + public static function insertVerifikasi(array $data) + { + return DB::table('Verifikasi')->insert($data); + } + + /** + * Ambil nilai konfigurasi batas penguncian pelaporan dari mcsystem. + * + * @return int|null + */ + public static function checkReportLockedAfter() + { + $row = DB::table('System') + ->where('Name', 'ReportLockedAfter') + ->first(); + + return $row ? (int)$row->val : null; + } + + /** + * Update kolom is_checked pada pelaporan. + */ + public static function updateIsChecked(array $filter, $is_checked) + { + return DB::table('Pelaporan') + ->where($filter) + ->update(['IsChecked' => $is_checked]); + } + + /** + * Cek apakah pelaporan editable. + * + * @param int $idmcpelaporan + * @param string|null $parameter + * @param object|null $currentUser // objek user untuk cek hak admin/granted, harus diberikan saat pemanggilan + * @return bool + */ + public static function checkEditable($idmcpelaporan, $parameter = null, $currentUser = null) + { + // Jika user admin, bisa edit + if ($currentUser && method_exists($currentUser, 'isAdmin') && $currentUser->isAdmin()) { + return true; + } + + $pelaporan = self::getById($idmcpelaporan); + if (empty($pelaporan)) { + return false; + } + + $refperusahaan = self::getPerusahaan($pelaporan->idrefperusahaan); + if ($refperusahaan && $refperusahaan->is_report_locked) { + $tahun = $pelaporan->tahun; + $periode = $pelaporan->idrefperiodepelaporan; + $periode_tenggang = self::checkReportLockedAfter(); + + $periode_akhir_bulan = ($periode * 3) + $periode_tenggang; + $periode_akhir_tahun = $tahun; + + if ($periode_akhir_bulan > 12) { + $periode_akhir_bulan -= 12; + $periode_akhir_tahun++; + } + + $waktu_periode_akhir = $periode_akhir_tahun . ($periode_akhir_bulan <= 9 ? '0' . $periode_akhir_bulan : $periode_akhir_bulan); + $waktu_sekarang = date('Ym'); + + if ($waktu_sekarang > $waktu_periode_akhir) { + return false; + } + } + + if (!empty($pelaporan->is_checked)) { + $is_checked = json_decode($pelaporan->is_checked, true); + if ($parameter && isset($is_checked[$parameter]) && $is_checked[$parameter] == 1) { + return false; + } + } + + return true; + } + + /** + * Cek editable khusus verifikasi. + * + * @param int $idmcpelaporan + * @param string $idrefpelaporan + * @param object|null $currentUser + * @return bool + */ + public static function checkEditableVerifikasi($idmcpelaporan, $idrefpelaporan = '', $currentUser = null) + { + if (!$currentUser || !method_exists($currentUser, 'isGranted') || !method_exists($currentUser, 'isAdmin')) { + return false; + } + + $result = false; + $pelaporan = self::getById($idmcpelaporan); + if (!$pelaporan) { + return false; + } + + $tahun = $pelaporan->tahun; + $periode = $pelaporan->idrefperiodepelaporan; + + if ($periode != 4) { + $bulan_akhir = $periode * 3; + $awal_tenggang = '01-' . ($bulan_akhir + 1) . '-' . $tahun; + } else { + $awal_tenggang = '01-01-' . ($tahun + 1); + } + + $get_report_locked = self::checkReportLockedAfter(); + + $akhir_tenggang = strtotime($awal_tenggang . ' + ' . (30 * $get_report_locked) . ' days'); + $current_date = strtotime(date('Y-m-d')); + + if ($current_date <= $akhir_tenggang + && $currentUser->isGranted('Verifikasi.edit') + && !$currentUser->isAdmin()) { + // Cek id verifikator + // Di sini harus implementasi pemanggilan model VerifikasiModel sesuai kebutuhan anda + // Untuk contoh saya asumsikan ada method statis getIdVerifikator + $idmcusers = $currentUser->id ?? null; + if (!$idmcusers) return false; + + // Contoh pemanggilan VerifikasiModel (harus dibuat) + $idrefverifikator = Verifikasi::getIdVerifikator($idmcusers); + + if ($idrefverifikator !== null && $idrefverifikator !== "0") { + $query = DB::table('Pelaporan as a') + ->join('Perusahaan as b', 'a.PerusahaanId', '=', 'b.id') + ->where('a.PelaporanId', $idmcpelaporan) + ->select('b.VerifikatorId') + ->first(); + + if ($query && $query->idrefverifikator == $idrefverifikator) { + $result = true; + } + } else { + $result = true; + } + } + + if ($result) { + $result = false; + $get_verifikasi = self::getVerifikasi(['PelaporanId' => $idmcpelaporan]); + if (!empty($get_verifikasi)) { + $last_verifikasi = end($get_verifikasi); + if ($last_verifikasi['verif'] == 2) { + $result = true; + } else { + // Dinonaktifkan berdasarkan task T7579 + // logic lama bisa diaktifkan kembali bila diperlukan + return true; + } + } + } + + return $result; + } + + /** + * Insert atau update kolom is_checked jika belum ada. + */ + public static function insertUpdateIsChecked($idmcpelaporan) + { + $pelaporan = self::getById($idmcpelaporan); + if (empty($pelaporan->is_checked)) { + $all_refpelaporan = self::getAllPelaporanCode(); + $is_checked = []; + foreach ($all_refpelaporan as $c) { + $is_checked[$c->kode] = 1; + } + self::updateIsChecked(['PelaporanId' => $idmcpelaporan], json_encode($is_checked)); + } + } + + /** + * Query dasar untuk pengambilan data pelaporan dengan join periode dan perusahaan. + */ + private static function _getQuery() + { + return DB::table('Pelaporan as a') + ->select( + 'a.*', + 'b.Nama as Periode', + 'b.BulanAwal', + 'b.BulanAkhir', + 'c.Nama as Perusahaan', + 'c.Alamat', + 'c.NomorInduk', + 'c.PelaporanId as PerusahaanId', + 'c.doc_pdl_orig', + 'c.doc_pdl_path' + ) + ->join(self::PERIODE . ' as b', 'b.id', '=', 'a.PeriodedPelaporanId') + ->join(self::PERUSAHAAN . ' as c', 'c.id', '=', 'a.PerusahaanId'); + } +} + + diff --git a/app/Models/PelaporanDate.php b/app/Models/PelaporanDate.php new file mode 100644 index 0000000..7e884dc --- /dev/null +++ b/app/Models/PelaporanDate.php @@ -0,0 +1,37 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model RefPelaporan. + */ + public function refPelaporan() + { + return $this->belongsTo(RefPelaporan::class, 'RefPelaporanId', 'RefPelaporanId'); + } +} diff --git a/app/Models/PeriodePelaporan.php b/app/Models/PeriodePelaporan.php index 28a619f..88495db 100644 --- a/app/Models/PeriodePelaporan.php +++ b/app/Models/PeriodePelaporan.php @@ -9,7 +9,7 @@ class PeriodePelaporan extends Model protected $table = 'PeriodePelaporan'; protected $primaryKey = 'PeriodePelaporanId'; protected $fillable = [ - 'NamaPeriodePelaporan', + 'Nama', 'BulanAwal', 'BulanSelesai', ]; diff --git a/app/Models/Perusahaan.php b/app/Models/Perusahaan.php index 9302757..eaa38d8 100644 --- a/app/Models/Perusahaan.php +++ b/app/Models/Perusahaan.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Http\Controllers\PelaporanController; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -93,9 +94,9 @@ class Perusahaan extends Model return $this->belongsTo(JenisDokIL::class, 'JenisDokILId', 'JenisDokILId'); } - public function historyKegiatan() + public function refhistoryKegiatan() { - return $this->belongsTo(HistoryKegiatan::class, 'HistoryKegiatanId', 'HistoryKegiatanId'); + return $this->belongsTo(RefHistoryKegiatan::class, 'RefHistoryKegiatanId', 'RefHistoryKegiatanId'); } @@ -104,4 +105,8 @@ class Perusahaan extends Model return $this->hasMany(HistoryPerusahaan::class, 'PerusahaanId', 'PerusahaanId'); } + public function pelaporan() + { + return $this->belongsTo(PelaporanController::class, 'PelaporanId', 'PelaporanId'); + } } diff --git a/app/Models/PetugasTps.php b/app/Models/PetugasTps.php new file mode 100644 index 0000000..8bda7cb --- /dev/null +++ b/app/Models/PetugasTps.php @@ -0,0 +1,30 @@ +belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/RefCerobong.php b/app/Models/RefCerobong.php new file mode 100644 index 0000000..3b3f21f --- /dev/null +++ b/app/Models/RefCerobong.php @@ -0,0 +1,42 @@ +belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/RefCerobongParameter.php b/app/Models/RefCerobongParameter.php new file mode 100644 index 0000000..438e798 --- /dev/null +++ b/app/Models/RefCerobongParameter.php @@ -0,0 +1,30 @@ +belongsTo(RefCerobong::class, 'RefCerobongId', 'RefCerobongId'); + } +} diff --git a/app/Models/RefHistoryKegiatan.php b/app/Models/RefHistoryKegiatan.php new file mode 100644 index 0000000..e638ea4 --- /dev/null +++ b/app/Models/RefHistoryKegiatan.php @@ -0,0 +1,23 @@ +hasMany(RefIpalParameter::class, 'RefIpalId', 'RefIpalId'); + } +} diff --git a/app/Models/RefIpalParameter.php b/app/Models/RefIpalParameter.php new file mode 100644 index 0000000..19e608b --- /dev/null +++ b/app/Models/RefIpalParameter.php @@ -0,0 +1,34 @@ +belongsTo(RefIpal::class, 'RefIpalId', 'RefIpalId'); + } +} diff --git a/app/Models/RefLog.php b/app/Models/RefLog.php new file mode 100644 index 0000000..4a7c43e --- /dev/null +++ b/app/Models/RefLog.php @@ -0,0 +1,19 @@ +hasMany(Verifikasi::class, 'RefPelaporanId', 'RefPelaporanId'); + } +} diff --git a/app/Models/Spl_AL.php b/app/Models/Spl_AL.php new file mode 100644 index 0000000..214bf29 --- /dev/null +++ b/app/Models/Spl_AL.php @@ -0,0 +1,30 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/Spl_BS.php b/app/Models/Spl_BS.php new file mode 100644 index 0000000..fab9b22 --- /dev/null +++ b/app/Models/Spl_BS.php @@ -0,0 +1,27 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/Spl_KDM.php b/app/Models/Spl_KDM.php new file mode 100644 index 0000000..70a9b2d --- /dev/null +++ b/app/Models/Spl_KDM.php @@ -0,0 +1,26 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/Spl_LB3.php b/app/Models/Spl_LB3.php new file mode 100644 index 0000000..8f82450 --- /dev/null +++ b/app/Models/Spl_LB3.php @@ -0,0 +1,31 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/Spl_LP.php b/app/Models/Spl_LP.php new file mode 100644 index 0000000..5153509 --- /dev/null +++ b/app/Models/Spl_LP.php @@ -0,0 +1,27 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/Spl_SB.php b/app/Models/Spl_SB.php new file mode 100644 index 0000000..2200bdb --- /dev/null +++ b/app/Models/Spl_SB.php @@ -0,0 +1,30 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/Spl_STB.php b/app/Models/Spl_STB.php new file mode 100644 index 0000000..56256b7 --- /dev/null +++ b/app/Models/Spl_STB.php @@ -0,0 +1,27 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/Stb.php b/app/Models/Stb.php new file mode 100644 index 0000000..58aa9ba --- /dev/null +++ b/app/Models/Stb.php @@ -0,0 +1,32 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/SumberSampah.php b/app/Models/SumberSampah.php new file mode 100644 index 0000000..0b37256 --- /dev/null +++ b/app/Models/SumberSampah.php @@ -0,0 +1,26 @@ +belongsTo(Perusahaan::class, 'PerusahaanId', 'PerusahaanId'); + } +} diff --git a/app/Models/System.php b/app/Models/System.php new file mode 100644 index 0000000..cbbe94d --- /dev/null +++ b/app/Models/System.php @@ -0,0 +1,20 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } +} diff --git a/app/Models/UdaraAmbienBakuMutu.php b/app/Models/UdaraAmbienBakuMutu.php new file mode 100644 index 0000000..56312e9 --- /dev/null +++ b/app/Models/UdaraAmbienBakuMutu.php @@ -0,0 +1,31 @@ +belongsTo(UdaraAmbienParameter::class, 'UdaraAmbienParameterId', 'UdaraAmbienParameterId'); + } +} diff --git a/app/Models/UdaraAmbienParameter.php b/app/Models/UdaraAmbienParameter.php new file mode 100644 index 0000000..6c3f8c9 --- /dev/null +++ b/app/Models/UdaraAmbienParameter.php @@ -0,0 +1,27 @@ +hasMany(UdaraAmbienBakuMutu::class, 'UdaraAmbienParameterId', 'UdaraAmbienParameterId'); + } +} diff --git a/app/Models/Verifikasi.php b/app/Models/Verifikasi.php new file mode 100644 index 0000000..7f7adc5 --- /dev/null +++ b/app/Models/Verifikasi.php @@ -0,0 +1,39 @@ +belongsTo(Pelaporan::class, 'PelaporanId', 'PelaporanId'); + } + + /** + * Relasi ke model RefPelaporan. + */ + public function refPelaporan() + { + return $this->belongsTo(RefPelaporan::class, 'RefPelaporanId', 'RefPelaporanId'); + } +} diff --git a/composer.json b/composer.json index 23e9cb1..3adef04 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ "laravel/framework": "^11.0", "laravel/sanctum": "^4.0", "laravel/tinker": "^2.9", + "league/flysystem-aws-s3-v3": "^3.29", "spatie/laravel-permission": "6.4.0", "tightenco/ziggy": "^2.0" }, diff --git a/composer.lock b/composer.lock index 2b584e4..942554f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,159 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "953cea45b540b8469800ed81d3f1fba6", + "content-hash": "e092b6f6aa930da1b1a2e88395649a47", "packages": [ + { + "name": "aws/aws-crt-php", + "version": "v1.2.7", + "source": { + "type": "git", + "url": "https://github.com/awslabs/aws-crt-php.git", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e", + "reference": "d71d9906c7bb63a28295447ba12e74723bd3730e", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35||^5.6.3||^9.5", + "yoast/phpunit-polyfills": "^1.0" + }, + "suggest": { + "ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality." + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "AWS SDK Common Runtime Team", + "email": "aws-sdk-common-runtime@amazon.com" + } + ], + "description": "AWS Common Runtime for PHP", + "homepage": "https://github.com/awslabs/aws-crt-php", + "keywords": [ + "amazon", + "aws", + "crt", + "sdk" + ], + "support": { + "issues": "https://github.com/awslabs/aws-crt-php/issues", + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7" + }, + "time": "2024-10-18T22:15:13+00:00" + }, + { + "name": "aws/aws-sdk-php", + "version": "3.343.14", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "8bb5b542b28c4538b44de4335396e77bf9fbedf6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/8bb5b542b28c4538b44de4335396e77bf9fbedf6", + "reference": "8bb5b542b28c4538b44de4335396e77bf9fbedf6", + "shasum": "" + }, + "require": { + "aws/aws-crt-php": "^1.2.3", + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/promises": "^2.0", + "guzzlehttp/psr7": "^2.4.5", + "mtdowling/jmespath.php": "^2.8.0", + "php": ">=8.1", + "psr/http-message": "^2.0" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "composer/composer": "^2.7.8", + "dms/phpunit-arraysubset-asserts": "^0.4.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5", + "psr/cache": "^2.0 || ^3.0", + "psr/simple-cache": "^2.0 || ^3.0", + "sebastian/comparator": "^1.2.3 || ^4.0 || ^5.0", + "symfony/filesystem": "^v6.4.0 || ^v7.1.0", + "yoast/phpunit-polyfills": "^2.0" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Aws\\": "src/" + }, + "exclude-from-classmap": [ + "src/data/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "support": { + "forum": "https://github.com/aws/aws-sdk-php/discussions", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.343.14" + }, + "time": "2025-05-19T18:02:45+00:00" + }, { "name": "brick/math", "version": "0.12.1", @@ -1858,6 +2009,61 @@ }, "time": "2024-10-08T08:58:34+00:00" }, + { + "name": "league/flysystem-aws-s3-v3", + "version": "3.29.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", + "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c6ff6d4606e48249b63f269eba7fabdb584e76a9", + "reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9", + "shasum": "" + }, + "require": { + "aws/aws-sdk-php": "^3.295.10", + "league/flysystem": "^3.10.0", + "league/mime-type-detection": "^1.0.0", + "php": "^8.0.2" + }, + "conflict": { + "guzzlehttp/guzzle": "<7.0", + "guzzlehttp/ringphp": "<1.1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\AwsS3V3\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frankdejonge.nl" + } + ], + "description": "AWS S3 filesystem adapter for Flysystem.", + "keywords": [ + "Flysystem", + "aws", + "file", + "files", + "filesystem", + "s3", + "storage" + ], + "support": { + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.29.0" + }, + "time": "2024-08-17T13:10:48+00:00" + }, { "name": "league/flysystem-local", "version": "3.29.0", @@ -2064,6 +2270,72 @@ ], "time": "2024-06-28T09:40:51+00:00" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.8.0", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc", + "shasum": "" + }, + "require": { + "php": "^7.2.5 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^3.0.3", + "phpunit/phpunit": "^8.5.33" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "files": [ + "src/JmesPath.php" + ], + "psr-4": { + "JmesPath\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.8.0" + }, + "time": "2024-09-04T18:46:31+00:00" + }, { "name": "nesbot/carbon", "version": "3.8.0", @@ -8485,12 +8757,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/config/filesystems.php b/config/filesystems.php index 32114d8..354a6bf 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -13,7 +13,7 @@ return [ | */ - 'default' => env('FILESYSTEM_DISK', 'public'), + 'default' => env('FILESYSTEM_DISK', 's3'), /* |-------------------------------------------------------------------------- @@ -50,10 +50,11 @@ return [ 'secret' => env('AWS_SECRET_ACCESS_KEY'), 'region' => env('AWS_DEFAULT_REGION'), 'bucket' => env('AWS_BUCKET'), - 'url' => env('AWS_URL'), + 'url' => env('AWS_URL') . '/' . env('AWS_BUCKET'), 'endpoint' => env('AWS_ENDPOINT'), - 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), - 'throw' => false, + 'use_path_style_endpoint' => true, // Always true for Minio + 'throw' => true, // Change to true to catch errors + 'visibility' => 'public', ], ], diff --git a/database/migrations/2025_02_14_142819_create_historykegiatan_table.php b/database/migrations/2025_02_14_142819_create_historykegiatan_table.php index 651ff7a..984ff85 100644 --- a/database/migrations/2025_02_14_142819_create_historykegiatan_table.php +++ b/database/migrations/2025_02_14_142819_create_historykegiatan_table.php @@ -11,8 +11,8 @@ return new class extends Migration */ public function up(): void { - Schema::create('HistoryKegiatan', function (Blueprint $table) { - $table->id('HistoryKegiatanId'); + Schema::create('RefHistoryKegiatan', function (Blueprint $table) { + $table->id('RefHistoryKegiatanId'); $table->string('NamaHistoryKegiatan'); $table->boolean('IsPublish')->default(1); $table->softDeletes(); @@ -25,6 +25,6 @@ return new class extends Migration */ public function down(): void { - Schema::dropIfExists('HistoryKegiatan'); + Schema::dropIfExists('RefHistoryKegiatan'); } }; diff --git a/database/migrations/2025_03_03_115324_create_history_perusahaan.php b/database/migrations/2025_03_03_115324_create_history_perusahaan.php index 08afbce..225abce 100644 --- a/database/migrations/2025_03_03_115324_create_history_perusahaan.php +++ b/database/migrations/2025_03_03_115324_create_history_perusahaan.php @@ -14,7 +14,7 @@ return new class extends Migration Schema::create('HistoryPerusahaan', function (Blueprint $table) { $table->id('HistoryPerusahaanId'); $table->unsignedInteger('PerusahaanId'); - $table->unsignedInteger('HistoryKegiatanId'); + $table->unsignedInteger('RefHistoryKegiatanId'); $table->date('TanggalHistory')->comment('tanggal surat'); $table->string('NomorHistory', 100)->nullable()->comment('nomor surat'); $table->text('KeteranganHistory')->nullable(); @@ -22,7 +22,7 @@ return new class extends Migration $table->timestamps(); $table->foreign('PerusahaanId')->references('PerusahaanId')->on('Perusahaan')->onDelete('set null'); - $table->foreign('HistoryKegiatanId')->references('HistoryKegiatanId')->on('HistoryKegiatan')->onDelete('set null'); + $table->foreign('RefHistoryKegiatanId')->references('RefHistoryKegiatanId')->on('RefHistoryKegiatan')->onDelete('set null'); }); } diff --git a/database/migrations/2025_03_11_104523_create_jeniskomponen_table.php b/database/migrations/2025_03_11_104523_create_jeniskomponen_table.php new file mode 100644 index 0000000..5b24b45 --- /dev/null +++ b/database/migrations/2025_03_11_104523_create_jeniskomponen_table.php @@ -0,0 +1,28 @@ +id('JenisKomponenId'); + $table->string('NamaKomponen', 255); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('JenisKomponen'); + } +}; diff --git a/database/migrations/2025_03_11_105335_create_hasils_table.php b/database/migrations/2025_03_11_105335_create_hasils_table.php new file mode 100644 index 0000000..31715d4 --- /dev/null +++ b/database/migrations/2025_03_11_105335_create_hasils_table.php @@ -0,0 +1,29 @@ +id('HasilId'); + $table->string('NamaHasil', 255); + $table->float('NilaiHasil'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Hasil'); + } +}; diff --git a/database/migrations/2025_03_11_110153_create_group_hasils_table.php b/database/migrations/2025_03_11_110153_create_group_hasils_table.php new file mode 100644 index 0000000..ff9742e --- /dev/null +++ b/database/migrations/2025_03_11_110153_create_group_hasils_table.php @@ -0,0 +1,28 @@ +id('GroupHasilId'); + $table->unsignedInteger('HasilId'); + $table->foreign('HasilId')->references('HasilId')->on('Hasil')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('GroupHasil'); + } +}; diff --git a/database/migrations/2025_03_11_111014_create_izin_pihak_ketigas_table.php b/database/migrations/2025_03_11_111014_create_izin_pihak_ketigas_table.php new file mode 100644 index 0000000..c4c25cc --- /dev/null +++ b/database/migrations/2025_03_11_111014_create_izin_pihak_ketigas_table.php @@ -0,0 +1,28 @@ +increments('IzinPihakKetigaId'); + $table->string('NamaIzin', 100)->nullable()->comment('Nama Izin'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('IzinPihakKetiga'); + } +}; diff --git a/database/migrations/2025_03_11_113050_create_petugas_tps_table.php b/database/migrations/2025_03_11_113050_create_petugas_tps_table.php new file mode 100644 index 0000000..1d92fab --- /dev/null +++ b/database/migrations/2025_03_11_113050_create_petugas_tps_table.php @@ -0,0 +1,38 @@ +id('PetugasTpsId'); + $table->unsignedBigInteger('PerusahaanId'); + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + $table->string('NamaPetugas', 255); + $table->tinyInteger('IsDeleted'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('PetugasTps', function (Blueprint $table) { + // Menghapus foreign key terlebih dahulu sebelum menghapus tabel + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('PetugasTps'); + } +}; diff --git a/database/migrations/2025_03_11_114117_create_sumber_sampahs_table.php b/database/migrations/2025_03_11_114117_create_sumber_sampahs_table.php new file mode 100644 index 0000000..b02f540 --- /dev/null +++ b/database/migrations/2025_03_11_114117_create_sumber_sampahs_table.php @@ -0,0 +1,37 @@ +id('SumberSampahId'); + $table->unsignedInteger('PerusahaanId'); + $table->string('NamaSumber', 255)->nullable()->comment('nama dan lokasi/sumber sampah'); + $table->tinyInteger('IsDeleted'); + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('SumberSampah', function (Blueprint $table) { + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('SumberSampah'); + } +}; diff --git a/database/migrations/2025_03_11_114735_create_udara_ambien_parameters_table.php b/database/migrations/2025_03_11_114735_create_udara_ambien_parameters_table.php new file mode 100644 index 0000000..9ef1412 --- /dev/null +++ b/database/migrations/2025_03_11_114735_create_udara_ambien_parameters_table.php @@ -0,0 +1,27 @@ +id('UdaraAmbienParameterId'); + $table->string('NamaParameter', 255)->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('UdaraAmbienParameter'); + } +}; diff --git a/database/migrations/2025_03_11_114837_create_udara_ambien_baku_mutus_table.php b/database/migrations/2025_03_11_114837_create_udara_ambien_baku_mutus_table.php new file mode 100644 index 0000000..fd80a38 --- /dev/null +++ b/database/migrations/2025_03_11_114837_create_udara_ambien_baku_mutus_table.php @@ -0,0 +1,39 @@ +increments('UdaraAmbienBakuMutuId'); + $table->unsignedInteger('UdaraAmbienParameterId')->nullable(); + $table->string('WaktuPengukuran', 25)->nullable(); + $table->decimal('NilaiBaku', 8, 2)->nullable()->comment('max value: 999.999,99'); + $table->string('Satuan', 25)->nullable(); + $table->tinyInteger('SistemPengukuran')->unsigned()->default(1)->comment('1=Aktif Kontinu, 2=Aktif Manual'); + + $table->foreign('UdaraAmbienParameterId') + ->references('UdaraAmbienParameterId') + ->on('UdaraAmbienParameter') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('UdaraAmbienBakuMutu', function (Blueprint $table) { + $table->dropForeign(['UdaraAmbienParameterId']); + }); + Schema::dropIfExists('UdaraAmbienBakuMutu'); + } +}; diff --git a/database/migrations/2025_03_11_115340_create_indikator_kdms_table.php b/database/migrations/2025_03_11_115340_create_indikator_kdms_table.php new file mode 100644 index 0000000..d74e18e --- /dev/null +++ b/database/migrations/2025_03_11_115340_create_indikator_kdms_table.php @@ -0,0 +1,27 @@ +id('IndikatorKdmId'); + $table->string('NamaIndikator', 255); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('IndikatorKdm'); + } +}; diff --git a/database/migrations/2025_03_11_131404_create_verifikasis_table.php b/database/migrations/2025_03_11_131404_create_verifikasis_table.php new file mode 100644 index 0000000..85e433b --- /dev/null +++ b/database/migrations/2025_03_11_131404_create_verifikasis_table.php @@ -0,0 +1,53 @@ +id('VerifikasiId'); + $table->unsignedInteger('PelaporanId'); + $table->unsignedInteger('RefPelaporanId'); + $table->tinyInteger('Verif'); + $table->dateTime('Tanggal'); + $table->integer('Oleh'); + + // Membuat index + $table->index('PelaporanId', 'Index_PelaporanId'); + $table->index('RefPelaporanId', 'Index_RefPelaporanId'); + + // Menambahkan foreign key untuk relasi dengan tabel Pelaporan + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + // Menambahkan foreign key untuk relasi dengan tabel RefPelaporan + $table->foreign('RefPelaporanId') + ->references('RefPelaporanId') + ->on('RefPelaporan') + ->onDelete('cascade'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Verifikasi', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['RefPelaporanId']); + }); + Schema::dropIfExists('Verifikasi'); + } +}; diff --git a/database/migrations/2025_03_11_131639_create_ref_pelaporans_table.php b/database/migrations/2025_03_11_131639_create_ref_pelaporans_table.php new file mode 100644 index 0000000..9952443 --- /dev/null +++ b/database/migrations/2025_03_11_131639_create_ref_pelaporans_table.php @@ -0,0 +1,29 @@ +id('RefPelaporanId'); + $table->string('NamaPelaporan', 255); + $table->string('Keterangan', 255); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('RefPelaporan'); + } +}; diff --git a/database/migrations/2025_03_11_132907_create_choices_l_p_s_table.php b/database/migrations/2025_03_11_132907_create_choices_l_p_s_table.php new file mode 100644 index 0000000..cfeb30e --- /dev/null +++ b/database/migrations/2025_03_11_132907_create_choices_l_p_s_table.php @@ -0,0 +1,39 @@ +id('ChoicesLPId'); + $table->unsignedInteger('KomponenId')->nullable()->comment('id dari komponen'); + $table->string('Nama', 100)->nullable(); + + // Menambahkan foreign key untuk relasi dengan tabel Komponen + $table->foreign('KomponenId') + ->references('KomponenId') + ->on('Komponen') + ->onDelete('cascade'); + $table->timestamps(); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('ChoicesLP', function (Blueprint $table) { + $table->dropForeign(['KomponenId']); + }); + Schema::dropIfExists('ChoicesLP'); + } +}; diff --git a/database/migrations/2025_03_11_133006_create_tanda_terimas_table.php b/database/migrations/2025_03_11_133006_create_tanda_terimas_table.php new file mode 100644 index 0000000..5ca1f60 --- /dev/null +++ b/database/migrations/2025_03_11_133006_create_tanda_terimas_table.php @@ -0,0 +1,46 @@ +id('TandaTerimaId'); + $table->unsignedInteger('PelaporanId'); + $table->string('Dokumen', 255)->nullable(); + $table->string('Email', 255)->nullable(); + $table->dateTime('TanggalKirim')->nullable(); + $table->integer('Oleh')->nullable(); + $table->enum('Del', ['y', 'n'])->default('n'); + $table->string('Parameter', 100)->nullable(); + + // Membuat index untuk kolom PelaporanId + $table->index('PelaporanId', 'Indexing_PelaporanId'); + + // Menambahkan foreign key untuk relasi dengan tabel Pelaporan + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('TandaTerima', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('TandaTerima'); + } +}; diff --git a/database/migrations/2025_03_11_134310_create_komponens_table.php b/database/migrations/2025_03_11_134310_create_komponens_table.php new file mode 100644 index 0000000..68f97c2 --- /dev/null +++ b/database/migrations/2025_03_11_134310_create_komponens_table.php @@ -0,0 +1,58 @@ +id('KomponenId'); + $table->unsignedInteger('RefPelaporanId'); + $table->unsignedInteger('JenisKomponenId'); + $table->unsignedInteger('GroupHasilId')->nullable(); + $table->string('Kode', 45); + $table->string('Nama', 255); + $table->tinyInteger('Lampiran'); + $table->text('Info')->nullable(); + $table->decimal('Bobot', 5, 2)->nullable(); + + // Menambahkan foreign key untuk relasi dengan tabel RefPelaporan + $table->foreign('RefPelaporanId') + ->references('RefPelaporanId') + ->on('RefPelaporan') + ->onDelete('cascade'); + + // Menambahkan foreign key untuk relasi dengan tabel JenisKomponen + $table->foreign('JenisKomponenId') + ->references('JenisKomponenId') + ->on('JenisKomponen') + ->onDelete('cascade'); + + // Menambahkan foreign key untuk relasi dengan tabel GroupHasil (opsional) + $table->foreign('GroupHasilId') + ->references('GroupHasilId') + ->on('GroupHasil') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Komponen', function (Blueprint $table) { + $table->dropForeign(['RefPelaporanId']); + $table->dropForeign(['JenisKomponenId']); + $table->dropForeign(['GroupHasilId']); + }); + Schema::dropIfExists('Komponen'); + } +}; diff --git a/database/migrations/2025_03_11_134747_create_catatans_table.php b/database/migrations/2025_03_11_134747_create_catatans_table.php new file mode 100644 index 0000000..ded5dd5 --- /dev/null +++ b/database/migrations/2025_03_11_134747_create_catatans_table.php @@ -0,0 +1,51 @@ +id('CatatanId'); + $table->unsignedInteger('PelaporanId'); + $table->unsignedInteger('RefPelaporanId'); + $table->text('IsiCatatan')->nullable(); + $table->text('Evaluasi')->nullable(); + + // Menambahkan index untuk kolom PelaporanId dan RefPelaporanId + $table->index('PelaporanId', 'IndexCatatan_PelaporanId'); + $table->index('RefPelaporanId', 'IndexCatatan_RefPelaporanId'); + + // Menambahkan foreign key untuk relasi dengan tabel Pelaporan + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + // Menambahkan foreign key untuk relasi dengan tabel RefPelaporan + $table->foreign('RefPelaporanId') + ->references('RefPelaporanId') + ->on('RefPelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Catatan', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['RefPelaporanId']); + }); + Schema::dropIfExists('Catatan'); + } +}; diff --git a/database/migrations/2025_03_11_135840_create_ref_cerobongs_table.php b/database/migrations/2025_03_11_135840_create_ref_cerobongs_table.php new file mode 100644 index 0000000..7f725da --- /dev/null +++ b/database/migrations/2025_03_11_135840_create_ref_cerobongs_table.php @@ -0,0 +1,56 @@ +increments('RefCerobongId'); + $table->unsignedInteger('PerusahaanId'); + $table->string('Kode', 45)->nullable(); + $table->string('Nama', 255)->nullable(); + $table->string('SumberEmisi', 255)->nullable(); + $table->string('JenisBahanBakar', 255)->nullable(); + $table->string('Konsumsi', 255)->nullable(); + $table->string('Bentuk', 255)->nullable(); + $table->float('Tinggi')->nullable(); + $table->float('Diameter')->nullable(); + $table->float('Posisi')->nullable(); + $table->string('JenisPengendali', 255)->nullable(); + $table->integer('JamOperasional')->nullable(); + // Karena Laravel tidak mendukung tipe SET, gunakan ENUM sebagai gantinya + $table->enum('Del', ['y', 'n']); + $table->float('Kapasitas')->nullable(); + $table->string('SatuanKapasitas', 255)->nullable(); + $table->double('Lintang')->nullable()->comment('lintang in decimal degree'); + $table->double('Bujur')->nullable()->comment('bujur in decimal degree'); + + // Membuat index untuk kolom PerusahaanId + $table->index('PerusahaanId', 'Indexing_PerusahaanId'); + + // Menambahkan foreign key untuk relasi dengan tabel Perusahaan + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('RefCerobong', function (Blueprint $table) { + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('RefCerobong'); + } +}; diff --git a/database/migrations/2025_03_11_135933_create_ref_cerobong_parameters_table.php b/database/migrations/2025_03_11_135933_create_ref_cerobong_parameters_table.php new file mode 100644 index 0000000..f7cfc85 --- /dev/null +++ b/database/migrations/2025_03_11_135933_create_ref_cerobong_parameters_table.php @@ -0,0 +1,44 @@ +increments('RefCerobongParameterId'); + $table->unsignedInteger('RefCerobongId'); + $table->string('Nama', 255)->nullable(); + $table->string('Satuan', 255)->nullable(); + $table->enum('BakuMutuJenis', ['Angka Tunggal', 'Rentang Angka', 'Positif/Negatif', 'Tanpa Baku Mutu']); + $table->string('BakuMutuNilai1', 45); + $table->string('BakuMutuNilai2', 45)->nullable(); + $table->enum('Del', ['y', 'n']); + + $table->index('RefCerobongId', 'Index_RefCerobongId'); + + $table->foreign('RefCerobongId') + ->references('RefCerobongId') + ->on('RefCerobong') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('RefCerobongParameter', function (Blueprint $table) { + $table->dropForeign(['RefCerobongId']); + }); + Schema::dropIfExists('RefCerobongParameter'); + } +}; diff --git a/database/migrations/2025_03_11_140738_create_cerobongs_table.php b/database/migrations/2025_03_11_140738_create_cerobongs_table.php new file mode 100644 index 0000000..1da6df4 --- /dev/null +++ b/database/migrations/2025_03_11_140738_create_cerobongs_table.php @@ -0,0 +1,64 @@ +id('CerobongId'); + $table->unsignedInteger('PelaporanId'); + $table->unsignedInteger('RefCerobongId'); + $table->string('Kode', 45)->nullable(); + $table->string('Nama', 255)->nullable(); + $table->string('SumberEmisi', 255)->nullable(); + $table->string('JenisBahanBakar', 255)->nullable(); + $table->string('Konsumsi', 255)->nullable(); + $table->string('Bentuk', 255)->nullable(); + $table->float('Tinggi')->nullable(); + $table->float('Diameter')->nullable(); + $table->float('Posisi')->nullable(); + $table->string('JenisPengendali', 255)->nullable(); + $table->float('JamOperasional')->nullable(); + $table->float('Kapasitas')->nullable(); + $table->string('SatuanKapasitas', 255)->nullable(); + $table->double('Lintang')->nullable()->comment('lintang in decimal degree'); + $table->double('Bujur')->nullable()->comment('bujur in decimal degree'); + + // Menambahkan index + $table->index('PelaporanId', 'IndexCerobong_PelaporanId'); + $table->index('RefCerobongId', 'IndexCerobong_RefCerobongId'); + + // Menambahkan foreign key untuk relasi dengan tabel Pelaporan + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + // Menambahkan foreign key untuk relasi dengan tabel RefCerobong + $table->foreign('RefCerobongId') + ->references('RefCerobongId') + ->on('RefCerobong') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Cerobong', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['RefCerobongId']); + }); + Schema::dropIfExists('Cerobong'); + } +}; diff --git a/database/migrations/2025_03_11_141240_create_cerobong_parameters_table.php b/database/migrations/2025_03_11_141240_create_cerobong_parameters_table.php new file mode 100644 index 0000000..33fcbbc --- /dev/null +++ b/database/migrations/2025_03_11_141240_create_cerobong_parameters_table.php @@ -0,0 +1,52 @@ +id('CerobongParameterId'); + $table->unsignedInteger('CerobongId'); + $table->unsignedInteger('RefCerobongParameterId'); + $table->string('Nama', 255)->nullable(); + $table->string('Satuan', 255)->nullable(); + $table->enum('BakuMutuJenis', ['Angka Tunggal', 'Rentang Angka', 'Positif/Negatif', 'Tanpa Baku Mutu']); + $table->string('BakuMutuNilai1', 45); + $table->string('BakuMutuNilai2', 45)->nullable(); + $table->enum('Del', ['y', 'n']); + + $table->index('CerobongId', 'Index_CerobongId'); + $table->index('RefCerobongParameterId', 'Index_RefCerobongParameterId'); + + $table->foreign('CerobongId') + ->references('CerobongId') + ->on('Cerobong') + ->onDelete('cascade'); + + $table->foreign('RefCerobongParameterId') + ->references('RefCerobongParameterId') + ->on('RefCerobongParameter') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('CerobongParameter', function (Blueprint $table) { + $table->dropForeign(['CerobongId']); + $table->dropForeign(['RefCerobongParameterId']); + }); + Schema::dropIfExists('CerobongParameter'); + } +}; diff --git a/database/migrations/2025_03_11_142008_create_evaluasis_table.php b/database/migrations/2025_03_11_142008_create_evaluasis_table.php new file mode 100644 index 0000000..06ff4b0 --- /dev/null +++ b/database/migrations/2025_03_11_142008_create_evaluasis_table.php @@ -0,0 +1,45 @@ +id('EvaluasiId'); + $table->unsignedInteger('PelaporanId'); + $table->string('DokumenEval', 255)->nullable(); + $table->unsignedInteger('TipeDokumen')->default(0)->comment('0 = Surat Evaluasi SKL, 1 = SE Status Mutu, 2 = SE Lainnya'); + $table->string('Email', 255)->nullable(); + $table->dateTime('TanggalKirim')->nullable(); + $table->integer('Oleh')->nullable(); + + $table->index('PelaporanId', 'IndexEvaluasi_PelaporanId'); + + // Menambahkan foreign key untuk relasi dengan tabel Pelaporan + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Evaluasi', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Evaluasi'); + } +}; diff --git a/database/migrations/2025_03_11_144245_create_group_perusahaans_table.php b/database/migrations/2025_03_11_144245_create_group_perusahaans_table.php new file mode 100644 index 0000000..7a4c69a --- /dev/null +++ b/database/migrations/2025_03_11_144245_create_group_perusahaans_table.php @@ -0,0 +1,50 @@ +id('GroupPerusahaanId'); + // Kolom UserId merujuk pada id di tabel users + $table->unsignedInteger('UserId'); + // Kolom PermissionId merujuk pada id di tabel permissions + $table->unsignedInteger('PerusahaanId'); + + // Menambahkan foreign key untuk relasi ke tabel users + $table->foreign('UserId') + ->references('id') + ->on('users') + ->onDelete('cascade'); + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + + + + $table->timestamps(); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('GroupPerusahaan', function (Blueprint $table) { + $table->dropForeign(['UserId']); + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('GroupPerusahaan'); + } +}; diff --git a/database/migrations/2025_03_11_145915_create_lokasis_table.php b/database/migrations/2025_03_11_145915_create_lokasis_table.php new file mode 100644 index 0000000..7293f67 --- /dev/null +++ b/database/migrations/2025_03_11_145915_create_lokasis_table.php @@ -0,0 +1,47 @@ +id('LokasiId'); + $table->unsignedInteger('PerusahaanId'); + $table->string('Nama', 255); + $table->double('Lintang')->nullable()->comment('lintang in decimal degree'); + $table->double('Bujur')->nullable()->comment('bujur in decimal degree'); + $table->tinyInteger('Tipe')->unsigned()->default(0)->comment('0=kebisingan ambien, 1=udara ambien'); + // Karena Laravel tidak mendukung tipe SET, kita gunakan ENUM sebagai gantinya + $table->enum('BakuMutuJenis', ['Angka Tunggal', 'Rentang Angka', 'Positif/Negatif']); + $table->string('BakuMutuNilai1', 45); + $table->string('BakuMutuNilai2', 45)->nullable(); + $table->enum('Del', ['y', 'n']); + + $table->index('PerusahaanId', 'IndexLokasi_PerusahaanId'); + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + $table->timestamps(); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Lokasi', function (Blueprint $table) { + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('Lokasi'); + } +}; diff --git a/database/migrations/2025_03_12_085831_create_ref_logs_table.php b/database/migrations/2025_03_12_085831_create_ref_logs_table.php new file mode 100644 index 0000000..ac85807 --- /dev/null +++ b/database/migrations/2025_03_12_085831_create_ref_logs_table.php @@ -0,0 +1,28 @@ +id('RefLog'); + $table->string('Nama', 100); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('RefLog'); + } +}; diff --git a/database/migrations/2025_03_12_090136_create_systems_table.php b/database/migrations/2025_03_12_090136_create_systems_table.php new file mode 100644 index 0000000..9746aea --- /dev/null +++ b/database/migrations/2025_03_12_090136_create_systems_table.php @@ -0,0 +1,29 @@ +id('SystemId'); + $table->string('Nama', 100); + $table->string('Val', 255); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('System'); + } +}; diff --git a/database/migrations/2025_03_12_090557_create_spl__a_l_s_table.php b/database/migrations/2025_03_12_090557_create_spl__a_l_s_table.php new file mode 100644 index 0000000..a5208ad --- /dev/null +++ b/database/migrations/2025_03_12_090557_create_spl__a_l_s_table.php @@ -0,0 +1,41 @@ +id('Spl_AL_Id'); + $table->unsignedInteger('PelaporanId'); + $table->float('Diuji')->nullable(); + $table->float('Melebihi')->nullable(); + $table->float('NilaiSpl')->nullable(); + + $table->index('PelaporanId', 'IndexSPLAL_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Spl_AL', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Spl_AL'); + } +}; diff --git a/database/migrations/2025_03_12_093430_create_spl__b_s_table.php b/database/migrations/2025_03_12_093430_create_spl__b_s_table.php new file mode 100644 index 0000000..3987099 --- /dev/null +++ b/database/migrations/2025_03_12_093430_create_spl__b_s_table.php @@ -0,0 +1,42 @@ +id('Spl_BS_Id'); + $table->unsignedInteger('PelaporanId'); + $table->tinyInteger('Tipe')->unsigned()->default(0)->comment('0=kebisingan ambien, 1=udara ambien'); + $table->float('Lokasi')->nullable(); + $table->float('Melebihi')->nullable(); + $table->float('NilaiSpl')->nullable(); + + $table->index('PelaporanId', 'IndexSPLBS_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Spl_BS', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Spl_BS'); + } +}; diff --git a/database/migrations/2025_03_12_093915_create_spl__k_d_m_s_table.php b/database/migrations/2025_03_12_093915_create_spl__k_d_m_s_table.php new file mode 100644 index 0000000..5183abc --- /dev/null +++ b/database/migrations/2025_03_12_093915_create_spl__k_d_m_s_table.php @@ -0,0 +1,41 @@ +id('Spl_KDM_Id'); + $table->unsignedInteger('PelaporanId'); + $table->float('Iya')->nullable(); + $table->float('Jumlah')->nullable(); + $table->float('NilaiSpl')->nullable(); + + $table->index('PelaporanId', 'IndexSPLKDM_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Spl_KDM', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Spl_KDM'); + } +}; diff --git a/database/migrations/2025_03_12_094106_create_spl__l_b3_s_table.php b/database/migrations/2025_03_12_094106_create_spl__l_b3_s_table.php new file mode 100644 index 0000000..2e9b60a --- /dev/null +++ b/database/migrations/2025_03_12_094106_create_spl__l_b3_s_table.php @@ -0,0 +1,47 @@ +id('Spl_LB3_Id'); + $table->unsignedInteger('PelaporanId'); + $table->float('Timbulan'); + $table->float('Perlakukan'); + $table->float('Residu'); + $table->float('BelumTerkelola'); + $table->float('Sisa'); + $table->string('Kinerja', 45); + $table->float('NilaiSpl'); + $table->tinyInteger('Status')->unsigned()->default(1) + ->comment('1=Ada Pengelolaan, 2=Tidak ada Pengelolaan, 3=Tidak ada Limbah'); + + $table->index('PelaporanId', 'IndexSPLLB3_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Spl_LB3', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Spl_LB3'); + } +}; diff --git a/database/migrations/2025_03_12_094200_create_spl__l_p_s_table.php b/database/migrations/2025_03_12_094200_create_spl__l_p_s_table.php new file mode 100644 index 0000000..b3d80ae --- /dev/null +++ b/database/migrations/2025_03_12_094200_create_spl__l_p_s_table.php @@ -0,0 +1,42 @@ +id('Spl_LP_Id'); + $table->unsignedInteger('PelaporanId'); + $table->float('Timbulan'); + $table->float('Diangkut'); + $table->float('Pengolahan')->nullable(); + $table->float('NilaiSpl'); + + $table->index('PelaporanId', 'IndexSPLLP_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Spl_LP', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Spl_LP'); + } +}; diff --git a/database/migrations/2025_03_12_094305_create_spl__l_b_s_table.php b/database/migrations/2025_03_12_094305_create_spl__l_b_s_table.php new file mode 100644 index 0000000..7115fbc --- /dev/null +++ b/database/migrations/2025_03_12_094305_create_spl__l_b_s_table.php @@ -0,0 +1,45 @@ +id('Spl_SB_Id'); + $table->unsignedInteger('PelaporanId'); + $table->float('BensinJumlah'); + $table->float('BensinUji'); + $table->float('BensinLulus'); + $table->float('DieselJumlah'); + $table->float('DieselUji'); + $table->float('DieselLulus'); + $table->float('NilaiSpl'); + + $table->index('PelaporanId', 'IndexSPLSB_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Spl_SB', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Spl_SB'); + } +}; diff --git a/database/migrations/2025_03_12_094620_create_spl__s_t_b_s_table.php b/database/migrations/2025_03_12_094620_create_spl__s_t_b_s_table.php new file mode 100644 index 0000000..f4218e7 --- /dev/null +++ b/database/migrations/2025_03_12_094620_create_spl__s_t_b_s_table.php @@ -0,0 +1,41 @@ +id('Spl_STB_Id'); + $table->unsignedInteger('PelaporanId'); + $table->float('Diuji')->nullable(); + $table->float('Melebihi')->nullable(); + $table->float('NilaiSpl')->nullable(); + + $table->index('PelaporanId', 'IndexSPLSTB_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Spl_STB', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Spl_STB'); + } +}; diff --git a/database/migrations/2025_03_12_094731_create_stbs_table.php b/database/migrations/2025_03_12_094731_create_stbs_table.php new file mode 100644 index 0000000..ec0848b --- /dev/null +++ b/database/migrations/2025_03_12_094731_create_stbs_table.php @@ -0,0 +1,46 @@ +id('Stb_Id'); + $table->unsignedInteger('PelaporanId'); + $table->enum('EmisiStb', ['Iya', 'Tidak'])->default('Iya'); + $table->integer('Cerobong')->nullable(); + $table->string('SuratPernyataan', 255)->nullable(); + $table->dateTime('TanggalUnggah')->nullable(); + $table->tinyInteger('Verifikasi')->nullable(); + $table->dateTime('TanggalVerifikasi')->nullable(); + $table->string('Keterangan', 255)->nullable(); + $table->unsignedInteger('Verifikator')->nullable(); + + $table->index('PelaporanId', 'IndexSTB_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Stb', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Stb'); + } +}; diff --git a/database/migrations/2025_03_12_100109_create_ref_ipals_table.php b/database/migrations/2025_03_12_100109_create_ref_ipals_table.php new file mode 100644 index 0000000..1fc7a25 --- /dev/null +++ b/database/migrations/2025_03_12_100109_create_ref_ipals_table.php @@ -0,0 +1,53 @@ +id('RefIpalId'); + $table->unsignedInteger('PerusahaanId'); + $table->string('NomorIpal', 100); + $table->string('NamaIpal', 255); + $table->string('DokumenIpal', 255); + $table->date('IzinTerbit'); + $table->date('IzinHabis'); + $table->string('SumberLimbah', 255); + $table->float('KapasitasIpal'); + $table->string('Teknologi', 255); + $table->string('BadanAir', 255); + $table->float('DebitMaksimum', 7, 2)->nullable(); + $table->double('Lintang')->nullable()->comment('lintang in decimal degree'); + $table->double('Bujur')->nullable()->comment('bujur in decimal degree'); + $table->enum('Del', ['y', 'n']); + + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + + $table->index('PerusahaanId', 'Index_PerusahaanId'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('RefIpal', function (Blueprint $table) { + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('RefIpal'); + } +}; diff --git a/database/migrations/2025_03_12_100200_create_ref_ipal_parameters_table.php b/database/migrations/2025_03_12_100200_create_ref_ipal_parameters_table.php new file mode 100644 index 0000000..b07ff15 --- /dev/null +++ b/database/migrations/2025_03_12_100200_create_ref_ipal_parameters_table.php @@ -0,0 +1,45 @@ +id('RefIpalParameterId'); + $table->unsignedInteger('RefIpalId'); + $table->string('NamaParameter', 45); + $table->string('Satuan', 255); + $table->enum('BakuMutuJenis', ['Angka Tunggal', 'Rentang Angka', 'Positif/Negatif', 'Tanpa Baku Mutu']); + $table->string('BakuMutuNilai1', 45); + $table->string('BakuMutuNilai2', 45)->nullable(); + $table->float('BatasEmisi', 14, 8)->nullable(); + $table->enum('Del', ['y', 'n']); + + $table->foreign('RefIpalId') + ->references('RefIpalId') + ->on('RefIpal') + ->onDelete('cascade'); + + $table->index('RefIpalId', 'Index_RefIpalId'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('RefIpalParameter', function (Blueprint $table) { + $table->dropForeign(['RefIpalId']); + }); + Schema::dropIfExists('RefIpalParameter'); + } +}; diff --git a/database/migrations/2025_03_12_103025_create_ipals_table.php b/database/migrations/2025_03_12_103025_create_ipals_table.php new file mode 100644 index 0000000..8bd5361 --- /dev/null +++ b/database/migrations/2025_03_12_103025_create_ipals_table.php @@ -0,0 +1,59 @@ +id('IpalId'); + $table->unsignedInteger('PelaporanId'); + $table->unsignedInteger('RefIpalId'); + $table->string('Nomor', 100); + $table->string('Nama', 255); + $table->string('Lampiran', 255); + $table->date('IzinTerbit'); + $table->date('IzinHabis'); + $table->string('Sumber', 255); + $table->float('Kapasitas'); + $table->string('Teknologi', 255); + $table->string('BadanAir', 255); + $table->float('DebitMaksimum', 7, 2)->nullable(); + $table->double('Lintang')->nullable()->comment('lintang in decimal degree'); + $table->double('Bujur')->nullable()->comment('bujur in decimal degree'); + + $table->index('PelaporanId', 'IndexPelaporan_PelaporanId'); + $table->index('RefIpalId', 'IndexRefIpal_RefIpalId'); + + // Foreign key untuk relasi (pastikan tabel Pelaporan dan RefIpal sudah ada) + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + $table->foreign('RefIpalId') + ->references('RefIpalId') + ->on('RefIpal') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Ipal', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['RefIpalId']); + }); + Schema::dropIfExists('Ipal'); + } +}; diff --git a/database/migrations/2025_03_12_103208_create_ipal_parameters_table.php b/database/migrations/2025_03_12_103208_create_ipal_parameters_table.php new file mode 100644 index 0000000..41a985c --- /dev/null +++ b/database/migrations/2025_03_12_103208_create_ipal_parameters_table.php @@ -0,0 +1,54 @@ +id('IpalParameterId'); + $table->unsignedInteger('IpalId'); + $table->unsignedInteger('RefIpalParameterId'); + $table->string('Nama', 255); + $table->string('Satuan', 255); + // Menggunakan enum sebagai pengganti tipe SET + $table->enum('BakuMutuJenis', ['Angka Tunggal', 'Rentang Angka', 'Positif/Negatif', 'Tanpa Baku Mutu'])->nullable(); + $table->string('BakuMutuNilai1', 45); + $table->string('BakuMutuNilai2', 45)->nullable(); + $table->float('BatasEmisi', 14, 8)->nullable(); + + $table->index('IpalId', 'IndexIpal_IpalId'); + $table->index('RefIpalParameterId', 'IndexRefIpalParameter_RefIpalParameterId'); + + // Foreign key untuk relasi + $table->foreign('IpalId') + ->references('IpalId') + ->on('Ipal') + ->onDelete('cascade'); + + $table->foreign('RefIpalParameterId') + ->references('RefIpalParameterId') + ->on('RefIpalParameter') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('IpalParameter', function (Blueprint $table) { + $table->dropForeign(['IpalId']); + $table->dropForeign(['RefIpalParameterId']); + }); + Schema::dropIfExists('IpalParameter'); + } +}; diff --git a/database/migrations/2025_03_12_110050_create_hasil_uji_a_l_s_table.php b/database/migrations/2025_03_12_110050_create_hasil_uji_a_l_s_table.php new file mode 100644 index 0000000..756419a --- /dev/null +++ b/database/migrations/2025_03_12_110050_create_hasil_uji_a_l_s_table.php @@ -0,0 +1,59 @@ +id('HasilUjiALId'); + $table->unsignedInteger('IpalId'); + $table->year('Tahun'); + $table->unsignedInteger('PerusahaanId'); + $table->unsignedInteger('IpalParameterId'); + $table->string('Bulan', 45); + $table->string('Nilai', 45)->nullable(); + $table->float('Debit', 7, 2)->nullable(); + $table->float('BebanEmisi', 12, 8)->nullable(); + + $table->index('IpalId', 'Index_IpalId'); + $table->index('PerusahaanId', 'index_PerusahaanId'); + $table->index('IpalParameterId', 'Index_IpalParameterId'); + + $table->foreign('IpalId') + ->references('IpalId') + ->on('Ipal') + ->onDelete('cascade'); + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + + $table->foreign('IpalParameterId') + ->references('IpalParameterId') + ->on('IpalParameter') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HasilUjiAL', function (Blueprint $table) { + $table->dropForeign(['IpalId']); + $table->dropForeign(['PerusahaanId']); + $table->dropForeign(['IpalParameterId']); + }); + Schema::dropIfExists('HasilUjiAL'); + } +}; diff --git a/database/migrations/2025_03_12_111134_create_hasil_uji_b_s_table.php b/database/migrations/2025_03_12_111134_create_hasil_uji_b_s_table.php new file mode 100644 index 0000000..9586d6e --- /dev/null +++ b/database/migrations/2025_03_12_111134_create_hasil_uji_b_s_table.php @@ -0,0 +1,54 @@ +increments('HasilUjiBSId'); + $table->unsignedInteger('PelaporanId'); + $table->unsignedInteger('LokasiId'); + $table->string('Nama', 255); + $table->double('Lintang')->nullable()->comment('lintang in decimal degree'); + $table->double('Bujur')->nullable()->comment('lintang in decimal degree'); + // Menggunakan ENUM sebagai pengganti tipe SET + $table->enum('BakuMutuJenis', ['Angka Tunggal', 'Rentang Angka', 'Positif/Negatif']); + $table->string('BakuMutuNilai1', 45); + $table->string('BakuMutuNilai2', 45)->nullable(); + $table->string('HasilUji', 45)->nullable(); + + $table->index('PelaporanId', 'IndexHasilUjiBS_PelaporanId'); + $table->index('LokasiId', 'Index_LokasiId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + $table->foreign('LokasiId') + ->references('LokasiId') + ->on('Lokasi') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HasilUjiBS', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['LokasiId']); + }); + Schema::dropIfExists('HasilUjiBS'); + } +}; diff --git a/database/migrations/2025_03_12_112219_create_hasil_uji_k_d_m_s_table.php b/database/migrations/2025_03_12_112219_create_hasil_uji_k_d_m_s_table.php new file mode 100644 index 0000000..13e6edf --- /dev/null +++ b/database/migrations/2025_03_12_112219_create_hasil_uji_k_d_m_s_table.php @@ -0,0 +1,49 @@ +id('HasilUjiKDMId'); + // Jika method year() belum tersedia, gunakan: $table->string('Tahun', 4); + $table->year('Tahun'); + $table->unsignedInteger('PerusahaanId'); + $table->unsignedInteger('IndikatorKdmId'); + $table->string('Bulan', 255); + $table->enum('Nilai', ['Iya', 'Tidak']); + + $table->index('PerusahaanId', 'IndexHasilUjiKDM_PerusahaanId'); + + $table->foreign('IndikatorKdmId') + ->references('IndikatorKdmId') + ->on('IndikatorKdm') + ->onDelete('cascade'); + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HasilUjiKDM', function (Blueprint $table) { + $table->dropForeign(['IndikatorKdmId']); + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('HasilUjiKDM'); + } +}; diff --git a/database/migrations/2025_03_12_113149_create_hasil_uji_l_p_s_table.php b/database/migrations/2025_03_12_113149_create_hasil_uji_l_p_s_table.php new file mode 100644 index 0000000..0014269 --- /dev/null +++ b/database/migrations/2025_03_12_113149_create_hasil_uji_l_p_s_table.php @@ -0,0 +1,63 @@ +id('HasilUjiLPId'); + $table->unsignedInteger('PelaporanId'); + $table->integer('Tahun'); + $table->unsignedInteger('PerusahaanId'); + $table->enum('Sampah', [ + 'Volume Timbulan Sampah', + 'Volume Pengolahan Sampah', + 'Volume Sampah Diangkut' + ]); + $table->enum('Jenis', [ + '', + 'Organik', + 'Anorganik', + 'Mudah Terurai', + 'Daur Ulang', + 'Residu' + ])->default(''); + $table->string('Bulan', 100); + $table->float('Nilai'); + + $table->index('PelaporanId', 'IndexHasilUjiPL_PelaporanId'); + $table->index('PerusahaanId', 'IndexHasilUjiPL_PerusahaanId'); + + // Menambahkan foreign key (pastikan tabel Pelaporan dan Perusahaan sudah ada) + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HasilUjiLP', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('HasilUjiLP'); + } +}; diff --git a/database/migrations/2025_03_12_113859_create_hasil_uji_s_t_b_s_table.php b/database/migrations/2025_03_12_113859_create_hasil_uji_s_t_b_s_table.php new file mode 100644 index 0000000..29a214b --- /dev/null +++ b/database/migrations/2025_03_12_113859_create_hasil_uji_s_t_b_s_table.php @@ -0,0 +1,57 @@ +id('HasilUjiSTBId'); + $table->unsignedInteger('CerobongId'); + $table->unsignedInteger('CerobongParameterId'); + $table->year('Tahun')->nullable(); + $table->unsignedInteger('PerusahaanId'); + $table->string('Semester1', 45)->nullable(); + $table->string('Semester2', 45)->nullable(); + + $table->index('CerobongId', 'IndexHasilUjiSTB_CerobongId'); + $table->index('CerobongParameterId', 'IndexHasilUjiSTB_CerobongParameterId'); + $table->index('PerusahaanId', 'IndexHasilUjiSTB_PerusahaanId'); + + $table->foreign('CerobongId') + ->references('CerobongId') + ->on('Cerobong') + ->onDelete('cascade'); + + $table->foreign('CerobongParameterId') + ->references('CerobongParameterId') + ->on('CerobongParameter') + ->onDelete('cascade'); + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HasilUjiSTB', function (Blueprint $table) { + $table->dropForeign(['CerobongId']); + $table->dropForeign(['CerobongParameterId']); + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('HasilUjiSTB'); + } +}; diff --git a/database/migrations/2025_03_12_114247_create_hasil_uji_u_a_s_table.php b/database/migrations/2025_03_12_114247_create_hasil_uji_u_a_s_table.php new file mode 100644 index 0000000..8ccf189 --- /dev/null +++ b/database/migrations/2025_03_12_114247_create_hasil_uji_u_a_s_table.php @@ -0,0 +1,49 @@ +id('HasilUjiUAId'); + $table->unsignedInteger('PelaporanId')->nullable(); + $table->unsignedInteger('LokasiId')->nullable(); + $table->string('Nama', 255)->nullable()->comment('nama lokasi'); + $table->double('Lintang')->nullable()->comment('lintang in decimal degree'); + $table->double('Bujur')->nullable()->comment('lintang in decimal degree'); + + $table->index('PelaporanId', 'IndexHasilUjiUA_PelaporanId'); + $table->index('LokasiId', 'IndexHasilUjiUA_LokasiId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + $table->foreign('LokasiId') + ->references('LokasiId') + ->on('Lokasi') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HasilUjiUA', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['LokasiId']); + }); + Schema::dropIfExists('HasilUjiUA'); + } +}; diff --git a/database/migrations/2025_03_12_114818_create_hasil_uji_u_a_paramters_table.php b/database/migrations/2025_03_12_114818_create_hasil_uji_u_a_paramters_table.php new file mode 100644 index 0000000..cba1872 --- /dev/null +++ b/database/migrations/2025_03_12_114818_create_hasil_uji_u_a_paramters_table.php @@ -0,0 +1,45 @@ +id('HasilUjiUAParameterId'); + $table->unsignedInteger('HasilUjiUAId')->nullable(); + $table->unsignedInteger('UdaraAmbienBakuMutuId')->nullable(); + $table->tinyInteger('Pengujian')->unsigned()->default(1)->comment('0=False (Tidak diuji), 1=True (Diuji)'); + $table->decimal('Nilai', 8, 2)->nullable()->comment('max value: 999.999,99'); + + $table->foreign('HasilUjiUAId') + ->references('HasilUjiUAId') + ->on('HasilUjiUA') + ->onDelete('cascade'); + + $table->foreign('UdaraAmbienBakuMutuId') + ->references('UdaraAmbienBakuMutuId') + ->on('UdaraAmbienBakuMutu') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HasilUjiUAParameter', function (Blueprint $table) { + $table->dropForeign(['HasilUjiUAId']); + $table->dropForeign(['UdaraAmbienBakuMutuId']); + }); + Schema::dropIfExists('HasilUjiUAParameter'); + } +}; diff --git a/database/migrations/2025_03_12_133721_create_history_kegiatans_table.php b/database/migrations/2025_03_12_133721_create_history_kegiatans_table.php new file mode 100644 index 0000000..5dfa3be --- /dev/null +++ b/database/migrations/2025_03_12_133721_create_history_kegiatans_table.php @@ -0,0 +1,47 @@ +id('HistoryKegiatanId'); + $table->unsignedInteger('PerusahaanId'); + $table->unsignedInteger('RefHistoryKegiatanId'); + $table->date('Tanggal')->comment('tanggal surat'); + $table->string('Nomor', 100)->nullable()->comment('nomor surat'); + $table->text('Keterangan')->nullable(); + $table->string('Dokumen', 255); + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + + $table->foreign('RefHistoryKegiatanId') + ->references('RefHistoryKegiatanId') + ->on('RefHistoryKegiatan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('HistoryKegiatan', function (Blueprint $table) { + $table->dropForeign(['PerusahaanId']); + $table->dropForeign(['RefHistoryKegiatanId']); + }); + Schema::dropIfExists('HistoryKegiatan'); + } +}; diff --git a/database/migrations/2025_03_12_134128_create_komunals_table.php b/database/migrations/2025_03_12_134128_create_komunals_table.php new file mode 100644 index 0000000..55952d4 --- /dev/null +++ b/database/migrations/2025_03_12_134128_create_komunals_table.php @@ -0,0 +1,39 @@ +id('KomunalId'); + $table->unsignedInteger('PelaporanId'); + $table->enum('Tersambung', ['Iya', 'Tidak']); + + $table->index('PelaporanId', 'IndexKomunal_PelaporanId'); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('Komunal', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + }); + Schema::dropIfExists('Komunal'); + } +}; diff --git a/database/migrations/2025_03_12_134251_create_pelaporan_dates_table.php b/database/migrations/2025_03_12_134251_create_pelaporan_dates_table.php new file mode 100644 index 0000000..043d65e --- /dev/null +++ b/database/migrations/2025_03_12_134251_create_pelaporan_dates_table.php @@ -0,0 +1,44 @@ +id('PelaporanDateId'); + $table->unsignedInteger('PelaporanId')->nullable(); + $table->unsignedInteger('RefPelaporanId'); + $table->date('ReportDate')->nullable(); + + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + $table->foreign('RefPelaporanId') + ->references('RefPelaporanId') + ->on('RefPelaporan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('PelaporanDate', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['RefPelaporanId']); + }); + Schema::dropIfExists('PelaporanDate'); + } +}; diff --git a/database/migrations/2025_03_12_141439_create_nilai_komponens_table.php b/database/migrations/2025_03_12_141439_create_nilai_komponens_table.php new file mode 100644 index 0000000..fd97923 --- /dev/null +++ b/database/migrations/2025_03_12_141439_create_nilai_komponens_table.php @@ -0,0 +1,74 @@ +id('NilaiKomponenId'); + $table->unsignedInteger('PelaporanId'); + $table->unsignedInteger('KomponenId'); + $table->unsignedInteger('HasilId'); + $table->float('Nilai')->nullable(); + $table->tinyInteger('Verifikasi')->nullable(); + $table->dateTime('TanggalVerifikasi')->nullable(); + $table->text('Catatan')->nullable(); + $table->text('Keterangan')->nullable(); + $table->unsignedInteger('Verifikator')->nullable(); + $table->unsignedInteger('IpalId')->nullable(); + $table->unsignedInteger('CerobongId')->nullable(); + + $table->index('PelaporanId', 'IndexNilaiKomponen_PelaporanId'); + $table->index('KomponenId', 'IndexNilaiKomponen_KomponenId'); + + // Foreign key constraints (pastikan tabel yang dirujuk sudah ada) + $table->foreign('PelaporanId') + ->references('PelaporanId') + ->on('Pelaporan') + ->onDelete('cascade'); + + $table->foreign('KomponenId') + ->references('KomponenId') + ->on('Komponen') + ->onDelete('cascade'); + + $table->foreign('HasilId') + ->references('HasilId') + ->on('Hasil') + ->onDelete('cascade'); + + $table->foreign('IpalId') + ->references('IpalId') + ->on('Ipal') + ->onDelete('cascade'); + + $table->foreign('CerobongId') + ->references('CerobongId') + ->on('Cerobong') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('NilaiKomponen', function (Blueprint $table) { + $table->dropForeign(['PelaporanId']); + $table->dropForeign(['KomponenId']); + $table->dropForeign(['HasilId']); + $table->dropForeign(['IpalId']); + $table->dropForeign(['CerobongId']); + }); + Schema::dropIfExists('NilaiKomponen'); + } +}; diff --git a/database/migrations/2025_03_12_142602_create_nilai_komponen_pihak_ketigas_table.php b/database/migrations/2025_03_12_142602_create_nilai_komponen_pihak_ketigas_table.php new file mode 100644 index 0000000..c92b3d4 --- /dev/null +++ b/database/migrations/2025_03_12_142602_create_nilai_komponen_pihak_ketigas_table.php @@ -0,0 +1,49 @@ +id('NilaiKomponenPihakKetigaId'); + $table->unsignedInteger('NilaiKomponenId')->nullable()->comment('id dari nilai komponen'); + $table->string('Nama', 255)->nullable()->comment('nama pihak ketiga'); + $table->unsignedInteger('IzinPihakKetigaId')->nullable()->comment('id dari refizin_pihakketiga, dalam bentuk json'); + $table->decimal('Jumlah', 7, 2)->unsigned()->nullable()->comment('jumlah limbah B3, max 99.999,99 ton'); + $table->tinyInteger('Satuan')->unsigned()->default(1)->comment('1=kg, 2=ton'); + $table->tinyInteger('IsDeleted')->unsigned()->default(0)->comment('0=false, 1=true'); + + // Menambahkan foreign key untuk kolom NilaiKomponenId + $table->foreign('NilaiKomponenId') + ->references('NilaiKomponenId') + ->on('NilaiKomponen') + ->onDelete('cascade'); + + $table->foreign('IzinPihakKetigaId') + ->references('IzinPihakKetigaId') + ->on('IzinPihakKetiga') + ->onDelete('cascade'); + + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('NilaiKomponenPihakKetiga', function (Blueprint $table) { + $table->dropForeign(['NilaiKomponenId']); + $table->dropForeign(['IzinPihakKetigaId']); + }); + Schema::dropIfExists('NilaiKomponenPihakKetiga'); + } +}; diff --git a/database/migrations/2025_03_12_143216_create_lampiran_a_l_s_table.php b/database/migrations/2025_03_12_143216_create_lampiran_a_l_s_table.php new file mode 100644 index 0000000..ce502e9 --- /dev/null +++ b/database/migrations/2025_03_12_143216_create_lampiran_a_l_s_table.php @@ -0,0 +1,50 @@ +id('LampiranALId'); + $table->unsignedInteger('IpalId'); + $table->year('Tahun'); + $table->unsignedInteger('PerusahaanId'); + $table->string('Bulan', 45); + $table->string('Dokumen', 255); + $table->dateTime('TanggalUnggah'); + + $table->index('IpalId', 'IndexLampiranAL_IpalId'); + $table->index('PerusahaanId', 'IndexLampiranAL_PerusahaanId'); + + $table->foreign('IpalId') + ->references('IpalId') + ->on('Ipal') + ->onDelete('cascade'); + + $table->foreign('PerusahaanId') + ->references('PerusahaanId') + ->on('Perusahaan') + ->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('LampiranAL', function (Blueprint $table) { + $table->dropForeign(['IpalId']); + $table->dropForeign(['PerusahaanId']); + }); + Schema::dropIfExists('LampiranAL'); + } +}; diff --git a/database/migrations/2025_05_15_093426_create_lampiran.php b/database/migrations/2025_05_15_093426_create_lampiran.php new file mode 100644 index 0000000..6c5ec42 --- /dev/null +++ b/database/migrations/2025_05_15_093426_create_lampiran.php @@ -0,0 +1,37 @@ +id('LampiranId'); + $table->unsignedInteger('PelaporanId'); + $table->integer('IpalId')->nullable(); + $table->unsignedInteger('KomponenId'); + $table->string('Dokumen', 255); + $table->dateTime('TanggalUnggah'); + $table->unsignedInteger('CerobongId')->nullable(); + + // Indexes + $table->index('PelaporanId', 'index_PelaporanId'); + $table->index('KomponenId', 'index_KomponenId'); + }); + + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('Lampiran'); + } +}; diff --git a/database/seeders/PerusahaanSeeder.php b/database/seeders/PerusahaanSeeder.php new file mode 100644 index 0000000..d94b658 --- /dev/null +++ b/database/seeders/PerusahaanSeeder.php @@ -0,0 +1,84 @@ +toArray(); + + // Make sure we have Kelurahan records + if (empty($kelurahanIds)) { + throw new \Exception("No Kelurahan records found. Please seed the Kelurahan table first."); + } + + // Get available JenisKegiatan IDs from the database + $jenisKegiatanIds = \App\Models\JenisKegiatan::pluck('JenisKegiatanId')->toArray(); + + // Make sure we have JenisKegiatan records + if (empty($jenisKegiatanIds)) { + throw new \Exception("No JenisKegiatan records found. Please seed the JenisKegiatan table first."); + } + + // Get available Verifikator IDs from the database + $verifikatorIds = \App\Models\Verifikator::pluck('VerifikatorId')->toArray(); + + // Make sure we have Verifikator records + if (empty($verifikatorIds)) { + throw new \Exception("No Verifikator records found. Please seed the Verifikator table first."); + } + + for ($i = 0; $i < 100; $i++) { + $data[] = [ + 'NomorInduk' => $faker->unique()->numerify('P########'), + 'JenisKegiatanId' => $faker->randomElement($jenisKegiatanIds), + 'NamaPerusahaan' => $faker->company, + 'Alamat' => $faker->address, + 'KelurahanId' => $faker->randomElement($kelurahanIds), + 'KodePos' => $faker->postcode, + 'Telepon' => $faker->phoneNumber, + 'JenisDokILId' => $faker->numberBetween(1, 3), + 'VerifikatorId' => $faker->randomElement($verifikatorIds), + 'IsPublish' => $faker->boolean, + 'Bujur' => $faker->longitude, + 'CPNama' => $faker->name, + 'CPTelepon' => $faker->phoneNumber, + 'ILNomor' => $faker->bothify('IL-####/???/####'), + 'ILTanggal' => $faker->date(), + 'JenisDokILId' => $faker->numberBetween(1, 3), + 'VerifikatorId' => $faker->numberBetween(1, 10), + 'IsPublish' => $faker->boolean, + 'ILDokumen' => $faker->randomElement(['dokumen1.pdf', 'dokumen2.pdf', 'dokumen3.pdf']), + 'ReportLocked' => $faker->boolean, + 'created_at' => $timestamp, + 'updated_at' => $timestamp, + ]; + + // Insert in chunks to avoid memory issues + if (($i + 1) % 100 === 0 || $i === 99) { + Perusahaan::insert($data); + $data = []; + } + } + + // Insert any remaining records + if (!empty($data)) { + Perusahaan::insert($data); + } + } +} diff --git a/package-lock.json b/package-lock.json index ae59cc1..6ca54b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "packages": { "": { "dependencies": { + "@hookform/resolvers": "^5.0.1", "@iconify/react": "^5.2.0", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.1.1", @@ -12,14 +13,14 @@ "@radix-ui/react-collapsible": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-label": "^2.1.6", "@radix-ui/react-navigation-menu": "^1.2.4", "@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.0", - "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-slot": "^1.2.2", "@radix-ui/react-switch": "^1.1.2", "@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-toast": "^1.2.6", @@ -43,6 +44,7 @@ "react-animate-height": "^3.2.3", "react-apexcharts": "^1.7.0", "react-day-picker": "^8.10.1", + "react-hook-form": "^7.56.2", "react-i18next": "^15.4.0", "react-perfect-scrollbar": "^1.5.8", "react-popper": "^2.3.0", @@ -58,7 +60,7 @@ "tinymce": "^7.6.1", "vaul": "^1.1.2", "ziggy-js": "^2.5.0", - "zod": "^3.23.8" + "zod": "^3.24.4" }, "devDependencies": { "@headlessui/react": "^1.4.2", @@ -948,6 +950,18 @@ "react-dom": "^16 || ^17 || ^18" } }, + "node_modules/@hookform/resolvers": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-5.0.1.tgz", + "integrity": "sha512-u/+Jp83luQNx9AdyW2fIPGY6Y7NG68eN2ZW8FOJYL+M0i4s49+refdJdOp/A9n9HFQtQs3HIDHQvX3ZET2o7YA==", + "license": "MIT", + "dependencies": { + "@standard-schema/utils": "^0.3.0" + }, + "peerDependencies": { + "react-hook-form": "^7.55.0" + } + }, "node_modules/@iconify/react": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@iconify/react/-/react-5.2.0.tgz", @@ -1313,6 +1327,24 @@ } } }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collapsible": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.2.tgz", @@ -1552,6 +1584,24 @@ } } }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-direction": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", @@ -1682,12 +1732,35 @@ } }, "node_modules/@radix-ui/react-label": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.1.tgz", - "integrity": "sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw==", + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.1.6.tgz", + "integrity": "sha512-S/hv1mTlgcPX2gCTJrWuTjSXf7ER3Zf7zWGtOprxhIIY93Qin3n5VgNA0Ez9AgrK/lEtlYgzLd4f5x6AVar4Yw==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.0.1" + "@radix-ui/react-primitive": "2.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.2.tgz", + "integrity": "sha512-uHa+l/lKfxuDD2zjN/0peM/RhhSmRjr5YWdk/37EnSv1nJ88uvG85DPexSm8HdFQROd2VdERJ6ynXbkCFi+APw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.2" }, "peerDependencies": { "@types/react": "*", @@ -1989,6 +2062,24 @@ } } }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.1.tgz", @@ -2157,6 +2248,24 @@ } } }, + "node_modules/@radix-ui/react-progress/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-roving-focus": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz", @@ -2442,6 +2551,24 @@ } } }, + "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-select/node_modules/@radix-ui/react-visually-hidden": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz", @@ -2489,12 +2616,12 @@ } }, "node_modules/@radix-ui/react-slot": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", - "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.2.tgz", + "integrity": "sha512-y7TBO4xN4Y94FvcWIOIh18fM4R1A8S4q1jhoz4PNzOoHsFcN8pogcFmZrTYAm4F9VRUrWP/Mw7xSKybIeRI+CQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.1" + "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", @@ -2506,6 +2633,21 @@ } } }, + "node_modules/@radix-ui/react-slot/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-switch": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.2.tgz", @@ -2645,6 +2787,24 @@ } } }, + "node_modules/@radix-ui/react-tabs/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-toast": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.2.6.tgz", @@ -2779,6 +2939,24 @@ } } }, + "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-toast/node_modules/@radix-ui/react-visually-hidden": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.2.tgz", @@ -3290,6 +3468,12 @@ "win32" ] }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, "node_modules/@svgdotjs/svg.draggable.js": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.5.tgz", @@ -6486,6 +6670,22 @@ "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", "license": "MIT" }, + "node_modules/react-hook-form": { + "version": "7.56.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.56.2.tgz", + "integrity": "sha512-vpfuHuQMF/L6GpuQ4c3ZDo+pRYxIi40gQqsCmmfUBwm+oqvBhKhwghCuj2o00YCgSfU6bR9KC/xnQGWm3Gr08A==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-i18next": { "version": "15.4.0", "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.0.tgz", @@ -7837,9 +8037,9 @@ } }, "node_modules/zod": { - "version": "3.24.1", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", - "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "version": "3.24.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.4.tgz", + "integrity": "sha512-OdqJE9UDRPwWsrHjLN2F8bPxvwJBK22EHLWtanu0LSYr5YqzsaaW3RMgmjwr8Rypg5k+meEJdSPXJZXE/yqOMg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index 94f21d0..831d788 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "vite": "^5.0" }, "dependencies": { + "@hookform/resolvers": "^5.0.1", "@iconify/react": "^5.2.0", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.1.1", @@ -32,14 +33,14 @@ "@radix-ui/react-collapsible": "^1.1.1", "@radix-ui/react-dialog": "^1.1.6", "@radix-ui/react-dropdown-menu": "^2.1.2", - "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-label": "^2.1.6", "@radix-ui/react-navigation-menu": "^1.2.4", "@radix-ui/react-popover": "^1.1.6", "@radix-ui/react-progress": "^1.1.2", "@radix-ui/react-scroll-area": "^1.0.5", "@radix-ui/react-select": "^2.1.6", "@radix-ui/react-separator": "^1.1.0", - "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-slot": "^1.2.2", "@radix-ui/react-switch": "^1.1.2", "@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-toast": "^1.2.6", @@ -63,6 +64,7 @@ "react-animate-height": "^3.2.3", "react-apexcharts": "^1.7.0", "react-day-picker": "^8.10.1", + "react-hook-form": "^7.56.2", "react-i18next": "^15.4.0", "react-perfect-scrollbar": "^1.5.8", "react-popper": "^2.3.0", @@ -78,6 +80,6 @@ "tinymce": "^7.6.1", "vaul": "^1.1.2", "ziggy-js": "^2.5.0", - "zod": "^3.23.8" + "zod": "^3.24.4" } } diff --git a/resources/js/components/AL/ALTable.tsx b/resources/js/components/AL/ALTable.tsx new file mode 100644 index 0000000..15e8c10 --- /dev/null +++ b/resources/js/components/AL/ALTable.tsx @@ -0,0 +1,416 @@ +import React from "react"; +import { Button } from "@/components/ui/button"; +import { + Tooltip, + TooltipTrigger, + TooltipContent, +} from "@/components/ui/tooltip"; +import { CircleHelp } from "lucide-react"; +import { + Select, + SelectTrigger, + SelectContent, + SelectItem, + SelectValue, +} from "@/components/ui/select"; + +interface KomponenData { + id: number; + nama: string; + kode: string; + nilai: number; + hasil?: { + id: number; + nama: string; + nilai: number; + }[]; + nama_refhasil?: string; + verifikasi?: boolean; + keterangan?: string; + lampiran?: boolean; +} + +interface JenisData { + nama: string; + komponen: Record; +} + +interface ALTableProps { + dataTable: Record; + nilaiKomponen: Record; + nilaiSyaratTeknis: Record; + nilai_A6: number; + nilai_A7: number; + idmcpelaporan: number; + idrefpelaporan: number; + rowspan_1: number; + spl: number; + spl_2: number; + editable: boolean; + onUpdateNilai: (kode: string, nilai: number) => void; + onOpenLampiranModal: (kode: string, idrefkomponen: number) => void; + onOpenSplModal: () => void; +} + +const ALTable: React.FC = ({ + dataTable, + nilaiKomponen, + nilaiSyaratTeknis, + nilai_A6, + nilai_A7, + idmcpelaporan, + idrefpelaporan, + rowspan_1, + spl, + spl_2, + editable, + onUpdateNilai, + onOpenLampiranModal, + onOpenSplModal, +}) => { + const [sklNilai, setSklNilai] = React.useState(0); + const komponenHide = ["A1", "A2", "A3", "A4", "A5"]; + const daftarNilai = React.useRef>({}); + + React.useEffect(() => { + // Initialize daftarNilai + const nilai: Record = {}; + Object.entries(dataTable).forEach(([_noJenis, jenis]) => { + Object.entries(jenis.komponen).forEach( + ([kodeKomponen, komponen]) => { + if (kodeKomponen !== "SK") { + if (komponenHide.includes(kodeKomponen)) { + nilai[kodeKomponen.toLowerCase()] = parseFloat( + nilaiSyaratTeknis[kodeKomponen].toFixed(2) + ); + } else if (kodeKomponen === "A6") { + nilai[kodeKomponen.toLowerCase()] = parseFloat( + nilai_A6.toFixed(2) + ); + } else if (kodeKomponen === "A7") { + nilai[kodeKomponen.toLowerCase()] = parseFloat( + nilai_A7.toFixed(2) + ); + } else { + const val = nilaiKomponen[kodeKomponen]; + nilai[kodeKomponen.toLowerCase()] = val + ? parseFloat(val.nilai) + : 0; + } + } + } + ); + }); + daftarNilai.current = nilai; + calculateSklNilai(); + }, [dataTable, nilaiKomponen, nilaiSyaratTeknis, nilai_A6, nilai_A7]); + + const calculateSklNilai = () => { + const kelompok1 = ["a1", "a2", "a3", "a4"]; + const kelompok2 = ["a5"]; + const kelompok3 = ["a6", "a7", "a8", "a9", "a10"]; + let total1 = 0; + let total2 = 0; + let total3 = 0; + + for (const [key, value] of Object.entries(daftarNilai.current)) { + if (typeof value === "number") { + if (kelompok1.includes(key)) { + total1 += value; + } else if (kelompok2.includes(key)) { + total2 += value; + } else if (kelompok3.includes(key)) { + total3 += value; + } + } + } + + const newSklNilai = + (15 * (total1 / kelompok1.length)) / 100 + + (15 * (total2 / kelompok2.length)) / 100 + + (70 * (total3 / kelompok3.length)) / 100; + + setSklNilai(parseFloat(newSklNilai.toFixed(2))); + }; + + const handleHasilChange = (komponen: KomponenData, hasilId: number) => { + if (!editable) return; + + const hasil = komponen.hasil?.find( + (h) => h.id === parseInt(hasilId.toString()) + ); + if (hasil) { + daftarNilai.current[komponen.kode.toLowerCase()] = hasil.nilai; + onUpdateNilai(komponen.kode, hasil.nilai); + calculateSklNilai(); + } + }; + + return ( + + + + + + + + + + + + + + + + + + + + + + + {Object.entries(dataTable).map(([noJenis, jenis]) => ( + + {noJenis && ( + + + + + + + + )} + + {Object.entries(jenis.komponen).map( + ([kodeKomponen, komponen]) => + kodeKomponen !== "SK" && ( + + + + {/* Kolom Hasil */} + + + {/* Kolom Nilai */} + + + {/* Kolom Lampiran */} + + + {/* Kolom Verifikasi */} + + + {/* Kolom Keterangan */} + + + ) + )} + + ))} + + + + + + + + + + +
+ No + + Komponen + + Hasil + + Nilai + + Lampiran + + Verifikasi + + Keterangan +
+ I + + + Nilai tingkat ketaatan pengelolaan air limbah (SKL + AL) (%) + + + + {sklNilai} +
+ {noJenis}. {jenis.nama} +
+ {kodeKomponen}. {komponen.nama} + + {komponen.hasil && + !komponenHide.includes( + kodeKomponen + ) ? ( + + ) : null} + + {komponenHide.includes(kodeKomponen) + ? parseFloat( + ( + nilaiSyaratTeknis[ + kodeKomponen + ] || 0 + ).toFixed(2) + ) + : kodeKomponen === "A6" + ? parseFloat( + nilai_A6.toFixed(2) + ) + : kodeKomponen === "A7" + ? parseFloat( + nilai_A7.toFixed(2) + ) + : nilaiKomponen[kodeKomponen] + ? nilaiKomponen[kodeKomponen] + .nilai + : 0} + + {komponen.lampiran && + !komponenHide.includes( + kodeKomponen + ) && ( + + )} + + {!komponenHide.includes( + kodeKomponen + ) && + nilaiKomponen[kodeKomponen] + ?.verifikasi !== + undefined && + (nilaiKomponen[kodeKomponen] + ?.verifikasi ? ( + + Approved + + ) : ( + + Not Approved + + ))} + + {!komponenHide.includes( + kodeKomponen + ) && + nilaiKomponen[kodeKomponen] + ?.keterangan} +
+ II + + + Nilai tingkat pemenuhan baku mutu air limbah{" "} + * (SPBMAL) (%) + + + {parseFloat(spl.toString())} + + +
+ ); +}; + +export default ALTable; diff --git a/resources/js/components/AL/LampiranModal.tsx b/resources/js/components/AL/LampiranModal.tsx new file mode 100644 index 0000000..1e2f056 --- /dev/null +++ b/resources/js/components/AL/LampiranModal.tsx @@ -0,0 +1,282 @@ +import React, { useState, useEffect } from "react"; +import { Button } from "@/components/ui/button"; +import { Upload, X, File, Trash2 } from "lucide-react"; +import axios from "axios"; + +interface LampiranModalProps { + isOpen: boolean; + onClose: () => void; + idMcIpal: number; + kodeKomponen: string; + namaKomponen: string; + editable: boolean; +} + +interface FileItem { + name: string; + size: number; + path: string; +} + +const LampiranModal: React.FC = ({ + isOpen, + onClose, + idMcIpal, + kodeKomponen, + namaKomponen, + editable, +}) => { + const [files, setFiles] = useState([]); + const [isUploading, setIsUploading] = useState(false); + const [uploadProgress, setUploadProgress] = useState(0); + const [dragActive, setDragActive] = useState(false); + + useEffect(() => { + if (isOpen) { + loadFiles(); + } + }, [isOpen, idMcIpal, kodeKomponen]); + + const loadFiles = async () => { + try { + const response = await axios.post( + "/pelaporan/al/lampiran-syarat-teknis/list-files", + { + idmcipal: idMcIpal, + kode_komponen: kodeKomponen, + } + ); + setFiles(response.data); + } catch (error) { + console.error("Error loading files:", error); + } + }; + + const handleDrag = (e: React.DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + + if (e.type === "dragenter" || e.type === "dragover") { + setDragActive(true); + } else if (e.type === "dragleave") { + setDragActive(false); + } + }; + + const handleDrop = (e: React.DragEvent) => { + e.preventDefault(); + e.stopPropagation(); + setDragActive(false); + + if (!editable) return; + + if (e.dataTransfer.files && e.dataTransfer.files.length > 0) { + handleFiles(e.dataTransfer.files); + } + }; + + const handleFileInput = (e: React.ChangeEvent) => { + if (!editable) return; + + if (e.target.files && e.target.files.length > 0) { + handleFiles(e.target.files); + } + }; + + const handleFiles = async (fileList: FileList) => { + setIsUploading(true); + setUploadProgress(0); + + const formData = new FormData(); + for (let i = 0; i < fileList.length; i++) { + formData.append("file[]", fileList[i]); + } + + try { + await axios.post( + `/pelaporan/al/lampiran-syarat-teknis/upload-file/${idMcIpal}/${kodeKomponen}`, + formData, + { + headers: { + "Content-Type": "multipart/form-data", + }, + onUploadProgress: (progressEvent) => { + if (progressEvent.total) { + const progress = Math.round( + (progressEvent.loaded * 100) / + progressEvent.total + ); + setUploadProgress(progress); + } + }, + } + ); + + loadFiles(); + } catch (error) { + console.error("Error uploading files:", error); + } finally { + setIsUploading(false); + } + }; + + const deleteFile = async (filePath: string) => { + if (!editable) return; + + try { + await axios.post( + "/pelaporan/al/lampiran-syarat-teknis/delete-file", + { + filePath, + idmcipal: idMcIpal, + kode_komponen: kodeKomponen, + } + ); + + loadFiles(); + } catch (error) { + console.error("Error deleting file:", error); + } + }; + + const formatFileSize = (bytes: number): string => { + if (bytes === 0) return "0 Bytes"; + + const k = 1024; + const sizes = ["Bytes", "KB", "MB", "GB"]; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; + }; + + if (!isOpen) return null; + + return ( +
+
+
+

+ Lampiran {kodeKomponen}: {namaKomponen} +

+ +
+ + {editable && ( +
+
+ + +
+ + {isUploading && ( +
+

+ Mengunggah: {uploadProgress}% +

+
+
+
+
+ )} +
+ )} + +
+

+ File yang diunggah: +

+ + {files.length === 0 ? ( +

+ Belum ada file yang diunggah +

+ ) : ( +
+ {files.map((file, index) => ( +
+
+ +
+

+ {file.name} +

+

+ {formatFileSize(file.size)} +

+
+
+
+ + Lihat + + {editable && ( + + )} +
+
+ ))} +
+ )} +
+ +
+ +
+
+
+ ); +}; + +export default LampiranModal; diff --git a/resources/js/components/AL/SplModal.tsx b/resources/js/components/AL/SplModal.tsx new file mode 100644 index 0000000..59fb107 --- /dev/null +++ b/resources/js/components/AL/SplModal.tsx @@ -0,0 +1,193 @@ +import React, { useState, useEffect } from "react"; +import { Button } from "@/components/ui/button"; +import { X, Info } from "lucide-react"; +import axios from "axios"; + +interface SplModalProps { + isOpen: boolean; + onClose: () => void; + idMcPelaporan: number; +} + +interface SplData { + nilai: number; + keterangan: string; + detail: { + nama_ipal: string; + parameter: string; + baku_mutu: number; + hasil_uji: number; + keterangan: string; + }[]; +} + +const SplModal: React.FC = ({ + isOpen, + onClose, + idMcPelaporan, +}) => { + const [splData, setSplData] = useState(null); + const [loading, setLoading] = useState(true); + + useEffect(() => { + if (isOpen) { + loadSplData(); + } + }, [isOpen, idMcPelaporan]); + + const loadSplData = async () => { + setLoading(true); + try { + const response = await axios.get( + `/pelaporan/al/spl/${idMcPelaporan}` + ); + setSplData(response.data); + } catch (error) { + console.error("Error loading SPL data:", error); + } finally { + setLoading(false); + } + }; + + if (!isOpen) return null; + + return ( +
+
+
+

+ Nilai Tingkat Pemenuhan Baku Mutu Air Limbah (SPBM + AL) +

+ +
+ +
+ {loading ? ( +
+
+
+ ) : splData ? ( + <> +
+ +

+ Nilai SPBMAL dihitung otomatis + berdasarkan data hasil uji yang dimasukkan. +

+
+ +
+

+ Nilai SPBMAL: +

+ + {splData.nilai.toFixed(2)}% + +
+ +

+ Detail Hasil Uji: +

+ + {splData.detail.length === 0 ? ( +

+ Belum ada data hasil uji +

+ ) : ( +
+ + + + + + + + + + + + {splData.detail.map( + (item, index) => ( + + + + + + + + ) + )} + +
+ IPAL + + Parameter + + Baku Mutu + + Hasil Uji + + Keterangan +
+ {item.nama_ipal} + + {item.parameter} + + {item.baku_mutu} + + + item.baku_mutu + ? "text-red-600" + : "text-green-600" + }`} + > + {item.hasil_uji} + + + {item.keterangan} +
+
+ )} + + {splData.keterangan && ( +
+

+ Keterangan: +

+

+ {splData.keterangan} +

+
+ )} + + ) : ( +
+

Data tidak tersedia

+
+ )} +
+ +
+ +
+
+
+ ); +}; + +export default SplModal; diff --git a/resources/js/components/HistoryPerusahaan/AddHistory.tsx b/resources/js/components/HistoryPerusahaan/AddHistory.tsx index 29a8bda..df4e588 100644 --- a/resources/js/components/HistoryPerusahaan/AddHistory.tsx +++ b/resources/js/components/HistoryPerusahaan/AddHistory.tsx @@ -143,7 +143,7 @@ export function DetailHistoryPerusahaanTable({ - {perusahaan.HistoryKegiatan || "-"} + {perusahaan.RefHistoryKegiatan || "-"} {perusahaan.KeteranganHistory || "-"} diff --git a/resources/js/components/Partials/Navbar.tsx b/resources/js/components/Partials/Navbar.tsx index 289fad1..08e4633 100644 --- a/resources/js/components/Partials/Navbar.tsx +++ b/resources/js/components/Partials/Navbar.tsx @@ -40,10 +40,13 @@ interface NavItemsProps { interface CustomPageProps extends InertiaPageProps { runPosts?: Post[]; errors: Record; + auth: { + user: any; + }; } const Navbar = () => { - const { runPosts = [] } = usePage().props; + const { runPosts = [], auth } = usePage().props; const [isScrolled, setIsScrolled] = useState(false); const [isDrawerOpen, setIsDrawerOpen] = useState(false); const { theme, setTheme } = useTheme(); @@ -191,10 +194,11 @@ const Navbar = () => {
- LOGIN + + {auth?.user ? "DASHBOARD" : "LOGIN"}
diff --git a/resources/js/components/Pelaporan/AL/IPAL/DataPendukungModal.tsx b/resources/js/components/Pelaporan/AL/IPAL/DataPendukungModal.tsx new file mode 100644 index 0000000..11b5f6a --- /dev/null +++ b/resources/js/components/Pelaporan/AL/IPAL/DataPendukungModal.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; + +interface DataPendukungModalProps { + open: boolean; + onClose: () => void; +} + +const DataPendukungModal: React.FC = ({ + open, + onClose, +}) => { + return ( + + + + Data Pendukung + +
+ {/* Tempatkan form atau daftar dokumen pendukung di sini */} +

Masukkan data pendukung disini...

+
+ + + +
+
+ ); +}; + +export default DataPendukungModal; diff --git a/resources/js/components/Pelaporan/AL/IPAL/HasilUjiLabModal.tsx b/resources/js/components/Pelaporan/AL/IPAL/HasilUjiLabModal.tsx new file mode 100644 index 0000000..ea3d098 --- /dev/null +++ b/resources/js/components/Pelaporan/AL/IPAL/HasilUjiLabModal.tsx @@ -0,0 +1,52 @@ +import React, { useState } from "react"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; + +interface HasilUjiLabModalProps { + open: boolean; + onClose: () => void; +} + +const HasilUjiLabModal: React.FC = ({ + open, + onClose, +}) => { + const [labResult, setLabResult] = useState(""); + + const handleSave = () => { + // Lakukan penyimpanan hasil uji lab + onClose(); + }; + + return ( + + + + Hasil Uji Lab + +
+ setLabResult(e.target.value)} + placeholder="Masukkan hasil uji lab" + /> +
+ + + + +
+
+ ); +}; + +export default HasilUjiLabModal; diff --git a/resources/js/components/Pelaporan/AL/IPAL/ModalIPAL.tsx b/resources/js/components/Pelaporan/AL/IPAL/ModalIPAL.tsx new file mode 100644 index 0000000..ab9e3e6 --- /dev/null +++ b/resources/js/components/Pelaporan/AL/IPAL/ModalIPAL.tsx @@ -0,0 +1,106 @@ +import React, { useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Form } from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { useNavigate } from "react-router-dom"; + +interface AddIpalModalProps { + isOpen: boolean; + onClose: () => void; + idPelaporan: string; +} + +const AddIpalModal: React.FC = ({ + isOpen, + onClose, + idPelaporan, +}) => { + const [nomor, setNomor] = useState(""); + const [nama, setNama] = useState(""); + + const navigate = useNavigate(); // Untuk navigasi setelah form disubmit + + // Fungsi untuk handle form submission + const handleSubmit = async (event: React.FormEvent) => { + event.preventDefault(); + + const response = await fetch( + `/pelaporan/al/ipal/add_ipal/${idPelaporan}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + nomor, + nama, + }), + } + ); + + if (response.ok) { + // Redirect atau close modal setelah berhasil simpan + onClose(); + navigate(`/admin/pelaporan/al/ipal`); // Sesuaikan dengan halaman yang diinginkan + } else { + // Menangani error atau validasi + alert("Gagal menyimpan data."); + } + }; + + return ( + !open && onClose()}> + + + + Pengelolaan Air Limbah - Instalasi Pengolah Air Limbah + + + +
+
+
+ + setNomor(e.target.value)} + required + /> +
+ +
+ + setNama(e.target.value)} + required + /> +
+
+ + + + +
+
+
+ ); +}; + +export default AddIpalModal; diff --git a/resources/js/components/Pelaporan/AL/IPAL/ParameterUjiLabModal.tsx b/resources/js/components/Pelaporan/AL/IPAL/ParameterUjiLabModal.tsx new file mode 100644 index 0000000..03f137a --- /dev/null +++ b/resources/js/components/Pelaporan/AL/IPAL/ParameterUjiLabModal.tsx @@ -0,0 +1,103 @@ +import React, { useState } from "react"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; + +interface Parameter { + id: number; + name: string; + value: string; +} + +interface ParameterUjiLabModalProps { + open: boolean; + onClose: () => void; +} + +const ParameterUjiLabModal: React.FC = ({ + open, + onClose, +}) => { + const [parameters, setParameters] = useState([]); + + const addParameter = () => { + const newParam: Parameter = { + id: Date.now(), + name: "", + value: "", + }; + setParameters([...parameters, newParam]); + }; + + const updateParameter = ( + id: number, + field: keyof Parameter, + value: string + ) => { + setParameters( + parameters.map((param) => + param.id === id ? { ...param, [field]: value } : param + ) + ); + }; + + const handleSave = () => { + // Lakukan penyimpanan data parameter uji lab + onClose(); + }; + + return ( + + + + Parameter Uji Lab + +
+ {parameters.map((param) => ( +
+ + updateParameter( + param.id, + "name", + e.target.value + ) + } + placeholder="Nama Parameter" + /> + + updateParameter( + param.id, + "value", + e.target.value + ) + } + placeholder="Nilai Parameter" + /> +
+ ))} + +
+ + + + +
+
+ ); +}; + +export default ParameterUjiLabModal; diff --git a/resources/js/components/Pelaporan/AL/IPAL/PersyaratanTeknisModal.tsx b/resources/js/components/Pelaporan/AL/IPAL/PersyaratanTeknisModal.tsx new file mode 100644 index 0000000..7c3656d --- /dev/null +++ b/resources/js/components/Pelaporan/AL/IPAL/PersyaratanTeknisModal.tsx @@ -0,0 +1,121 @@ +import React, { useState } from "react"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogFooter, +} from "@/components/ui/dialog"; +import { Button } from "@/components/ui/button"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +interface TechnicalRequirement { + id: number; + name: string; + result: number; +} + +interface PersyaratanTeknisModalProps { + open: boolean; + onClose: () => void; +} + +const PersyaratanTeknisModal: React.FC = ({ + open, + onClose, +}) => { + const initialRequirements: TechnicalRequirement[] = [ + { id: 1, name: "Instalasi pengolah air limbah", result: 0 }, + { id: 2, name: "Flowmeter", result: 0 }, + { id: 3, name: "Titik pengambilan sampel", result: 0 }, + { id: 4, name: "Saluran air limbah & air hujan terpisah", result: 0 }, + ]; + + const [requirements, setRequirements] = + useState(initialRequirements); + const [uploaded, setUploaded] = useState(false); + + const handleSelectChange = (id: number, value: string) => { + let resultValue = 0; + if (value === "ada-berfungsi") resultValue = 100; + else if (value === "ada-tidak-berfungsi") resultValue = 50; + else if (value === "tidak-ada") resultValue = 0; + + setRequirements( + requirements.map((req) => + req.id === id ? { ...req, result: resultValue } : req + ) + ); + }; + + const handleUpload = () => { + // Simulasi upload dokumen, kemudian enable dropdown + setUploaded(true); + }; + + const handleSave = () => { + // Lakukan penyimpanan data persyaratan teknis + onClose(); + }; + + return ( + + + + Persyaratan Teknis + +
+ {!uploaded && ( + + )} + {requirements.map((req) => ( +
+ {req.name} + +
+ ))} +
+ + + + +
+
+ ); +}; + +export default PersyaratanTeknisModal; diff --git a/resources/js/components/app-sidebar.tsx b/resources/js/components/app-sidebar.tsx index 37cf5ac..333934d 100644 --- a/resources/js/components/app-sidebar.tsx +++ b/resources/js/components/app-sidebar.tsx @@ -153,8 +153,8 @@ const data = { }, { title: "History Kegiatan", - url: "/admin/historykegiatan", - permissions: ["HistoryKegiatan.index"], + url: "/admin/refhistorykegiatan", + permissions: ["RefHistoryKegiatan.index"], }, { title: "Jenis Sanksi", @@ -223,14 +223,19 @@ export function AppSidebar({ ...props }: React.ComponentProps) { return menu .map((item) => { if (item.items) { - const filteredItems = item.items.filter((subItem) => - subItem.permissions - ? hasAnyPermission( - Array.isArray(subItem.permissions) - ? subItem.permissions - : Object.keys(subItem.permissions) // Pastikan selalu array - ) - : true + const filteredItems = item.items.filter( + (subItem: { + permissions?: string[] | Record; + title: string; + url: string; + }) => + subItem.permissions + ? hasAnyPermission( + Array.isArray(subItem.permissions) + ? subItem.permissions + : Object.keys(subItem.permissions) // Pastikan selalu array + ) + : true ); if (filteredItems.length > 0) { diff --git a/resources/js/components/ui/form.tsx b/resources/js/components/ui/form.tsx new file mode 100644 index 0000000..2003743 --- /dev/null +++ b/resources/js/components/ui/form.tsx @@ -0,0 +1,176 @@ +import * as React from "react" +import * as LabelPrimitive from "@radix-ui/react-label" +import { Slot } from "@radix-ui/react-slot" +import { + Controller, + FormProvider, + useFormContext, + type ControllerProps, + type FieldPath, + type FieldValues, +} from "react-hook-form" + +import { cn } from "@/lib/utils" +import { Label } from "@/components/ui/label" + +const Form = FormProvider + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +> = { + name: TName +} + +const FormFieldContext = React.createContext( + {} as FormFieldContextValue +) + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +>({ + ...props +}: ControllerProps) => { + return ( + + + + ) +} + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext) + const itemContext = React.useContext(FormItemContext) + const { getFieldState, formState } = useFormContext() + + const fieldState = getFieldState(fieldContext.name, formState) + + if (!fieldContext) { + throw new Error("useFormField should be used within ") + } + + const { id } = itemContext + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + } +} + +type FormItemContextValue = { + id: string +} + +const FormItemContext = React.createContext( + {} as FormItemContextValue +) + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const id = React.useId() + + return ( + +
+ + ) +}) +FormItem.displayName = "FormItem" + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField() + + return ( + + +
+ + + {showSkFields && ( + <> +
+ + +
+ {props.verifikasi_sk && ( + <> +
+ + + {props.verifikasi_sk} + +
+
+ +

+ {props.ket_sk} +

+
+ + )} + + )} + + + {/* Main Table */} +
+ +
+ + {/* Notes Section */} +
+ +