get('userposid'); $userId = session()->get('userid'); $certificateModel = new CertificateModel(); // 1. Mulai Query Builder $builder = $certificateModel->select(' certificates.cert_id, certificates.cert_number, certificates.cert_name, certificates.cert_type, certificates.actid, certificates.issued_date, certificates.expired_date, certificates.status, certificates.user_validation_at, certificates.spv_validation_at, certificates.manager_validation_at, activities.subject as activity_subject, CONCAT(users.firstname, " ", users.lastname) as fullname ') ->join('activities', 'activities.actid = certificates.actid', 'left') ->join('users', 'users.userid = certificates.user_id', 'left') ->where('certificates.cert_type', 'BAI'); // 2. Filter berdasarkan Role if (in_array($userPosId, [1, 3, 5])) { // Manager & IT: Tidak perlu filter tambahan (lihat semua) } else if ($userPosId == 2) { // SPV: Melihat data user yang "reportto"-nya adalah ID supervisor ini $builder->where('users.reportto', $userId); } else if ($userPosId == 4) { // TSOIVD: Hanya melihat data milik sendiri $builder->where('certificates.user_id', $userId); } else {// Role lain: Tidak diberi akses return $this->response->setJSON([]); } // 3. Eksekusi Query $allData = $builder->findAll(); if (empty($allData)) { return $this->response->setJSON([]); // Kembalikan array kosong agar frontend tidak error } return $this->response->setJSON($allData); } public function createinstallationPreview($certid = null) { // Untuk Preview Sertifikat //Melakukan search data dari database if (!$certid) { return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID is required']); } // Get certificate data Berdasarkan certid $certificate = [ 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11914', 'certname' => 'Jokoh Calibration Certificate', 'productname' => 'Jokoh', 'productnumber' => 'SN-2024-001', 'issuedate' => '2024-01-15', 'expirydate' => '2025-01-15', 'vendor' => 'Summit Calibration Lab', 'isval' => null ]; if (empty($certificate)) { // JIka Tidak Ada return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']); } return $this->previewPdf($certificate, 'installation'); // Preview PDF } // Untuk Sertifikat Maintenance [2] public function maintenanceIndex() { // Index return view('certificate_maintenance_index'); } public function getDataIndexMaintenance() { $userPosId = session()->get('userposid'); $userId = session()->get('userid'); $certificateModel = new CertificateModel(); // 1. Mulai Query Builder $builder = $certificateModel->select(' certificates.cert_id, certificates.cert_number, certificates.cert_name, certificates.cert_type, certificates.actid, certificates.issued_date, certificates.expired_date, certificates.status, certificates.user_validation_at, certificates.spv_validation_at, certificates.manager_validation_at, activities.subject as activity_subject, CONCAT(users.firstname, " ", users.lastname) as fullname ') ->join('activities', 'activities.actid = certificates.actid', 'left') ->join('users', 'users.userid = certificates.user_id', 'left') ->where('certificates.cert_type', 'MC');; // 2. Filter berdasarkan Role if (in_array($userPosId, [1, 3, 5])) { // Manager & IT: Tidak perlu filter tambahan (lihat semua) } else if ($userPosId == 2) { // SPV: Melihat data user yang "reportto"-nya adalah ID supervisor ini $builder->where('users.reportto', $userId); } else if ($userPosId == 4) { // TSOIVD: Hanya melihat data milik sendiri $builder->where('certificates.user_id', $userId); } else {// Role lain: Tidak diberi akses return $this->response->setJSON([]); } // 3. Eksekusi Query $allData = $builder->findAll(); if (empty($allData)) { return $this->response->setJSON([]); // Kembalikan array kosong agar frontend tidak error } return $this->response->setJSON($allData); } public function showDataMaintenance() { // Untuk API Get Data $certid = $this->request->getPost('certid'); if (!$certid) { return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID Not Found']); } $certificateModel = new CertificateModel(); $data = $certificateModel->select(' certificates.cert_id, certificates.cert_number, certificates.cert_name, certificates.status, activities.actid, activities.subject, productcatalog.productname, sites.sitename, products.productnumber, CASE WHEN certificates.cert_type = "MC" THEN "Maintenance" WHEN certificates.cert_type = "IC" THEN "Installation" WHEN certificates.cert_type = "UTC" THEN "User Training" WHEN certificates.cert_type = "BAI" THEN "Before After Inspection" WHEN certificates.cert_type = "BAP" THEN "Berita Acara Pengerjaan" ELSE certificates.cert_type END AS certtype, CONCAT(us.firstname, " ", us.lastname) AS username, certificates.user_validation_at, CONCAT(spv.firstname, " ", spv.lastname) AS spvname, certificates.spv_validation_at, CONCAT(mgr.firstname, " ", mgr.lastname) AS managername, certificates.manager_validation_at, certificates.issued_date, certificates.expired_date ', false) ->join('activities', 'activities.actid = certificates.actid', 'inner') ->join('products', 'products.productid = activities.productid', 'inner') ->join('productcatalog', 'productcatalog.catalogid = products.catalogid', 'inner') ->join('sites', 'sites.siteid = activities.siteid', 'left') ->join('users as us', 'us.userid = certificates.user_id', 'left') ->join('users as spv', 'spv.userid = certificates.spv_id', 'left') ->join('users as mgr', 'mgr.userid = certificates.manager_id', 'left') ->join('userposition', 'userposition.userposid = us.userposid', 'left') ->where('certificates.cert_id', $certid) ->first(); $data['issued_date'] = $data['issued_date'] ? date('d M Y', strtotime($data['issued_date'])) : null; $data['user_validation_at'] = $data['user_validation_at'] ? date('d M Y H:i', strtotime($data['user_validation_at'])) : null; $data['spv_validation_at'] = $data['spv_validation_at'] ? date('d M Y H:i', strtotime($data['spv_validation_at'])) : null; $data['manager_validation_at'] = $data['manager_validation_at'] ? date('d M Y H:i', strtotime($data['manager_validation_at'])) : null; if (empty($data)) { // Jika Tidak Ada return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']); } return $this->response->setJSON($data); } public function createMaintenancePreview($certid = null) { // Untuk Preview Sertifikat if (!$certid) { return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID Not Found']); } $certificateModel = new CertificateModel(); $data = $certificateModel->select(' certificates.cert_name, certificates.issued_date, certificates.expired_date, certificates.file_url, productalias.productaliastext as productname, sites.sitename as sitename, products.productnumber, CASE WHEN certificates.cert_type = "MC" THEN "Maintenance" WHEN certificates.cert_type = "IC" THEN "Installation" WHEN certificates.cert_type = "UTC" THEN "User Training" WHEN certificates.cert_type = "BAI" THEN "Before After Inspection" WHEN certificates.cert_type = "BAP" THEN "Berita Acara Pengerjaan" ELSE certificates.cert_type END AS cert_type, CONCAT(users.firstname, " ", users.lastname) AS fullname, userposition.texts AS user_position, certificates.issued_date, certificates.expired_date, certificates.cert_number -- Penting agar callback UUID tetap jalan ', false) ->join('users', 'users.userid = certificates.user_id', 'left') ->join('userposition', 'userposition.userposid = users.userposid', 'left') ->join('activities', 'activities.actid = certificates.actid', 'left') ->join('sites', 'sites.siteid = activities.siteid', 'left') ->join('products', 'products.productid = activities.productid', 'left') ->join('productcatalog', 'productcatalog.catalogid = products.catalogid', 'left') ->join('productalias', 'productalias.productaliasid = productcatalog.productaliasid', 'left') ->where('certificates.cert_id', $certid) ->first(); $certificate = [ 'certname' => $data['cert_name'], 'sitename' => $data['sitename'], 'certtype' => $data['cert_type'], 'fullname' => $data['fullname'], 'userposition' => $data['user_position'], 'productname' => $data['productname'], 'productnumber' => $data['productnumber'], 'issueddate' => $data['issued_date'], 'expireddate' => $data['expired_date'] ]; $builder = new Builder( writer: new PngWriter(), data: $data['file_url'], size: 120, margin: 0 ); $result = $builder->build(); $certificate['qrcode'] = $result->getDataUri(); if (empty($certificate)) { // Jika Tidak Ada return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']); } return $this->previewPdf($certificate, 'maintenance'); // Preview PDF } // Untuk Sertifikat Training [3] // public function trainingIndex() { // return view('certificate_training_index'); // } // public function getDataIndexTraining() { // // $actid = $this->request->getVar('actid'); // // Sample data - replace with actual database query // $certificates = [ // [ // 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919', // 'certname' => 'Jokoh Calibration Certificate', // 'productname' => 'Jokoh', // 'productnumber' => 'SN-2024-001', // 'issuedate' => '2024-01-15', // 'expirydate' => '2025-01-15', // 'vendor' => 'Summit Calibration Lab', // 'isval' => null // ], // [ // 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919', // 'certname' => 'Electrical Safety Test', // 'productname' => 'GE Healthcare VIVID', // 'productnumber' => 'GE-VIV-Q992', // 'issuedate' => '2024-06-12', // 'expirydate' => '2026-10-01', // 'vendor' => 'Pramita Medika Service', // 'isval' => '2026-03-01' // ] // ]; // // If no actid, return all certificates // if (empty($certificates)) { // return $this->response->setJSON(null); // } // return $this->response->setJSON($certificates); // } // public function createTrainingPreview($certid = null) { // Untuk Preview Sertifikat // //Melakukan search data dari database // if (!$certid) { // return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID is required']); // } // // Get certificate data Berdasarkan certid // $certificate = [ // 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919', // 'certname' => 'Jokoh Calibration Certificate', // 'productname' => 'Jokoh', // 'productnumber' => 'SN-2024-001', // 'issuedate' => '2024-01-15', // 'expirydate' => '2025-01-15', // 'vendor' => 'Summit Calibration Lab', // 'isval' => null // ]; // if (empty($certificate)) { // JIka Tidak Ada // return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']); // } // return $this->previewPdf($certificate, 'training'); // Preview PDF // } // Untuk Sertifikat Calibrate [4] // public function calibrateIndex() { // return view('certificate_calibrate_index'); // } // public function getDataIndexCalibrate() { // // $actid = $this->request->getVar('actid'); // // Sample data - replace with actual database query // $certificates = [ // [ // 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919', // 'certname' => 'Jokoh Calibration Certificate', // 'productname' => 'Jokoh', // 'productnumber' => 'SN-2024-001', // 'issuedate' => '2024-01-15', // 'expirydate' => '2025-01-15', // 'vendor' => 'Summit Calibration Lab', // 'isval' => null // ], // [ // 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919', // 'certname' => 'Electrical Safety Test', // 'productname' => 'GE Healthcare VIVID', // 'productnumber' => 'GE-VIV-Q992', // 'issuedate' => '2024-06-12', // 'expirydate' => '2026-10-01', // 'vendor' => 'Pramita Medika Service', // 'isval' => '2026-03-01' // ] // ]; // // If no actid, return all certificates // if (empty($certificates)) { // return $this->response->setJSON(null); // } // return $this->response->setJSON($certificates); // } // public function createCalibratePreview($certid = null) { // Untuk Preview Sertifikat // //Melakukan search data dari database // if (!$certid) { // return $this->response->setStatusCode(400)->setJSON(['error' => 'Certificate ID is required']); // } // // Get certificate data Berdasarkan certid // $certificate = [ // 'certid' => 'f353ca91-4fc5-49f2-9b9e-304f83d11919', // 'certname' => 'Jokoh Calibration Certificate', // 'productname' => 'Jokoh', // 'productnumber' => 'SN-2024-001', // 'issuedate' => '2024-01-15', // 'expirydate' => '2025-01-15', // 'vendor' => 'Summit Calibration Lab', // 'isval' => null // ]; // if (empty($certificate)) { // JIka Tidak Ada // return $this->response->setStatusCode(404)->setJSON(['error' => 'Maintenance certificate not found']); // } // return $this->previewPdf($certificate, 'calibrate', 'tms24i'); // Preview PDF // } // Helper Function Preview dan Validate private function previewPdf($certificate, $type) { // Untuk Show/Preview PDF // Generate PDF $options = new Options(); $options->set('chroot', FCPATH); $options->set('isRemoteEnabled', true); $options->set('isHtml5ParserEnabled', true); // $options->set('defaultFont', 'Playfair Display'); $dompdf = new Dompdf($options); // Format dates $certificate['issueddate'] = date('d-M-Y', strtotime($certificate['issueddate'])); $certificate['expireddate'] = date('d-M-Y', strtotime($certificate['expireddate'])); // Select template and orientation based on type $template = ''; $orientation = 'portrait'; switch($type) { case 'training': $template = 'certificates/certificate_training'; $orientation = 'landscape'; break; case 'calibration': if ($productType == 'tms50i') { $template = 'certificates/callibrations_template/certificate_tms50i_calibration'; } else if ($productType == 'tms24i') { $template = 'certificates/callibrations_template/certificate_tms24i_calibration'; } else if ($productType == 'tms30i') { $template = 'certificates/callibrations_template/certificate_tms30i_calibration'; } else if ($productType == 'bs430') { $template = 'certificates/callibrations_template/certificate_bs430_calibration'; } else if ($productType == 'cl900i') { $template = 'certificates/callibrations_template/certificate_cl900i_calibration'; } else if ($productType == 'jokoh') { $template = 'certificates/callibrations_template/certificate_jokoh_calibration'; } else if ($productType == 'bc760r') { $template = 'certificates/callibrations_template/certificate_bc760r_calibration'; } else if ($productType == 'bc5140') { $template = 'certificates/callibrations_template/certificate_bc5140_calibration'; } else { return $this->response->setStatusCode(404)->setJSON(['error' => 'Not Found']); } $orientation = 'portrait'; break; case 'maintenance': $template = 'certificates/certificate_maintenance'; $orientation = 'landscape'; break; case 'installation': $template = 'certificates/certificate_installation'; $orientation = 'landscape'; break; } $html = view($template, [ 'certificate' => $certificate]); $dompdf->loadHtml($html); $dompdf->set_option('isRemoteEnabled', true); $dompdf->setPaper('A4', $orientation); $dompdf->render(); // Output PDF $filename = $certificate['certname']. '.pdf'; $dompdf->stream($filename, ['Attachment' => false]); } public function validateCertificate() { $certid = $this->request->getPost('certid'); $certificateType = $this->request->getPost('certificateType'); if (!$certid || !$certificateType) { return $this->response->setJSON(['success' => false, 'message' => 'Parameter tidak lengkap.']); } $userId = session()->get('userid'); $userPosId = session()->get('userposid'); $certificateModel = new CertificateModel(); // 1. Ambil data dasar saja dulu untuk pengecekan awal $currentCert = $certificateModel->find($certid); if (!$currentCert) { return $this->response->setJSON(['success' => false, 'message' => 'Data tidak ditemukan.']); } $updateData = []; $currentTime = date('Y-m-d H:i:s'); // 2. Filter Role & Cek Duplikasi switch ($userPosId) { case 1: // Manager if (!empty($currentCert['manager_validation_at'])) return $this->response->setJSON(['success' => false, 'message' => 'Anda sudah Melakukan Validasi.']); $updateData = ['manager_id' => $userId, 'manager_validation_at' => $currentTime]; break; case 2: // SPV if (!empty($currentCert['spv_validation_at'])) return $this->response->setJSON(['success' => false, 'message' => 'Anda sudah Melakukan Validasi.']); $updateData = ['spv_id' => $userId, 'spv_validation_at' => $currentTime]; break; case 4: // TSOIVD if ($currentCert['user_id'] != $userId) return $this->response->setJSON(['success' => false, 'message' => 'Bukan pemilik sertifikat.']); if (!empty($currentCert['user_validation_at'])) return $this->response->setJSON(['success' => false, 'message' => 'Anda sudah Melakukan Validasi.']); $updateData = ['user_validation_at' => $currentTime]; break; default: return $this->response->setJSON(['success' => false, 'message' => 'Akses ditolak.'], 403); } // 3. Eksekusi Update Validasi Role if ($certificateModel->update($certid, $updateData)) { // 4. Cek apakah ini validasi terakhir? // Ambil ulang data terbaru (cukup kolom validation saja untuk efisiensi) $checkFinal = $certificateModel->select('user_validation_at, spv_validation_at, manager_validation_at') ->find($certid); if (!empty($checkFinal['user_validation_at']) && (!empty($checkFinal['spv_validation_at']) || !empty($checkFinal['manager_validation_at']))) { // Check $checkStatus = $certificateModel->select('status')->find($certid); if ($checkStatus['status'] == 'validated') { return $this->response->setJSON([ 'success' => true, 'message' => 'Semua validasi telah dilakukan' ]); } // Update Status Utama $certificateModel->update($certid, ['status' => 'validated']); // Baru jalankan query berat JOIN di sini untuk keperluan PDF/Notifikasi $latestData = $certificateModel->select(' certificates.cert_name, certificates.issued_date, certificates.expired_date, certificates.file_url, productalias.productaliastext as productname, sites.sitename as sitename, products.productnumber, CASE WHEN certificates.cert_type = "MC" THEN "Maintenance" WHEN certificates.cert_type = "IC" THEN "Installation" WHEN certificates.cert_type = "UTC" THEN "Training" WHEN certificates.cert_type = "BAI" THEN "Before After Inspection" WHEN certificates.cert_type = "BAP" THEN "Berita Acara Pengerjaan" ELSE certificates.cert_type END AS cert_type, CONCAT(users.firstname, " ", users.lastname) AS fullname, userposition.texts AS user_position, certificates.issued_date, certificates.expired_date, certificates.cert_number -- Penting agar callback UUID tetap jalan ', false) ->join('users', 'users.userid = certificates.user_id', 'left') ->join('userposition', 'userposition.userposid = users.userposid', 'left') ->join('activities', 'activities.actid = certificates.actid', 'left') ->join('sites', 'sites.siteid = activities.siteid', 'left') ->join('products', 'products.productid = activities.productid', 'left') ->join('productcatalog', 'productcatalog.catalogid = products.catalogid', 'left') ->join('productalias', 'productalias.productaliasid = productcatalog.productaliasid', 'left') ->where('certificates.cert_id', $certid) ->first(); $certificate = [ 'file_url' => $latestData['file_url'], 'certname' => $latestData['cert_name'], 'sitename' => $latestData['sitename'], 'certtype' => $latestData['cert_type'], 'fullname' => $latestData['fullname'], 'userposition' => $latestData['user_position'], 'productname' => $latestData['productname'], 'productnumber' => $latestData['productnumber'], 'issueddate' => date('d-M-Y', strtotime($latestData['issued_date'])), 'expireddate' => date('d-M-Y', strtotime($latestData['expired_date'])), 'exportToPDF' => true ]; try { $pdfAfterValidation = $this->savePdf($certificate, $latestData['cert_type'], $latestData['cert_number']); // Simpan ke PDF $certificateModel->update($certid, [ // Update ke tabel certificates 'file_location' => $pdfAfterValidation['file_relative'], 'metadata_title' => $pdfAfterValidation['metadata_title'], 'metadata_keywords' => $pdfAfterValidation['metadata_keywords'].";".base_url('certificates/number/'.$latestData['cert_number']), // 'file_url' => base_url('certificates/number/'.$latestData['cert_number']) ]); return $this->response->setJSON([ 'success' => true, 'message' => 'Semua validasi telah dilakukan, PDF sudah di generate' ]); } catch (\Throwable $e) { return $this->response->setStatusCode(500)->setJSON([ 'success' => false, 'message' => $e->getMessage(), 'line' => $e->getLine(), 'file' => $e->getFile() ]); } } return $this->response->setJSON([ 'success' => true, 'message' => "Sertifikat {$certificateType} berhasil divalidasi." ]); } return $this->response->setJSON(['success' => false, 'message' => 'Gagal memperbarui data.']); } public function savePdf($certificate, $certificateType, $cert_number, $productType = null) { $certificateType = strtolower($certificateType); switch ($certificateType) { case 'training': $template = 'certificates/certificate_training'; $orientation = 'landscape'; $subDir = 'training'; break; case 'calibration': $orientation = 'portrait'; $subDir = 'calibration'; switch ($productType) { case 'tms50i': $template = 'certificates/callibrations_template/certificate_tms50i_calibration'; break; case 'tms24i': $template = 'certificates/callibrations_template/certificate_tms24i_calibration'; break; case 'tms30i': $template = 'certificates/callibrations_template/certificate_tms30i_calibration'; break; case 'bs430': $template = 'certificates/callibrations_template/certificate_bs430_calibration'; break; case 'cl900i': $template = 'certificates/callibrations_template/certificate_cl900i_calibration'; break; case 'jokoh': $template = 'certificates/callibrations_template/certificate_jokoh_calibration'; break; case 'bc760r': $template = 'certificates/callibrations_template/certificate_bc760r_calibration'; break; case 'bc5140': $template = 'certificates/callibrations_template/certificate_bc5140_calibration'; break; default: throw new \Exception('Product type calibration tidak valid'); } break; case 'maintenance': $template = 'certificates/certificate_maintenance'; $orientation = 'landscape'; $subDir = 'maintenance'; break; case 'installation': $template = 'certificates/certificate_installation'; $orientation = 'landscape'; $subDir = 'installation'; break; default: throw new \Exception('Certificate type tidak valid'); } if (empty($template)) { throw new \Exception('Template tidak ditemukan'); } // Dompdf $options = new Options(); $options->set('chroot', FCPATH); $options->set('isRemoteEnabled', true); $options->set('isHtml5ParserEnabled', true); // Create QR $builder = new Builder( writer: new PngWriter(), data: $certificate['file_url'], size: 120, margin: 0 ); $resultQr = $builder->build(); $certificate['qrcode'] = $resultQr->getDataUri(); $dompdf = new Dompdf($options); $html = view($template, ['certificate' => $certificate]); $dompdf->loadHtml($html); $dompdf->setPaper('A4', $orientation); $dompdf->render(); // Metadata $dompdf->addInfo('Title', $certificate['certname']); $dompdf->addInfo('Keywords', $certificate['certtype'] . ' Certificate;'.base_url('certificates/number/'.$cert_number)); // Folder $uploadDir = FCPATH . 'upload/documents/' . $subDir; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0755, true); } // Safe filename $cleanName = preg_replace('/[^A-Za-z0-9_\-]/', '_', $certificate['certname']); $timestamp = date('YmdHis'); $filename = $cleanName . '_' . $timestamp . '.pdf'; $filePath = $uploadDir . DIRECTORY_SEPARATOR . $filename; if (!file_put_contents($filePath, $dompdf->output())) { throw new \Exception('Gagal menyimpan file PDF'); } return [ 'file_name' => $filename, 'file_path' => $filePath, 'file_relative' => 'upload/documents/' . $subDir . '/' . $filename, 'metadata_title' => $certificate['certname'], 'metadata_keywords' => $certificate['certtype'] . ' Certificate' ]; } public function view($uuid) { try { $certificateModel = new CertificateModel(); // Ambil dari model (UUID → binary otomatis) $certificate = $certificateModel->getByUuid($uuid); if (!$certificate) { throw new \Exception('Certificate tidak ditemukan'); } if (empty($certificate['file_location'])) { throw new \Exception('File PDF belum tersedia'); } $filePath = FCPATH . $certificate['file_location']; if (!file_exists($filePath)) { throw new \Exception('File tidak ditemukan di server'); } return $this->response ->setHeader('Content-Type', 'application/pdf') ->setHeader( 'Content-Disposition', 'inline; filename="' . basename($filePath) . '"' ) ->setBody(file_get_contents($filePath)); } catch (\Throwable $e) { return $this->response->setStatusCode(404)->setJSON([ // 'success' => false, 'message' => "404 Not Found" ]); } } }