forked from mahdahar/crm-summit
Update Fitur Certificate Training
This commit is contained in:
parent
038e5e74db
commit
799edf9588
@ -161,6 +161,8 @@ $routes->get('/activities/getproduct/(:num)', 'Activities::getproduct/$1/$2/$3')
|
||||
$routes->get('/activities/getvendor/(:num)', 'Activities::getvendor/$1');
|
||||
$routes->get('/activities/getconsumable/(:num)', 'Activities::getconsumable/$1');
|
||||
$routes->get('/activities/getcontact/(:num)', 'Activities::getcontact/$1');
|
||||
$routes->get('/activities/getsitecontact/(:num)', 'Activities::getsitecontact/$1');
|
||||
$routes->get('/activities/getsitecontact/(:num)/(:num)', 'Activities::getsitecontact/$1/$2');
|
||||
$routes->get('/activities/newtextarea', 'Activities::newtextarea');
|
||||
$routes->get('/activities/activitiesproduct/(:num)', 'Activities::activitiesproduct/$1');
|
||||
$routes->get('/activities/dummy', 'Activities::dummy');
|
||||
@ -212,23 +214,24 @@ $routes->group('certificates', function($routes) {
|
||||
// Untuk Index Tiap Menu
|
||||
$routes->get('maintenance', 'Certificates::maintenanceIndex'); // OK
|
||||
$routes->get('installation', 'Certificates::installationIndex'); // OK
|
||||
// $routes->get('training', 'Certificates::trainingIndex'); // OK
|
||||
$routes->get('training', 'Certificates::trainingIndex'); // OK
|
||||
// $routes->get('calibration', 'Certificates::calibrateIndex'); // OK
|
||||
|
||||
// Untuk Get API
|
||||
$routes->get('api/getindexmaintenance', 'Certificates::getDataIndexMaintenance'); // OK
|
||||
$routes->get('api/getindexinstallation', 'Certificates::getDataIndexInstallation'); // OK
|
||||
// $routes->get('api/getindextraining', 'Certificates::getDataIndexTraining'); // OK
|
||||
$routes->get('api/getindextraining', 'Certificates::getDataIndexTraining'); // OK
|
||||
// $routes->get('api/getindexcalibrate', 'Certificates::getDataIndexCalibrate');
|
||||
|
||||
// Untuk Get Modal Data
|
||||
$routes->post('api/showmaintenance', 'Certificates::showDataMaintenance'); // OK
|
||||
$routes->post('api/showinstallation', 'Certificates::showDataInstallation'); // OK
|
||||
$routes->post('api/showtraining', 'Certificates::showDataTraining'); // OK
|
||||
|
||||
// Untuk Preview Cerificate
|
||||
$routes->get('maintenance/show/(:any)', 'Certificates::createMaintenancePreview/$1'); // OK
|
||||
$routes->get('installation/show/(:any)', 'Certificates::createInstallationPreview/$1'); // OK
|
||||
// $routes->get('training/show/(:any)', 'Certificates::createTrainingPreview/$1'); // OK
|
||||
$routes->get('training/show/(:any)', 'Certificates::createTrainingPreview/$1'); // OK
|
||||
// $routes->get('calibration/show/(:any)/(:any)', 'Certificates::createCalibratePreview/$1/$2');
|
||||
|
||||
$routes->post('api/validatecertificate', 'Certificates::validateCertificate'); // OK
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Models\CertificateModel;
|
||||
use App\Models\CertificateTrainingModel;
|
||||
use App\Models\ActivitiesModel;
|
||||
use App\Models\ActdetailModel;
|
||||
use App\Models\InvTransModel;
|
||||
@ -376,6 +377,14 @@ class Activities extends Controller {
|
||||
$query = $db->query($sql);
|
||||
$results = $query->getResultArray();
|
||||
$data['vendors'] = $results;
|
||||
|
||||
// $sql = "select c.* from contacts c
|
||||
// Left join sitecontact sc on sc.contactid=c.contactid
|
||||
// where sc.siteid = 2";
|
||||
$sql = "SELECT contactid, firstname, lastname, initial, title, email_1 FROM contacts";
|
||||
$query = $db->query($sql);
|
||||
$results = $query->getResultArray();
|
||||
$data['contacts'] = $results;
|
||||
|
||||
if( $this->request->getVar('siteid') != '' ) { $siteid = $this->request->getVar('siteid'); }
|
||||
|
||||
@ -408,7 +417,13 @@ class Activities extends Controller {
|
||||
'attachment' => $this->request->getVar('attachment'),
|
||||
'actdetailid' => $this->request->getVar('actdetailid'),
|
||||
'acttextid' => $this->request->getVar('acttextid'),
|
||||
'textvalue' => $this->request->getVar('textvalue')
|
||||
'textvalue' => $this->request->getVar('textvalue'),
|
||||
];
|
||||
$data['training_certificates'] = [
|
||||
'trainingids' => $this->request->getVar('trainingids'),
|
||||
'trainingnames' => $this->request->getVar('trainingnames'),
|
||||
'trainingdates' => $this->request->getVar('trainingdates'),
|
||||
'validatealltraining' => $this->request->getVar('validatealltraining'),
|
||||
];
|
||||
|
||||
$actby = $this->request->getVar('actby');
|
||||
@ -470,11 +485,17 @@ class Activities extends Controller {
|
||||
$userid_owner = $data['new_value']['userid_owner'];
|
||||
$this->createCertificate($actid, $issuedDate, $userid_owner, 'MC');
|
||||
}
|
||||
if ($this->request->getVar('installation')) { // Jika Maintenance Dicentang
|
||||
if ($this->request->getVar('installation')) { // Jika Installation Dicentang
|
||||
$issuedDate = $data['new_value']['closedate'] ?? null;
|
||||
$userid_owner = $data['new_value']['userid_owner'];
|
||||
$this->createCertificate($actid, $issuedDate, $userid_owner, 'IC');
|
||||
}
|
||||
if ($this->request->getVar('training')) { // Jika User Training Dicentang
|
||||
if ($data['training_certificates']['trainingids'] != null) {
|
||||
$userid_owner = $data['new_value']['userid_owner'];
|
||||
$this->createCertificateTraining($actid, $userid_owner, $data['training_certificates']);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// update edit
|
||||
@ -550,33 +571,43 @@ class Activities extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// UNTUK CERTIFICATES
|
||||
$certificateTypes = [
|
||||
'maintenance' => 'MC',
|
||||
'installation' => 'IC',
|
||||
];
|
||||
$hasAnyAction = false;
|
||||
// // UNTUK CERTIFICATES
|
||||
// $certificateTypes = [
|
||||
// 'maintenance' => 'MC',
|
||||
// 'installation' => 'IC'
|
||||
// ];
|
||||
// $hasAnyAction = false;
|
||||
// $issuedDate = $data['new_value']['closedate'] ?? null;
|
||||
// $userid_owner = $data['new_value']['userid_owner'];
|
||||
// foreach ($certificateTypes as $requestName => $certCode) { //perulangan untuk mengecek semua checkbox
|
||||
// if ($this->request->getVar($requestName)) {
|
||||
// $hasAnyAction = true; // Jika checkbox dicentang, tandai bahwa ada aksi
|
||||
// $this->updateCertificate($actid, $issuedDate, $userid_owner, $certCode);
|
||||
// }
|
||||
// }
|
||||
// if (!$hasAnyAction) { // Jika setelah dicek semua ternyata tidak ada satupun yang dicentang, baru jalankan delete
|
||||
// $this->deleteCertificate($actid);
|
||||
// }
|
||||
$reqMaintenance = $this->request->getPost('maintenance') !== null;
|
||||
$reqInstallation = $this->request->getPost('installation') !== null;
|
||||
$reqTraining = $this->request->getPost('training') !== null;
|
||||
$issuedDate = $data['new_value']['closedate'] ?? null;
|
||||
$userid_owner = $data['new_value']['userid_owner'];
|
||||
foreach ($certificateTypes as $requestName => $certCode) { //perulangan untuk mengecek semua checkbox
|
||||
if ($this->request->getVar($requestName)) {
|
||||
$hasAnyAction = true; // Jika checkbox dicentang, tandai bahwa ada aksi
|
||||
$this->updateCertificate($actid, $issuedDate, $userid_owner, $certCode);
|
||||
}
|
||||
if ($reqMaintenance) {// MC
|
||||
$this->updateCertificate($actid, $issuedDate, $userid_owner, 'MC');
|
||||
} else {
|
||||
$this->deleteCertificate($actid, 'MC');
|
||||
}
|
||||
if (!$hasAnyAction) { // Jika setelah dicek semua ternyata tidak ada satupun yang dicentang, baru jalankan delete
|
||||
$this->deleteCertificate($actid);
|
||||
if ($reqInstallation) {// IC
|
||||
$this->updateCertificate($actid, $issuedDate, $userid_owner, 'IC');
|
||||
} else {
|
||||
$this->deleteCertificate($actid, 'IC');
|
||||
}
|
||||
if ($reqTraining) {// UTC
|
||||
$this->updateCertificateTraining($actid, $userid_owner, $data['training_certificates']);
|
||||
} else {
|
||||
$this->deleteCertificateTraining(null, $actid);
|
||||
}
|
||||
// if ($this->request->getVar('maintenance')) { // Maintenance
|
||||
// // Maintenance sertifikat create or update
|
||||
// $issuedDate = $data['new_value']['closedate'] ?? null;
|
||||
// $userid_owner = $data['new_value']['userid_owner'];
|
||||
// $this->updateCertificate($actid, $issuedDate, $userid_owner, 'MC');
|
||||
// } else {
|
||||
// // Hapus softdelete sertifikat
|
||||
// $this->deleteCertificate($actid);
|
||||
// }
|
||||
}
|
||||
|
||||
// act by consumables
|
||||
@ -1692,7 +1723,7 @@ class Activities extends Controller {
|
||||
return view('invtrans_index', $data);
|
||||
}
|
||||
|
||||
// Untuk CRUD Sertifikat
|
||||
// Untuk CRUD Sertifikat Installation dan Maintenance
|
||||
public function createCertificate ($actid, $issuedDate, $userid_owner, $certificate_type) {
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
@ -1744,6 +1775,7 @@ class Activities extends Controller {
|
||||
$existingCerts = $certificateModel->withDeleted()
|
||||
->select('status')
|
||||
->where('actid', $actid)
|
||||
->where('cert_type', $certificate_type)
|
||||
->findAll();
|
||||
|
||||
// Variabel penanda apakah data sudah pernah ada di database
|
||||
@ -1807,22 +1839,25 @@ class Activities extends Controller {
|
||||
$newCertificate = $certificateModel->find($certid);
|
||||
$certificateModel->update($certid, ['file_url' => base_url('certificates/number/'.$newCertificate['cert_number'])]);
|
||||
} else {
|
||||
// dd($isDataExist);
|
||||
// Jika data sudah ada, eksekusi UPDATE
|
||||
// Catatan: Karena bisa ada lebih dari 1 data dengan actid yang sama (karena findAll),
|
||||
// Update ini akan menimpa semua baris yang punya actid tersebut.
|
||||
$certificateModel->withDeleted()
|
||||
->where('actid', $actid)
|
||||
->where('cert_type', $certificate_type)
|
||||
->set($certPayload)
|
||||
->update();
|
||||
}
|
||||
}
|
||||
public function deleteCertificate($actid) {
|
||||
public function deleteCertificate($actid, $certificate_type) {
|
||||
$certificateModel = new CertificateModel();
|
||||
|
||||
// 1. Cek apakah data sudah ada menggunakan findAll()
|
||||
$existingCerts = $certificateModel->withDeleted()
|
||||
->select('status')
|
||||
->where('actid', $actid)
|
||||
->where('cert_type', $certificate_type)
|
||||
->findAll();
|
||||
|
||||
// Variabel penanda apakah data sudah pernah ada di database
|
||||
@ -1837,8 +1872,307 @@ class Activities extends Controller {
|
||||
return;
|
||||
}
|
||||
}
|
||||
$certificateModel->where('actid', $actid)->delete();
|
||||
$certificateModel->where('actid', $actid)->where('cert_type', $certificate_type)->delete();
|
||||
}
|
||||
|
||||
|
||||
public function createCertificateTraining ($actid, $userid_owner, $training_data) {
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
$sql = "SELECT prl.productaliastext as productname
|
||||
FROM `activities` act
|
||||
LEFT JOIN products pr ON pr.productid = act.productid
|
||||
LEFT JOIN productcatalog prc ON prc.catalogid = pr.catalogid
|
||||
LEFT JOIN productalias prl ON prl.productaliasid = prc.productaliasid
|
||||
WHERE act.actid = $actid";
|
||||
$query = $db->query($sql);
|
||||
$result = $query->getRowArray();
|
||||
|
||||
$insertCert = [
|
||||
'cert_type' => "UTC",
|
||||
'actid' => $actid,
|
||||
'user_id' => $userid_owner
|
||||
];
|
||||
|
||||
$certificateModel = new CertificateModel();
|
||||
$CertificateTrainingModel = new CertificateTrainingModel();
|
||||
|
||||
// Apakah Validasi Semuanya Dicentang
|
||||
if($training_data['validatealltraining'] != null) {
|
||||
$currentTime = date('Y-m-d H:i:s');
|
||||
} else {
|
||||
$currentTime = null;
|
||||
}
|
||||
|
||||
foreach ($training_data['trainingids'] as $index => $id) {
|
||||
|
||||
// Ambil data berdasarkan index yang sama
|
||||
$contact_id = $id;
|
||||
$name = $training_data['trainingnames'][$index];
|
||||
$issued_date = $training_data['trainingdates'][$index];
|
||||
|
||||
$insertCert['cert_name'] = "UTC_" . ($result['productname'] ?? 'UNKNOWN') . "_" . $name . "_" . $actid;
|
||||
$insertCert['issued_date'] = $issued_date;
|
||||
$insertCert['user_validation_at'] = $currentTime;
|
||||
|
||||
$certificateModel->insert($insertCert);
|
||||
$certid = $certificateModel->getInsertID();
|
||||
|
||||
$newCertificate = $certificateModel->find($certid);
|
||||
$certificateModel->update($certid, ['file_url' => base_url('certificates/number/'.$newCertificate['cert_number'])]);
|
||||
|
||||
$CertificateTrainingModel->insert(['cert_id' => (int)$certid, 'contact_id' => (int)$contact_id]);
|
||||
}
|
||||
|
||||
}
|
||||
public function updateCertificateTraining($actid, $userid_owner, $new_training_data) {
|
||||
$certificateModel = new CertificateModel();
|
||||
|
||||
$existingTrainingCerts = $certificateModel->withDeleted() // 1. Ambil data existing dari database
|
||||
->select('
|
||||
Certificates.cert_id,
|
||||
Certificates.cert_name,
|
||||
Certificates.status,
|
||||
Certificates_Training.contact_id
|
||||
')
|
||||
->join('Certificates_Training', 'Certificates_Training.cert_id = Certificates.cert_id', 'join')
|
||||
->where('Certificates.actid', $actid)
|
||||
->where('Certificates.cert_type', 'UTC')
|
||||
->findAll();
|
||||
|
||||
|
||||
$existingMap = []; // 2. Buat Map untuk data existing
|
||||
foreach ($existingTrainingCerts as $cert) {
|
||||
$contactId = is_object($cert) ? $cert->contact_id : $cert['contact_id'];
|
||||
$existingMap[$contactId] = $cert;
|
||||
}
|
||||
|
||||
// Temp
|
||||
$dataToInsert = [];
|
||||
$dataToUpdate = [];
|
||||
$dataToDelete = [];
|
||||
|
||||
$currentTime = date('Y-m-d H:i:s');
|
||||
|
||||
// 3. Looping data baru dari form
|
||||
if (!empty($new_training_data['trainingids']) && is_array($new_training_data['trainingids'])) {
|
||||
foreach ($new_training_data['trainingids'] as $index => $contactId) {
|
||||
|
||||
$trainingName = $new_training_data['trainingnames'][$index] ?? null;
|
||||
$trainingDate = $new_training_data['trainingdates'][$index] ?? null;
|
||||
|
||||
// Cek apakah data sudah ada di database
|
||||
if (array_key_exists($contactId, $existingMap)) {
|
||||
$existingData = $existingMap[$contactId];
|
||||
$certId = is_object($existingData) ? $existingData->cert_id : $existingData['cert_id'];
|
||||
|
||||
// if ($new_training_data['validatealltraining'] != null) {
|
||||
// $certificatesUpdate['user_validation_at'] = $currentTime;
|
||||
// } else {
|
||||
// $certificatesUpdate['user_validation_at'] = null;
|
||||
// }
|
||||
$certificatesUpdate['cert_id'] = $certId;
|
||||
// $certificatesUpdate['actid'] = $actid;
|
||||
$certificatesUpdate['issued_date'] = $trainingDate;
|
||||
$certificatesUpdate['deleted_at'] = null;
|
||||
|
||||
$certificatesTrainingUpdate['cert_id'] = $certId;
|
||||
$certificatesTrainingUpdate['contact_id'] = $contactId;
|
||||
$certificatesTrainingUpdate['deleted_at'] = null;
|
||||
|
||||
$certificatesUpdates[] = $certificatesUpdate;
|
||||
$certificatesTrainingUpdates[] = $certificatesTrainingUpdate;
|
||||
|
||||
unset($existingMap[$contactId]); // ELIMINASI: Hapus dari map karena data ini dipertahankan
|
||||
} else {
|
||||
// Insert Temp
|
||||
$dataToInsert['trainingids'][] = $contactId;
|
||||
$dataToInsert['trainingnames'][] = $trainingName;
|
||||
$dataToInsert['trainingdates'][] = $trainingDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Proses Sisa Data di Map menjadi DELETE
|
||||
// Apapun yang tersisa di $existingMap berarti tidak ada di $new_training_data
|
||||
foreach ($existingMap as $contactId => $existingData) {
|
||||
$certId = is_object($existingData) ? $existingData->cert_id : $existingData['cert_id'];
|
||||
|
||||
// Memasukkan cert_id, contact_id, (dan actid jika itu parameter ke-3 yang dimaksud)
|
||||
$dataToDelete[] = [
|
||||
'cert_id' => $certId,
|
||||
'contact_id' => $contactId,
|
||||
'actid' => $actid
|
||||
];
|
||||
}
|
||||
|
||||
// Cek hasil klasifikasinya:
|
||||
// dd(['Insert' => $dataToInsert, 'Update' => $dataToUpdate, 'Delete' => $dataToDelete]);
|
||||
|
||||
// OK
|
||||
if (!empty($dataToInsert)) {
|
||||
$dataToInsert['validatealltraining'] = $new_training_data['validatealltraining'];
|
||||
$this->createCertificateTraining($actid, $userid_owner, $dataToInsert);
|
||||
}
|
||||
|
||||
if (!empty($certificatesUpdates)) {
|
||||
|
||||
$certificateModel = new CertificateModel();
|
||||
$CertificateTrainingModel = new CertificateTrainingModel();
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
$db->transStart();
|
||||
|
||||
$certificateModel->builder()
|
||||
->where('cert_type', 'UTC')
|
||||
->where('status', 'unvalidated')
|
||||
->updateBatch($certificatesUpdates, 'cert_id');
|
||||
|
||||
foreach ($certificatesTrainingUpdates as $trainingUpdate) {
|
||||
$CertificateTrainingModel->builder()
|
||||
->where('cert_id', $trainingUpdate['cert_id'])
|
||||
->where('contact_id', $trainingUpdate['contact_id'])
|
||||
->set([
|
||||
'deleted_at' => null // Paksa restore data
|
||||
])->update();
|
||||
}
|
||||
|
||||
$db->transComplete();
|
||||
|
||||
if ($db->transStatus() === false) {
|
||||
// Handle jika transaksi gagal
|
||||
log_message('error', 'Gagal melakukan update sertifikat training.');
|
||||
}
|
||||
}
|
||||
|
||||
// OK
|
||||
if (!empty($dataToDelete)) {
|
||||
$this->deleteCertificateTraining($dataToDelete, null);
|
||||
}
|
||||
}
|
||||
public function deleteCertificateTraining($updateToDelete, $deleteActid) {
|
||||
|
||||
$certificateModel = new CertificateModel();
|
||||
$CertificateTrainingModel = new CertificateTrainingModel();
|
||||
|
||||
// if (!empty($updateToDelete)) {
|
||||
// foreach ($updateToDelete as $key => $value) {
|
||||
|
||||
// // 1. Cari data sertifikat terlebih dahulu untuk mendapatkan cert_id
|
||||
// $certificate = $certificateModel
|
||||
// ->where('actid', $value['actid'])
|
||||
// ->where('status', 'unvalidated')
|
||||
// ->where('cert_type', 'UTC')
|
||||
// ->first(); // Gunakan first() jika Laravel, atau get()->getRowArray() jika CI4
|
||||
|
||||
// // 2. Pastikan data ditemukan sebelum melakukan penghapusan
|
||||
// if ($certificate) {
|
||||
|
||||
// // Ambil cert_id dari hasil query (sesuaikan dengan format return object/array framework Anda)
|
||||
// $certId = $certificate['cert_id']; // atau $certificate->cert_id jika berupa object
|
||||
|
||||
// // 3. Hapus data di CertificateTrainingModel menggunakan $certId yang baru didapat
|
||||
// $CertificateTrainingModel
|
||||
// ->where('cert_id', $certId)
|
||||
// ->where('contact_id', $value['contact_id'])
|
||||
// ->delete();
|
||||
|
||||
// // 4. Hapus data di certificateModel
|
||||
// // Kita cukup gunakan cert_id karena itu sudah spesifik (Primary Key)
|
||||
// $certificateModel
|
||||
// ->where('cert_id', $certId)
|
||||
// ->delete();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (!empty($updateToDelete)) {
|
||||
|
||||
foreach ($updateToDelete as $key => $value) {
|
||||
|
||||
$isSuccess = $certificateModel
|
||||
->where('actid', $value['actid'])
|
||||
->where('cert_id', $value['cert_id'])
|
||||
->where('status', 'unvalidated')
|
||||
->where('cert_type', 'UTC')->delete();
|
||||
|
||||
// Cek apakah ada baris yang benar-benar dihapus di database
|
||||
if ($isSuccess && $certificateModel->affectedRows() > 0) {
|
||||
$CertificateTrainingModel
|
||||
->where('cert_id', $value['cert_id'])
|
||||
->where('contact_id', $value['contact_id'])->delete();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleteActid != null) {
|
||||
// 1. Ambil (SELECT) dulu daftar cert_id yang memenuhi syarat sebelum dihapus
|
||||
$certsToDelete = $certificateModel
|
||||
->select('cert_id') // Kita hanya butuh kolom cert_id
|
||||
->where('actid', $deleteActid)
|
||||
->where('status', 'unvalidated')
|
||||
->where('cert_type', 'UTC')
|
||||
->findAll();
|
||||
|
||||
// Pastikan ada data yang ditemukan sebelum mengeksekusi delete
|
||||
if (!empty($certsToDelete)) {
|
||||
|
||||
// Ekstrak hasil query menjadi array 1 dimensi berisi kumpulan cert_id
|
||||
// Contoh hasil: [10, 15, 22]
|
||||
$certIds = array_column($certsToDelete, 'cert_id');
|
||||
|
||||
// Gunakan Transaction agar jika salah satu gagal, semuanya batal (aman)
|
||||
$db = \Config\Database::connect();
|
||||
$db->transStart();
|
||||
|
||||
// 2. Hapus data relasi di tabel Certificates_Training (Pivot)
|
||||
// Gunakan whereIn karena kita menghapus banyak cert_id sekaligus
|
||||
$CertificateTrainingModel
|
||||
->whereIn('cert_id', $certIds)
|
||||
->delete();
|
||||
|
||||
// 3. Hapus data utama di tabel Certificates
|
||||
// Kita bisa langsung pakai $certIds yang sudah didapat
|
||||
$certificateModel
|
||||
->whereIn('cert_id', $certIds)
|
||||
->delete();
|
||||
|
||||
$db->transComplete();
|
||||
|
||||
if ($db->transStatus() === false) {
|
||||
// Logika jika proses delete gagal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Untuk Training Contact
|
||||
public function getsitecontact($siteid=null, $actid=null){
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
if($siteid == null) {
|
||||
$filterquery = '';
|
||||
} else {
|
||||
$filterquery = "where sc.siteid=$siteid";
|
||||
}
|
||||
$sql = "SELECT sc.siteid, c.contactid, c.firstname, c.lastname, c.title, c.initial, c.email_1 from contacts c
|
||||
Left join sitecontact sc on sc.contactid=c.contactid
|
||||
$filterquery";
|
||||
$query = $db->query($sql);
|
||||
$results = $query->getResultArray();
|
||||
$data['sitecontacts'] = $results;
|
||||
|
||||
$data['siteid'] = $siteid;
|
||||
|
||||
// Get Data Training User
|
||||
if($actid != null) {
|
||||
$certificateTrainingModel = new CertificateTrainingModel();
|
||||
$traininguser = $certificateTrainingModel->select('contacts.contactid, contacts.firstname, contacts.lastname, contacts.title, contacts.initial, contacts.email_1, certificates.issued_date')
|
||||
->join('certificates', 'certificates.cert_id = certificates_training.cert_id', 'inner')
|
||||
->join('contacts', 'contacts.contactid = certificates_training.contact_id', 'inner')
|
||||
->where('certificates.actid', $actid)
|
||||
->findAll();
|
||||
$data['traininguser'] = $traininguser;
|
||||
}
|
||||
|
||||
return view('activities_getsitecontacts', $data);
|
||||
}
|
||||
}
|
||||
@ -43,7 +43,7 @@ class Certificates extends BaseController {
|
||||
')
|
||||
->join('activities', 'activities.actid = certificates.actid', 'left')
|
||||
->join('users', 'users.userid = certificates.user_id', 'left')
|
||||
->where('certificates.cert_type', 'IC');;
|
||||
->where('certificates.cert_type', 'IC');
|
||||
|
||||
// 2. Filter berdasarkan Role
|
||||
if (in_array($userPosId, [1, 3, 5])) { // Manager & IT: Tidak perlu filter tambahan (lihat semua)
|
||||
@ -208,7 +208,7 @@ class Certificates extends BaseController {
|
||||
')
|
||||
->join('activities', 'activities.actid = certificates.actid', 'left')
|
||||
->join('users', 'users.userid = certificates.user_id', 'left')
|
||||
->where('certificates.cert_type', 'MC');;
|
||||
->where('certificates.cert_type', 'MC');
|
||||
|
||||
// 2. Filter berdasarkan Role
|
||||
if (in_array($userPosId, [1, 3, 5])) { // Manager & IT: Tidak perlu filter tambahan (lihat semua)
|
||||
@ -350,69 +350,189 @@ class Certificates extends BaseController {
|
||||
|
||||
|
||||
// Untuk Sertifikat Training [3]
|
||||
// public function trainingIndex() {
|
||||
// return view('certificate_training_index');
|
||||
// }
|
||||
// public function getDataIndexTraining() {
|
||||
// // $actid = $this->request->getVar('actid');
|
||||
public function trainingIndex() {
|
||||
return view('certificate_training_index');
|
||||
}
|
||||
public function getDataIndexTraining() {
|
||||
$userPosId = session()->get('userposid');
|
||||
$userId = session()->get('userid');
|
||||
|
||||
$certificateModel = new CertificateModel();
|
||||
|
||||
// // 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'
|
||||
// ]
|
||||
// ];
|
||||
// 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', 'UTC');
|
||||
|
||||
// // If no actid, return all certificates
|
||||
// if (empty($certificates)) {
|
||||
// return $this->response->setJSON(null);
|
||||
// }
|
||||
// 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([]);
|
||||
}
|
||||
|
||||
// return $this->response->setJSON($certificates);
|
||||
// }
|
||||
// public function createTrainingPreview($certid = null) { // Untuk Preview Sertifikat
|
||||
// //Melakukan search data dari database
|
||||
// 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 showDataTraining() { // 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 "Berita Acara Instalasi"
|
||||
WHEN certificates.cert_type = "BAP" THEN "Berita Acara Penarikan"
|
||||
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,
|
||||
CONCAT(contacts.firstname, " ", contacts.lastname) AS fullname
|
||||
', 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')
|
||||
->join('certificates_training', 'certificates_training.cert_id = certificates.cert_id', 'left')
|
||||
->join('contacts', 'contacts.contactid = certificates_training.contact_id', '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 createTrainingPreview($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 "training"
|
||||
WHEN certificates.cert_type = "BAI" THEN "Berita Acara Instalasi"
|
||||
WHEN certificates.cert_type = "BAP" THEN "Berita Acara Penarikan"
|
||||
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,
|
||||
CONCAT(contacts.firstname, " ", contacts.lastname) AS fullname,
|
||||
contacts.title,
|
||||
zones.zonename as city,
|
||||
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('accounts', 'accounts.accountid = sites.accountid', 'left')
|
||||
->join('zones', 'zones.zoneid = accounts.zoneid', 'left')
|
||||
->join('products', 'products.productid = activities.productid', 'left')
|
||||
->join('productcatalog', 'productcatalog.catalogid = products.catalogid', 'left')
|
||||
->join('productalias', 'productalias.productaliasid = productcatalog.productaliasid', 'left')
|
||||
->join('certificates_training', 'certificates_training.cert_id = certificates.cert_id', 'left')
|
||||
->join('contacts', 'contacts.contactid = certificates_training.contact_id', 'left')
|
||||
->where('certificates.cert_id', $certid)
|
||||
->first();
|
||||
$certificate = [
|
||||
'certname' => trim($data['cert_name']),
|
||||
'sitename' => $data['sitename'],
|
||||
'title' => empty($data['title']) ? '' : ', ' . $data['title'],
|
||||
'city' => empty($data['city']) ? '' : $data['city'],
|
||||
'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']
|
||||
];
|
||||
if ($certificate['certtype'] == 'training') {
|
||||
$certificate['issueddate'] = date('F d, Y', strtotime($data['issued_date']));
|
||||
} else {
|
||||
$certificate['issueddate'] = date('d-M-Y', strtotime($data['issued_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']);
|
||||
}
|
||||
|
||||
// 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
|
||||
// }
|
||||
|
||||
return $this->previewPdf($certificate, 'training'); // Preview PDF
|
||||
}
|
||||
|
||||
// Untuk Sertifikat Calibrate [4]
|
||||
// public function calibrateIndex() {
|
||||
@ -490,10 +610,12 @@ class Certificates extends BaseController {
|
||||
|
||||
$dompdf = new Dompdf($options);
|
||||
|
||||
// Format dates
|
||||
$certificate['issueddate'] = date('d-M-Y', strtotime($certificate['issueddate']));
|
||||
|
||||
if(isset($certificate['expireddate'])) {
|
||||
if ($type == 'training') {
|
||||
$certificate['issueddate'] = date('F d, Y', strtotime($certificate['issueddate']));
|
||||
} else {
|
||||
$certificate['issueddate'] = date('d-M-Y', strtotime($certificate['issueddate']));
|
||||
}
|
||||
if (isset($certificate['expireddate'])) {
|
||||
$certificate['expireddate'] = date('d-M-Y', strtotime($certificate['expireddate']));
|
||||
}
|
||||
|
||||
@ -619,51 +741,95 @@ class Certificates extends BaseController {
|
||||
$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 "Berita Acara Instalasi"
|
||||
// WHEN certificates.cert_type = "BAP" THEN "Berita Acara Penarikan"
|
||||
// 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();
|
||||
$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 "Berita Acara Instalasi"
|
||||
WHEN certificates.cert_type = "BAP" THEN "Berita Acara Penarikan"
|
||||
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();
|
||||
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 "Berita Acara Instalasi"
|
||||
WHEN certificates.cert_type = "BAP" THEN "Berita Acara Penarikan"
|
||||
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,
|
||||
CONCAT(contacts.firstname, " ", contacts.lastname) AS fullname,
|
||||
contacts.title,
|
||||
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('accounts', 'accounts.accountid = sites.accountid', 'left')
|
||||
->join('zones', 'zones.zoneid = accounts.zoneid', 'left')
|
||||
->join('products', 'products.productid = activities.productid', 'left')
|
||||
->join('productcatalog', 'productcatalog.catalogid = products.catalogid', 'left')
|
||||
->join('productalias', 'productalias.productaliasid = productcatalog.productaliasid', 'left')
|
||||
->join('certificates_training', 'certificates_training.cert_id = certificates.cert_id', 'left')
|
||||
->join('contacts', 'contacts.contactid = certificates_training.contact_id', 'left')
|
||||
->where('certificates.cert_id', $certid)
|
||||
->first();
|
||||
|
||||
$certificate = [
|
||||
'title' => empty($latestData['title']) ? '' : ', ' . $latestData['title'],
|
||||
'file_url' => $latestData['file_url'],
|
||||
'certname' => $latestData['cert_name'],
|
||||
'sitename' => $latestData['sitename'],
|
||||
'city' => empty($data['city']) ? '' : $data['city'],
|
||||
'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'])),
|
||||
// 'issueddate' => date('d-M-Y', strtotime($latestData['issued_date'])),
|
||||
'expireddate' => date('d-M-Y', strtotime($latestData['expired_date'])),
|
||||
'exportToPDF' => true
|
||||
];
|
||||
if ($latestData['cert_type'] == 'training') {
|
||||
$certificate['issueddate'] = date('F d, Y', strtotime($latestData['issued_date']));
|
||||
} else {
|
||||
$certificate['issueddate'] = date('d-M-Y', strtotime($latestData['issued_date']));
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Controllers;
|
||||
|
||||
use App\Models\ContactsModel;
|
||||
use App\Models\SiteContactModel;
|
||||
use CodeIgniter\Controller;
|
||||
|
||||
class Contacts extends Controller {
|
||||
@ -38,7 +39,7 @@ class Contacts extends Controller {
|
||||
}
|
||||
if ($this->request->getMethod() === 'POST') {
|
||||
$rules = [
|
||||
'contactid' => 'required',
|
||||
// 'contactid' => 'required',
|
||||
'firstname' => 'required',
|
||||
'email_1' => 'required',
|
||||
'initial' => 'required'
|
||||
@ -53,7 +54,8 @@ class Contacts extends Controller {
|
||||
'email_2' => $this->request->getVar('email_2'),
|
||||
'phone' => $this->request->getVar('phone'),
|
||||
'mobile_1' => $this->request->getVar('mobile_1'),
|
||||
'mobile_2' => $this->request->getVar('mobile_2')
|
||||
'mobile_2' => $this->request->getVar('mobile_2'),
|
||||
'siteid' => $this->request->getVar('siteid') ?? null //Untuk Create dari AR
|
||||
];
|
||||
|
||||
if($this->validate($rules)){
|
||||
@ -67,6 +69,18 @@ class Contacts extends Controller {
|
||||
$contactsModel->set('createdate', 'NOW()', FALSE);
|
||||
$contactsModel->set('enddate', NULL);
|
||||
$contactsModel->insert($data['new_value']);
|
||||
$contactid = $contactsModel->getInsertID();
|
||||
|
||||
if($this->request->getVar('siteid') != null) {
|
||||
$siteContactModel = new SiteContactModel();
|
||||
$siteContactValue = [
|
||||
'siteid' => $this->request->getVar('siteid'),
|
||||
'contactid' => $contactid,
|
||||
'contactemail' => $this->request->getVar('email_1'),
|
||||
];
|
||||
$siteContactModel->insert($siteContactValue);
|
||||
}
|
||||
|
||||
return view('form_success');
|
||||
}
|
||||
} else {
|
||||
|
||||
63
app/Models/CertificateTrainingModel.php
Normal file
63
app/Models/CertificateTrainingModel.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class CertificateTrainingModel extends Model
|
||||
{
|
||||
protected $table = 'certificates_training';
|
||||
protected $primaryKey = 'cert_training_id';
|
||||
protected $useAutoIncrement = true;
|
||||
protected $returnType = 'array'; // Bisa diubah ke 'object' jika lebih suka
|
||||
|
||||
// Fitur Soft Delete
|
||||
protected $useSoftDeletes = true;
|
||||
|
||||
// Field yang boleh diisi (Mass Assignment)
|
||||
protected $allowedFields = ['cert_id', 'contact_id'];
|
||||
|
||||
// Fitur Otomatisasi Timestamp
|
||||
protected $useTimestamps = true;
|
||||
protected $dateFormat = 'datetime';
|
||||
protected $createdField = 'created_at';
|
||||
protected $updatedField = 'updated_at';
|
||||
protected $deletedField = 'deleted_at';
|
||||
|
||||
// Validasi Sederhana
|
||||
protected $validationRules = [
|
||||
'cert_id' => 'required|numeric',
|
||||
'contact_id' => 'required|numeric',
|
||||
];
|
||||
|
||||
protected $validationMessages = [
|
||||
'cert_id' => [
|
||||
'required' => 'ID Sertifikat wajib diisi.',
|
||||
'numeric' => 'ID Sertifikat harus berupa angka.'
|
||||
],
|
||||
'contact_id' => [
|
||||
'required' => 'ID Contact wajib diisi.',
|
||||
'numeric' => 'ID Contact harus berupa angka.'
|
||||
]
|
||||
];
|
||||
|
||||
protected $skipValidation = false;
|
||||
|
||||
// /**
|
||||
// * Contoh Method untuk mengambil data training lengkap dengan nama sertifikat dan contact
|
||||
// */
|
||||
// public function getTrainingDetails($id = null)
|
||||
// {
|
||||
// $builder = $this->db->table($this->table);
|
||||
// $builder->select('Certificates_Training.*, Certificates.cert_name, Contacts.contact_name'); // Asumsi nama tabel Contacts
|
||||
// $builder->join('Certificates', 'Certificates.cert_id = Certificates_Training.cert_id');
|
||||
// $builder->join('Contacts', 'Contacts.contact_id = Certificates_Training.contact_id');
|
||||
// $builder->where('Certificates_Training.deleted_at', null); // Pastikan yang belum dihapus
|
||||
|
||||
// if ($id) {
|
||||
// return $builder->where('cert_training_id', $id)->get()->getRowArray();
|
||||
// }
|
||||
|
||||
// return $builder->get()->getResultArray();
|
||||
// }
|
||||
}
|
||||
@ -26,6 +26,7 @@ foreach($products as $qdata) {
|
||||
|
||||
$now = date('Y-m-d\TH:i');
|
||||
$siteid = '';
|
||||
$contactid = '';
|
||||
$productid = '';
|
||||
$vendorid = '';
|
||||
$swversion = '';
|
||||
@ -62,6 +63,7 @@ if(isset($data)) {
|
||||
$acttypeid = $data['acttypeid'];
|
||||
$userid_owner = $data['userid_owner'];
|
||||
$activitystatus = $data['activitystatus'];
|
||||
$contactid = $data['contactid'];
|
||||
|
||||
// Untuk REFF : Menentukan mana yg dipakai untuk actid_ref
|
||||
if ($refer_page) {
|
||||
@ -109,6 +111,9 @@ if(isset($data)) {
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
|
||||
<input type='hidden' name='userid_creator' value='<?=$_SESSION['userid'];?>' />
|
||||
|
||||
<!-- Untuk Training -->
|
||||
<input type='hidden' id='current_actid' value='<?= isset($data['actid']) ? $data['actid'] : '' ?>' />
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
@ -194,7 +199,7 @@ if(isset($data)) {
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="owner" class="form-label border-start border-5 border-primary ps-1">Activity Owner</label>
|
||||
<select name="userid_owner" class="form-select form-select-sm select2">
|
||||
<select id="userid_owner" name="userid_owner" class="form-select form-select-sm select2">
|
||||
<option value="">-- Choose one --</option>
|
||||
<?php
|
||||
foreach ($users as $data) {
|
||||
@ -250,7 +255,7 @@ if(isset($data)) {
|
||||
Berita Acara Instalasi
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<div class="col-md-6 mb-2">
|
||||
<div class="form-check">
|
||||
@ -259,7 +264,7 @@ if(isset($data)) {
|
||||
User Training Certificate
|
||||
</label>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -269,7 +274,8 @@ if(isset($data)) {
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="form-group">
|
||||
<label for="status" class="form-label border-start border-5 border-primary ps-1">Activity Status</label>
|
||||
<select name="activitystatus" id="status" class="form-select form-select-sm" onchange='changestatus()' required>
|
||||
<!-- <select name="activitystatus" id="status" class="form-select form-select-sm" onchange='changestatus()' required> -->
|
||||
<select name="activitystatus" id="status" class="form-select form-select-sm" required>
|
||||
<option value="" disabled>-- Choose one --</option>
|
||||
<?php
|
||||
foreach ($stats as $statcode => $stat) {
|
||||
@ -633,51 +639,7 @@ if(isset($data)) {
|
||||
</h2>
|
||||
<div id="trainingAccordion" class="accordion-collapse collapse bg-white" aria-labelledby="trainingHeading" data-bs-parent="#accordionTraining">
|
||||
<div class="accordion-body">
|
||||
<input type='hidden' name='trainingid_delete' id='trainingid_delete' />
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-12 col-lg-5">
|
||||
<div class="form-group">
|
||||
<label for="trainingname" class="form-label">Nama</label>
|
||||
<input type='text' class="form-control form-control-sm trainingname" placeholder="Masukkan nama" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-lg-5">
|
||||
<div class="form-group">
|
||||
<label for="trainingdate" class="form-label">Tanggal</label>
|
||||
<input type='text' class="form-control form-control-sm trainingdate" placeholder="YYYY-MM-DD" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-2 col-12 col-lg-2 mt-2">
|
||||
<button type='button' class='btn btn-sm btn-success' onclick='addTrainingRow();'>Tambah</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div class='table-responsive'>
|
||||
<table class='table table-bordered table-sm' id='training_table'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style='width:45%;'>Nama Analis</th>
|
||||
<th style='width:45%;'>Tanggal</th>
|
||||
<th style='width:10%;'>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
if(isset($trainingdata)) {
|
||||
foreach($trainingdata as $data) {
|
||||
$trainingid = $data['trainingid'];
|
||||
$qname = $data['trainingname'];
|
||||
$qdate = $data['trainingdate'];
|
||||
echo "<tr> <input type='hidden' name='trainingnames[]' value='".$qname."'> <input type='hidden' name='trainingdates[]' value='".$qdate."' /> <td>$qname</td> <td>$qdate</td>".
|
||||
"<td> <button type='button' class='btn btn-sm btn-warning' onclick='deleteTrainingRow(this, $trainingid)'>Hapus</button> </td>".
|
||||
"</tr>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<span id='training_form'></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -804,14 +766,14 @@ $(document).ready(function() {
|
||||
// $("#calibration").prop('disabled', true);
|
||||
$("#installation").prop('disabled', true);
|
||||
// $("#offreport").prop('disabled', true);
|
||||
// $("#training").prop('disabled', true);
|
||||
$("#training").prop('disabled', true);
|
||||
}
|
||||
else if (this.value == '3') {
|
||||
$("#maintenance").prop('disabled', true);
|
||||
// $("#calibration").prop('disabled', false);
|
||||
$("#installation").prop('disabled', false);
|
||||
// $("#offreport").prop('disabled', false);
|
||||
// $("#training").prop('disabled', false);
|
||||
$("#training").prop('disabled', false);
|
||||
}
|
||||
else {
|
||||
// Ini akan menjadi default jika #acttypeid kosong atau bukan 5 dan 3
|
||||
@ -819,9 +781,30 @@ $(document).ready(function() {
|
||||
// $("#calibration").prop('disabled', true);
|
||||
$("#installation").prop('disabled', true);
|
||||
// $("#offreport").prop('disabled', true);
|
||||
// $("#training").prop('disabled', true);
|
||||
$("#training").prop('disabled', true);
|
||||
}
|
||||
}).trigger('change');
|
||||
|
||||
let siteid = $('#siteid').val();
|
||||
let current_actid = $('#current_actid').val();
|
||||
|
||||
// Perbaikan di sini: '!current_actid' otomatis mengecek null, undefined, atau string kosong ('')
|
||||
if (!current_actid) {
|
||||
current_actid = '';
|
||||
} else {
|
||||
current_actid = '/' + current_actid;
|
||||
}
|
||||
|
||||
// Untuk Training
|
||||
if (siteid !== '') {
|
||||
$.get("<?=base_url();?>activities/getsitecontact/" + siteid + current_actid, function(data) {
|
||||
$('#training_form').html(data);
|
||||
$('.select2').select2({
|
||||
theme: 'bootstrap-5',
|
||||
width: '100%'
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// acttext
|
||||
@ -832,7 +815,7 @@ function acttext_del(e, actdetailid) {
|
||||
var actdetailid = actdetailid.toString();
|
||||
var d = $('#actdetailid_delete');
|
||||
d.val(d.val()+' '+actdetailid);
|
||||
console.log(d.val());
|
||||
// console.log(d.val());
|
||||
}
|
||||
}
|
||||
|
||||
@ -884,35 +867,6 @@ function acttext_add() {
|
||||
})
|
||||
}
|
||||
|
||||
// $('#actby').change(function() {
|
||||
// var actby=this.value;
|
||||
// if(actby == 'P') {
|
||||
// var siteid=$('#siteid').val();
|
||||
// $.get("<?=base_url();?>/activities/getproduct/"+siteid, function(data) {
|
||||
// $('#actby_item').html(data);
|
||||
// $('.select2').select2({
|
||||
// theme: 'bootstrap-5',
|
||||
// width: '100%'
|
||||
// });
|
||||
// })
|
||||
// } else if (actby == 'V') {
|
||||
// $.get("<?=base_url();?>/activities/getvendor/0", function(data) {
|
||||
// $('#actby_item').html(data);
|
||||
// })
|
||||
// } else if (actby == 'C') {
|
||||
// $.get("<?=base_url();?>/activities/getconsumable/0", function(data) {
|
||||
// $('#actby_item').html(data);
|
||||
// $('.select2').select2({
|
||||
// theme: 'bootstrap-5',
|
||||
// width: '100%'
|
||||
// });
|
||||
// })
|
||||
// }else {
|
||||
// $('#actby_item').html('');
|
||||
// }
|
||||
|
||||
// })
|
||||
|
||||
// 1. Event ketika 'Activity by' diubah (Kode asli Anda dengan sedikit penyesuaian)
|
||||
$('#actby').change(function() {
|
||||
var actby = this.value;
|
||||
@ -949,8 +903,27 @@ $('#actby').change(function() {
|
||||
// 2. --- MODIFIKASI TAMBAHAN ---
|
||||
// Event ketika 'Site' diubah
|
||||
$('#siteid').change(function() {
|
||||
var actby = $('#actby').val(); // Cek status Activity by saat ini
|
||||
var siteid = this.value; // Ambil nilai siteid yang baru dipilih
|
||||
let actby = $('#actby').val(); // Cek status Activity by saat ini
|
||||
|
||||
let siteid = $('#siteid').val();
|
||||
let current_actid = $('#current_actid').val();
|
||||
if (!current_actid) {
|
||||
current_actid = '';
|
||||
} else {
|
||||
current_actid = '/' + current_actid;
|
||||
}
|
||||
// Khusus Untuk Training
|
||||
if(siteid == '') {
|
||||
$('#training_form').html('<div class="text-center">Please Fill Site First!</div>');
|
||||
} else {
|
||||
$.get("<?=base_url();?>activities/getsitecontact/" + siteid + current_actid, function(data) {
|
||||
$('#training_form').html(data);
|
||||
$('.select2').select2({
|
||||
theme: 'bootstrap-5',
|
||||
width: '100%'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Hanya jalankan AJAX ulang JIKA Activity by sedang memilih 'P'
|
||||
if (actby == 'P') {
|
||||
@ -988,12 +961,11 @@ $('#status').change(function() {
|
||||
// else { $("#maintenance").prop('disabled', true); $("#calibration").prop('disabled', true); $("#installation").prop('disabled', true); $("#offreport").prop('disabled', true); $("#training").prop('disabled', true);}
|
||||
// })
|
||||
$('#acttypeid').change(function() {
|
||||
if (this.value=='5'){ $("#maintenance").prop('disabled', false); $("#installation").prop('disabled', true);}
|
||||
else if (this.value=='3'){ $("#maintenance").prop('disabled', true); $("#installation").prop('disabled', false);}
|
||||
else { $("#maintenance").prop('disabled', true); $("#installation").prop('disabled', true);}
|
||||
if (this.value=='5'){ $("#maintenance").prop('disabled', false); $("#installation").prop('disabled', true); $("#training").prop('disabled', true);}
|
||||
else if (this.value=='3'){ $("#maintenance").prop('disabled', true); $("#installation").prop('disabled', false); $("#training").prop('disabled', false); }
|
||||
else { $("#maintenance").prop('disabled', true); $("#installation").prop('disabled', true); $("#training").prop('disabled', true);}
|
||||
})
|
||||
|
||||
|
||||
// reportdate change => opendate.value = reportdate.value
|
||||
$('#reportdate').change(function() {
|
||||
$('#opendate').val(this.value);
|
||||
@ -1012,7 +984,7 @@ function deleteRow(btn, itxid) {
|
||||
var itxid = itxid.toString();
|
||||
var d = $('#itxid_delete');
|
||||
d.val(d.val()+' '+itxid);
|
||||
console.log(d.val());
|
||||
// console.log(d.val());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1097,41 +1069,10 @@ function triggerChange(element){
|
||||
element.dispatchEvent(changeEvent);
|
||||
}
|
||||
|
||||
// Training Analyst
|
||||
function addTrainingRow() {
|
||||
var trainingname = $('.trainingname').val();
|
||||
var trainingdate = $('.trainingdate').val();
|
||||
|
||||
if (trainingname == "" || trainingdate == "") {
|
||||
alert("Nama dan tanggal tidak boleh kosong");
|
||||
return;
|
||||
}
|
||||
|
||||
var newRow = "<tr> <input type='hidden' name='trainingnames[]' value='"+trainingname+"'> <input type='hidden' name='trainingdates[]' value='"+trainingdate+"' />"+
|
||||
" <td>"+trainingname+"</td> <td>"+trainingdate+"</td>"+
|
||||
" <td class='text-center'> <button type='button' class='btn btn-sm btn-warning' onclick='deleteTrainingRow(this, 0)'>Hapus</button> </td> </tr>";
|
||||
$("#training_table").append(newRow);
|
||||
|
||||
$('.trainingname').val('');
|
||||
}
|
||||
function deleteTrainingRow(btn, trainingid) {
|
||||
if(confirm('Are you sure?')) {
|
||||
var row = btn.parentNode.parentNode;
|
||||
row.parentNode.removeChild(row);
|
||||
if (trainingid > 0) {
|
||||
var trainingid = trainingid.toString();
|
||||
var d = $('#trainingid_delete');
|
||||
d.val(d.val()+' '+trainingid);
|
||||
console.log(d.val());
|
||||
}
|
||||
}
|
||||
}
|
||||
// flatpickr for training date
|
||||
flatpickr(".trainingdate", { allowInput: true, dateFormat: "Y-m-d" });
|
||||
// Training checkbox enable/disable accordion
|
||||
function toggleTrainingAccordion() {
|
||||
var trainingChecked = $('#training').prop('checked');
|
||||
var trainingDisabled = $('#training').prop('disabled');
|
||||
let trainingChecked = $('#training').prop('checked');
|
||||
let trainingDisabled = $('#training').prop('disabled');
|
||||
if (trainingChecked && !trainingDisabled) {
|
||||
// Enable accordion
|
||||
$('#accordionTraining').find('button').prop('disabled', false);
|
||||
@ -1140,6 +1081,7 @@ function toggleTrainingAccordion() {
|
||||
$('#accordionTraining').find('button').removeClass('disabled');
|
||||
$('#accordionTraining').removeClass('opacity-50').removeClass('pointer-events-none');
|
||||
$('#accordionTraining').find('.accordion-button').attr('data-bs-toggle', 'collapse');
|
||||
|
||||
} else {
|
||||
// Disable accordion
|
||||
$('#accordionTraining').find('button').prop('disabled', true);
|
||||
@ -1184,53 +1126,48 @@ function toggleCalibrateAccordion() {
|
||||
$('#accordionCalibrate').find('.accordion-button').removeAttr('data-bs-toggle');
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize on page load
|
||||
toggleCalibrateAccordion();
|
||||
|
||||
// toggleCalibrateAccordion();
|
||||
// Event listener for calibration checkbox change
|
||||
$('#calibration').change(function() {
|
||||
toggleCalibrateAccordion();
|
||||
});
|
||||
|
||||
// $('#calibration').change(function() {
|
||||
// toggleCalibrateAccordion();
|
||||
// });
|
||||
// Event listener for calibration checkbox disable/enable (when acttypeid changes)
|
||||
$('#acttypeid').change(function() {
|
||||
toggleCalibrateAccordion();
|
||||
});
|
||||
|
||||
// $('#acttypeid').change(function() {
|
||||
// toggleCalibrateAccordion();
|
||||
// });
|
||||
// Calibrate
|
||||
function addCalibrateRow() {
|
||||
var calibratename = $('.calibratename').val();
|
||||
var calibratevalue = $('.calibratevalue').val();
|
||||
var calibrateunit = $('.calibrateunit').val();
|
||||
// function addCalibrateRow() {
|
||||
// var calibratename = $('.calibratename').val();
|
||||
// var calibratevalue = $('.calibratevalue').val();
|
||||
// var calibrateunit = $('.calibrateunit').val();
|
||||
|
||||
if (calibratename == "" || calibratevalue == "" || calibrateunit == "") {
|
||||
alert("Nama parameter, nilai, dan satuan tidak boleh kosong");
|
||||
return;
|
||||
}
|
||||
// if (calibratename == "" || calibratevalue == "" || calibrateunit == "") {
|
||||
// alert("Nama parameter, nilai, dan satuan tidak boleh kosong");
|
||||
// return;
|
||||
// }
|
||||
|
||||
var newRow = "<tr> <input type='hidden' name='calibratenames[]' value='"+calibratename+"'> <input type='hidden' name='calibratevalues[]' value='"+calibratevalue+"' /> <input type='hidden' name='calibrateunits[]' value='"+calibrateunit+"' />"+
|
||||
" <td>"+calibratename+"</td> <td>"+calibratevalue+"</td> <td>"+calibrateunit+"</td>"+
|
||||
" <td class='text-center'> <button type='button' class='btn btn-sm btn-warning' onclick='deleteCalibrateRow(this, 0)'>Hapus</button> </td> </tr>";
|
||||
$("#calibrate_table").append(newRow);
|
||||
// var newRow = "<tr> <input type='hidden' name='calibratenames[]' value='"+calibratename+"'> <input type='hidden' name='calibratevalues[]' value='"+calibratevalue+"' /> <input type='hidden' name='calibrateunits[]' value='"+calibrateunit+"' />"+
|
||||
// " <td>"+calibratename+"</td> <td>"+calibratevalue+"</td> <td>"+calibrateunit+"</td>"+
|
||||
// " <td class='text-center'> <button type='button' class='btn btn-sm btn-warning' onclick='deleteCalibrateRow(this, 0)'>Hapus</button> </td> </tr>";
|
||||
// $("#calibrate_table").append(newRow);
|
||||
|
||||
$('.calibratename').val('');
|
||||
$('.calibratevalue').val('');
|
||||
$('.calibrateunit').val('');
|
||||
}
|
||||
|
||||
function deleteCalibrateRow(btn, calibrateid) {
|
||||
if(confirm('Are you sure?')) {
|
||||
var row = btn.parentNode.parentNode;
|
||||
row.parentNode.removeChild(row);
|
||||
if (calibrateid > 0) {
|
||||
var calibrateid = calibrateid.toString();
|
||||
var d = $('#calibrateid_delete');
|
||||
d.val(d.val()+' '+calibrateid);
|
||||
console.log(d.val());
|
||||
}
|
||||
}
|
||||
}
|
||||
// $('.calibratename').val('');
|
||||
// $('.calibratevalue').val('');
|
||||
// $('.calibrateunit').val('');
|
||||
// }
|
||||
// function deleteCalibrateRow(btn, calibrateid) {
|
||||
// if(confirm('Are you sure?')) {
|
||||
// var row = btn.parentNode.parentNode;
|
||||
// row.parentNode.removeChild(row);
|
||||
// if (calibrateid > 0) {
|
||||
// var calibrateid = calibrateid.toString();
|
||||
// var d = $('#calibrateid_delete');
|
||||
// d.val(d.val()+' '+calibrateid);
|
||||
// console.log(d.val());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
</script>
|
||||
|
||||
<script src="<?=base_url();?>/assets/uppy/uppy-full.js"></script>
|
||||
|
||||
319
app/Views/activities_getsitecontacts.php
Normal file
319
app/Views/activities_getsitecontacts.php
Normal file
@ -0,0 +1,319 @@
|
||||
<div class='row mb-2'>
|
||||
<div class="col-12 text-end">
|
||||
<button type="button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#createContactModal">
|
||||
<i class="fa-solid fa-plus"></i> Tambah Analyst Baru
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="createContactModal" tabindex="-1" aria-labelledby="createContactModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title fw-bold" id="createContactModalLabel">Contact Editor</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<form id="formCreateContact" action="<?= base_url('/contacts/create'); ?>" method="POST">
|
||||
<div class="modal-body">
|
||||
<input type='hidden' name='siteid' id='siteid' value='<?= $siteid; ?>' />
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="firstname" class="col-sm-3 col-form-label">First Name <span class="text-danger">*</span></label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control form-control-sm" id="firstname" name="firstname" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="lastname" class="col-sm-3 col-form-label">Last Name <span class="text-danger">*</span></label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control form-control-sm" id="lastname" name="lastname" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="initial" class="col-sm-3 col-form-label">Initial <span class="text-danger">*</span></label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control form-control-sm" id="initial" name="initial" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="title" class="col-sm-3 col-form-label">Title</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control form-control-sm" id="title" name="title">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="birthdate" class="col-sm-3 col-form-label">Birthdate</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="date" class="form-control form-control-sm" id="birthdate" name="birthdate">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="email_1" class="col-sm-3 col-form-label">Email 1 <span class="text-danger">*</span></label>
|
||||
<div class="col-sm-9">
|
||||
<input type="email" class="form-control form-control-sm" id="email_1" name="email_1" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="email_2" class="col-sm-3 col-form-label">Email 2</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="email" class="form-control form-control-sm" id="email_2" name="email_2">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="phone" class="col-sm-3 col-form-label">Phone</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control form-control-sm" id="phone" name="phone">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="mobile_1" class="col-sm-3 col-form-label">Mobile 1</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control form-control-sm" id="mobile_1" name="mobile_1">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 align-items-center">
|
||||
<label for="mobile_2" class="col-sm-3 col-form-label">Mobile 2</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control form-control-sm" id="mobile_2" name="mobile_2">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer border-top-0">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="submit" class="btn btn-primary">Save Contact</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type='hidden' name='trainingid_delete' id='trainingid_delete' />
|
||||
<div class="row g-3 align-items-end mb-3">
|
||||
<div class="col-12 col-md-4">
|
||||
<label for="trainingname" class="form-label border-start border-5 border-primary ps-1 mb-1">Analyst Name</label>
|
||||
<select name="trainingname" id="trainingname" class="form-select form-select-sm select2 trainingname">
|
||||
<option value="">-- Choose one --</option>
|
||||
<?php
|
||||
if(!empty($sitecontacts)) {
|
||||
foreach ($sitecontacts as $data) {
|
||||
$qcontactid = $data['contactid'];
|
||||
$qcontactname = $data['firstname'] . " " . $data['lastname'];
|
||||
|
||||
// Siapkan data tambahannya
|
||||
$qcontactinitial = $data['initial'];
|
||||
$qcontacttitle = $data['title'];
|
||||
$qcontactemail = $data['email_1'];
|
||||
|
||||
// Simpan di data-attribute
|
||||
echo "<option value='$qcontactid' data-name='$qcontactname' data-initial='$qcontactinitial' data-title='$qcontacttitle' data-email='$qcontactemail'>$qcontactname</option>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12 col-md-3">
|
||||
<label for="trainingdate" class="form-label mb-1">Tanggal</label>
|
||||
<input type="text" name="trainingdate" id="trainingdate" class="form-control form-control-sm trainingdate"
|
||||
placeholder="YYYY-MM-DD" />
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-2">
|
||||
<div class="form-check mb-md-1">
|
||||
<input class="form-check-input" type="checkbox" value="1" id="validatealltraining"
|
||||
name="validatealltraining" checked>
|
||||
<label class="form-check-label" for="validatealltraining" style="font-size: 0.875rem;">
|
||||
Validasi Semua Peserta
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-3 d-grid">
|
||||
<button type="button" class="btn btn-sm btn-success" onclick="addTrainingRow();">Tambah</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div class='table-responsive'>
|
||||
<table class='table table-bordered table-sm' id='training_table'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style='width:2%;'>No</th>
|
||||
<th style='width:8%;'>Initial</th>
|
||||
<th style='width:30%;'>Nama Analyst</th>
|
||||
<th style='width:15%;'>Title</th>
|
||||
<th style='width:25%;'>Email</th>
|
||||
<th style='width:15%;'>Tanggal</th>
|
||||
<th style='width:11%;' class='text-center'>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
// Cek apakah ada data $traininguser
|
||||
if(isset($traininguser) && !empty($traininguser)):
|
||||
$no = 1;
|
||||
foreach ($traininguser as $tu):
|
||||
?>
|
||||
<tr>
|
||||
<td class="text-center"><?= $no++ ?></td>
|
||||
<td><?= esc($tu['initial']) ?></td>
|
||||
<td>
|
||||
<?= esc($tu['firstname']) ?> <?= esc($tu['lastname']) ?>
|
||||
<input type="hidden" name="trainingids[]" value="<?= esc($tu['contactid']) ?>">
|
||||
<input type="hidden" name="trainingnames[]" value="<?= esc($tu['firstname']) ?> <?= esc($tu['lastname']) ?>">
|
||||
<input type="hidden" name="trainingdates[]" value="<?= esc($tu['issued_date']) ?>">
|
||||
</td>
|
||||
<td><?= esc($tu['title']) ?></td>
|
||||
<td><?= esc($tu['email_1']) ?></td>
|
||||
<td><?= esc($tu['issued_date']) ?></td>
|
||||
<td class="text-center">
|
||||
<button type="button" class="btn btn-sm btn-danger" onclick="deleteTrainingRow(this, '<?= esc($tu['contactid']) ?>')">Hapus</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
endforeach;
|
||||
endif;
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
function addTrainingRow() {
|
||||
var selectEl = $('#trainingname');
|
||||
var selectedOption = selectEl.find('option:selected');
|
||||
|
||||
var contactid = selectEl.val();
|
||||
var trainingname = selectedOption.data('name');
|
||||
var trainingdate = $('#trainingdate').val();
|
||||
|
||||
if (!contactid || !trainingdate) {
|
||||
alert("Nama Analyst atau Tanggal tidak boleh kosong.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Agar Tidak Double Check
|
||||
var exists = false;
|
||||
// Selektor ini tetap berfungsi dengan baik karena mencari awalan 'trainingids'
|
||||
$("input[name^='trainingids']").each(function(){
|
||||
if($(this).val() == contactid){
|
||||
exists = true;
|
||||
}
|
||||
});
|
||||
|
||||
if(exists){
|
||||
alert("Analyst sudah ditambahkan.");
|
||||
return;
|
||||
}
|
||||
|
||||
var initial = selectedOption.data('initial') || '-';
|
||||
var title = selectedOption.data('title') || '-';
|
||||
var email = selectedOption.data('email') || '-';
|
||||
|
||||
var rowIndex = $('#training_table tbody tr').length;
|
||||
|
||||
var newRow = `
|
||||
<tr>
|
||||
<td class="text-center">${rowIndex + 1}</td>
|
||||
<td>${initial}</td>
|
||||
<td>
|
||||
${trainingname}
|
||||
<input type="hidden" name="trainingids[]" value="${contactid}">
|
||||
<input type="hidden" name="trainingnames[]" value="${trainingname}">
|
||||
<input type="hidden" name="trainingdates[]" value="${trainingdate}">
|
||||
</td>
|
||||
<td>${title}</td>
|
||||
<td>${email}</td>
|
||||
<td>${trainingdate}</td>
|
||||
<td class="text-center">
|
||||
<button type="button" class="btn btn-sm btn-danger" onclick="deleteTrainingRow(this)">Hapus</button>
|
||||
</td>
|
||||
</tr>`;
|
||||
|
||||
$("#training_table tbody").append(newRow);
|
||||
|
||||
// reset input
|
||||
selectEl.val('').trigger('change');
|
||||
}
|
||||
function deleteTrainingRow(btn, contactid) {
|
||||
if(confirm('Apakah Anda yakin ingin menghapus data ini?')) {
|
||||
$(btn).closest('tr').remove();
|
||||
|
||||
// Update nomor urut tabel otomatis untuk tampilan
|
||||
$('#training_table tbody tr').each(function(index) {
|
||||
$(this).find('td:first').text(index + 1);
|
||||
});
|
||||
|
||||
// Memasukkan ID yang dihapus ke input hidden 'trainingid_delete'
|
||||
if (contactid > 0) {
|
||||
var d = $('#trainingid_delete');
|
||||
var currentVal = d.val();
|
||||
d.val(currentVal ? currentVal + ',' + contactid : contactid);
|
||||
}
|
||||
}
|
||||
}
|
||||
flatpickr(".trainingdate", { allowInput: true, dateFormat: "Y-m-d" });
|
||||
|
||||
|
||||
$('#formCreateContact').submit(function(e) {
|
||||
// 1. Cegah form melakukan reload halaman bawaan HTML
|
||||
e.preventDefault();
|
||||
|
||||
// 2. Ambil URL action dan data dari form
|
||||
var url = $(this).attr('action');
|
||||
var formData = $(this).serialize();
|
||||
|
||||
// 3. Kirim data ke controller menggunakan AJAX POST
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
data: formData,
|
||||
success: function(response) {
|
||||
// Tutup modal dan bersihkan isian formnya
|
||||
$('#createContactModal').modal('hide');
|
||||
$('#formCreateContact')[0].reset();
|
||||
|
||||
// Tampilkan pesan sukses
|
||||
alert('Contact berhasil ditambahkan!');
|
||||
|
||||
// --- INI BAGIAN REFRESH-NYA ---
|
||||
var siteid = $('#siteid').val();
|
||||
var current_actid = $('#current_actid').val();
|
||||
|
||||
// Siapkan format url untuk current_actid (sama seperti logika sebelumnya)
|
||||
if (current_actid !== '' && current_actid !== undefined) {
|
||||
current_actid = '/' + current_actid;
|
||||
} else {
|
||||
current_actid = '';
|
||||
}
|
||||
|
||||
// Jalankan ulang $.get milikmu khusus untuk training_form
|
||||
if(siteid !== '') {
|
||||
$.get("<?=base_url();?>/activities/getsitecontact/" + siteid + current_actid, function(data) {
|
||||
$('#training_form').html(data);
|
||||
|
||||
// Re-inisialisasi select2 agar tampilannya kembali rapi
|
||||
$('.select2').select2({
|
||||
theme: 'bootstrap-5',
|
||||
width: '100%'
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
alert('Terjadi kesalahan saat menyimpan data!');
|
||||
console.error(xhr.responseText);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@ -3,209 +3,166 @@
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<div class="page-wrapper">
|
||||
<div class="container-fluid">
|
||||
<div class="row page-titles">
|
||||
<div class="col-md-5 align-self-center">
|
||||
<h4 class="text-themecolor">Certificates Training Management</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
<div class="row page-titles">
|
||||
<div class="col-md-5 align-self-center">
|
||||
<h4 class="text-themecolor">Certificates Training Management</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-12 mb-3">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" id="searchInput" class="form-control"
|
||||
placeholder="Search certificates by name, product, type, vendor, or dates...">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-2">
|
||||
<select id="statusFilter" class="form-select form-select-sm">
|
||||
<option value="">All Status</option>
|
||||
<option value="active">Active</option>
|
||||
<option value="expired">Expired</option>
|
||||
<option value="expiring">Expiring Soon</option>
|
||||
<option value="isval">Need Validation</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4 mb-2">
|
||||
<select id="typeFilter" class="form-select form-select-sm">
|
||||
<option value="">All Types</option>
|
||||
<option value="tms">TMS</option>
|
||||
<option value="joko">Jokoh</option>
|
||||
<option value="boeki">Tokyo Boeki</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4 mb-2">
|
||||
<button onclick="resetFilters()" class="btn btn-secondary btn-sm w-100">
|
||||
<i class="fas fa-redo"></i> Reset Filters
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="row mb-3">
|
||||
<div class="col-12 mb-3">
|
||||
<div class="input-group input-group-sm">
|
||||
<span class="input-group-text"><i class="fas fa-search"></i></span>
|
||||
<input type="text" id="searchInput" class="form-control"
|
||||
placeholder="Search certificates by name, product, type, vendor, or dates...">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 mb-2">
|
||||
<select id="productFilter" class="form-select form-select-sm">
|
||||
<option value="">--Product Filter--</option>
|
||||
<option value="tms">TMS</option>
|
||||
<option value="jokoh">Jokoh</option>
|
||||
<option value="mindray">Mindray</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4 mb-2">
|
||||
<select id="validationFilter" class="form-select form-select-sm">
|
||||
<option value="">--Validation Filter--</option>
|
||||
<option value="valid">Validated</option>
|
||||
<option value="unval">Unvalidated</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4 mb-2">
|
||||
<button onclick="resetFilters()" class="btn btn-secondary btn-sm w-100">
|
||||
<i class="fas fa-redo"></i> Reset Filters
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TABLE -->
|
||||
<div class="table-responsive" style="width: 100%;">
|
||||
<table id="certificatesTable" class="table table-striped table-hover border" style="width: 100%;">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th style="width:20%">Certificate Name</th>
|
||||
<th style="width:20%">Product/Equipment</th>
|
||||
<th style="width:20%">Activity Report</th>
|
||||
<th style="width:10%">Issue Date</th>
|
||||
<th style="width:10%">Expiry Date</th>
|
||||
<th style="width:10%">Status</th>
|
||||
<th class="text-center" style="width:10%">Action</th>
|
||||
<th style="width: 32%">Certificate</th>
|
||||
<th style="width: 38%">Act Report</th>
|
||||
<th style="width: 10%">Issue Date</th>
|
||||
<th style="width: 8%">Validation</th>
|
||||
<th class="text-center" style="width: 12%">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Validate Modal -->
|
||||
<div class="modal fade" id="validateModal" tabindex="-1" aria-labelledby="validateModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-warning text-dark">
|
||||
<h5 class="modal-title" id="validateModalLabel">
|
||||
<i class="fa-solid fa-check-double"></i> Validate Certificate
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Certificate ID</label>
|
||||
<p id="modalCertId" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Certificate Name</label>
|
||||
<p id="modalCertName" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Product/Equipment</label>
|
||||
<p id="modalProductName" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Serial Number</label>
|
||||
<p id="modalProductNumber" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Issue Date</label>
|
||||
<p id="modalIssueDate" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Expiry Date</label>
|
||||
<p id="modalExpiryDate" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Vendor</label>
|
||||
<p id="modalVendor" class="form-control-plaintext">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Activity Report</label>
|
||||
<p id="modalExpiryDate" class="form-control-plaintext">
|
||||
<a href="javascript:void(0)" class="activity-report-link text-decoration-none" data-certid="${certid}" style="color:#d43215b0;">Act ID - Nama AR - Nama User <i class="fa-solid fa-up-right-from-square"></i></a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class='row mb-3'>
|
||||
<label class='form-label fw-bold'>User Analyst yang ditraining</label>
|
||||
<div class='table-responsive'>
|
||||
<table class='table table-bordered table-sm'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style='width:10%'>No</th>
|
||||
<th style='width:45%'>Nama</th>
|
||||
<th style='width:45%'>Tanggal</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id='training-table'>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Ahmad Fauzi</td>
|
||||
<td>2024-01-15</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Budi Santoso</td>
|
||||
<td>2024-01-16</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Citra Dewi</td>
|
||||
<td>2024-01-17</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>Dian Pratama</td>
|
||||
<td>2024-01-18</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>Eko Wijaya</td>
|
||||
<td>2024-01-19</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-warning">
|
||||
<i class="fa-solid fa-info-circle"></i>
|
||||
<strong>Validation Information:</strong> Please review the certificate details above before validating. Once validated, the certificate status will change from "Need Validation" to "Active".
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 mb-3">
|
||||
<label class="form-label fw-bold">Certificate Preview</label>
|
||||
<div class="border rounded p-2" style="height: 500px; overflow: hidden;">
|
||||
<iframe id="certificatePreview" src="" style="width: 100%; height: 100%; border: none;"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="validateModal" tabindex="-1" aria-labelledby="validateModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-warning text-dark" id='modalHeader'>
|
||||
<h5 class="modal-title" id="validateModalLabel">
|
||||
Validate Training Certificate
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row border-bottom mb-3 pb-2">
|
||||
<div class="col-md-8">
|
||||
<label class="form-label "><i class="fa-solid fa-certificate me-2"></i>Certificate Name</label>
|
||||
<h5 id="modalCertName" class="mt-2 fw-bolder">-</h5>
|
||||
</div>
|
||||
<div class="col-md-4 text-md-end">
|
||||
<h5 id="modalValidation">-</h5>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
<i class="fa-solid fa-times"></i> Cancel
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning text-dark" id="confirmValidateBtn">
|
||||
<i class="fa-solid fa-check"></i> Validate Certificate
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label "><i class="fa-solid fa-book-medical me-2"></i>Certificate Number</label>
|
||||
<p id="modalCertNumber" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label "><i class="fa-solid fa-microchip me-2"></i>Product/Equipment</label>
|
||||
<p id="modalProductName" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label "><i class="fa-solid fa-hashtag me-2"></i>Serial Number</label>
|
||||
<p id="modalProductNumber" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label "><i class="fa-regular fa-hospital me-2"></i>Site</label>
|
||||
<p id="modalSiteName" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label "><i class="fa-solid fa-calendar-check me-2"></i>Analyst Name</label>
|
||||
<p id="modalAnalystName" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label "><i class="fa-solid fa-calendar-check me-2"></i>Issue Date</label>
|
||||
<p id="modalIssueDate" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-12 mb-4">
|
||||
<label class="form-label "><i class="fa-solid fa-file-lines me-2"></i>Activity Report Reference</label>
|
||||
<a href="javascript:void(0)" id="modalActivityLink" class="activity-report-link text-decoration-none fw-bolder" style="color:#d43215b0;">
|
||||
<div class="p-2 border rounded bg-light">
|
||||
<i class="fa-solid fa-up-right-from-square me-2"></i>
|
||||
<span id="modalActivity">-</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label"><i class="fa-solid fa-user me-2"></i>Owner Validation</label>
|
||||
<p id="modalValOwner" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label"><i class="fa-solid fa-user me-2"></i>SPV Validation</label>
|
||||
<p id="modalValSpv" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label class="form-label"><i class="fa-solid fa-user me-2"></i>Manager Validation</label>
|
||||
<p id="modalValManager" class="form-control-plaintext border-bottom fw-bolder">-</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id='modalInfo'></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 mb-3">
|
||||
<div class="border rounded p-2" style="height: 500px; overflow: hidden;">
|
||||
<iframe id="certificatePreview" src="" style="width: 100%; height: 100%; border: none;"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
<i class="fa-solid fa-times"></i> Cancel
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning text-dark" id="confirmValidateBtn">
|
||||
<i class="fa-solid fa-check"></i> Validate Certificate
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('style') ?>
|
||||
<style>
|
||||
#certificatesTable {
|
||||
width: 100% !important;
|
||||
}
|
||||
#certificatesTable_wrapper {
|
||||
width: 100% !important;
|
||||
}
|
||||
</style>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('script') ?>
|
||||
@ -213,7 +170,7 @@
|
||||
$(function () {
|
||||
|
||||
let table = $('#certificatesTable').DataTable({
|
||||
order: [[5, 'asc']],
|
||||
order: [[3, 'asc']], // Order by Validation Column
|
||||
pageLength: 25,
|
||||
dom: '<"row"<"col-md-6"l>>rtip',
|
||||
responsive: true,
|
||||
@ -224,53 +181,43 @@ $(function () {
|
||||
.then(response => response.json())
|
||||
.then(result => {
|
||||
callback({
|
||||
data: result.map(cert => {
|
||||
let certid = cert.certid || '';
|
||||
let certname = cert.certname || '-';
|
||||
let productname = cert.productname || '-';
|
||||
let productnumber = cert.productnumber || '';
|
||||
let issuedateRaw = cert.issuedate || '';
|
||||
let expirydateRaw = cert.expirydate || '';
|
||||
let vendor = cert.vendor || '-';
|
||||
let isval = cert.isval || null;
|
||||
data: result.map((cert, index) => {
|
||||
|
||||
let certid = cert.cert_id || '';
|
||||
let certname = cert.cert_name || '-';
|
||||
let certnumber = cert.cert_number || '';
|
||||
let actid = cert.actid || '';
|
||||
let issuedateRaw = cert.issued_date || '';
|
||||
let status = cert.status; // Validation status
|
||||
let fullname = cert.fullname;
|
||||
let activity_subject = cert.activity_subject;
|
||||
|
||||
let issuedate = '-';
|
||||
let expirydate = '-';
|
||||
let statusBadge = '<span class="badge bg-warning text-dark">Need Validation</span>';
|
||||
let validationBadge = '';
|
||||
|
||||
if (isval != null) {
|
||||
if (issuedateRaw && issuedateRaw !== '0000-00-00') {
|
||||
issuedate = new Date(issuedateRaw).toLocaleDateString('en-US', { month: 'short', day: '2-digit', year: 'numeric' });
|
||||
}
|
||||
if (issuedateRaw && issuedateRaw !== '0000-00-00') {
|
||||
let date = new Date(issuedateRaw);
|
||||
let day = String(date.getDate()).padStart(2, '0');
|
||||
let month = date.toLocaleString('en-US', { month: 'short' });
|
||||
let year = date.getFullYear();
|
||||
issuedate = `${day} ${month} ${year}`;
|
||||
}
|
||||
|
||||
if (expirydateRaw && expirydateRaw !== '0000-00-00') {
|
||||
expirydate = new Date(expirydateRaw).toLocaleDateString('en-US', { month: 'short', day: '2-digit', year: 'numeric' });
|
||||
let today = new Date();
|
||||
let expiryDate = new Date(expirydateRaw);
|
||||
let days = Math.ceil((expiryDate - today) / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (days < 0) {
|
||||
statusBadge = '<span class="badge bg-danger">Expired</span>';
|
||||
} else if (days <= 30) {
|
||||
statusBadge = '<span class="badge bg-info">Expiring Soon</span>';
|
||||
} else {
|
||||
statusBadge = '<span class="badge bg-success">Active</span>';
|
||||
}
|
||||
} else {
|
||||
statusBadge = '<span class="badge bg-secondary">N/A</span>';
|
||||
}
|
||||
if (status == 'unvalidated') {
|
||||
validationBadge = '<div class=""><span class="badge bg-warning text-dark">unvalidated</span></div>';
|
||||
} else {
|
||||
validationBadge = '<div class=""><span class="badge bg-success">validated</span></div>';
|
||||
}
|
||||
|
||||
return [
|
||||
`<strong>${certname}</strong><br><small class="text-muted">ID: ${certid}</small>`,
|
||||
`${productname}${productnumber ? '<br><small class="text-muted">SN: ' + productnumber + '</small>' : ''}`,
|
||||
`<a href="javascript:void(0)" class="activity-report-link text-decoration-none" data-certid="${certid}" style="color:#d43215b0;">Act ID - Nama AR - Nama User <i class="fa-solid fa-up-right-from-square"></i></a>`,
|
||||
`<strong>${certname}</strong><br><small class="text-muted">Cert# : ${certnumber}</small>`,
|
||||
`<a href="javascript:void(0)" class="activity-report-link text-decoration-none" data-certid="${certid}" data-actid="${actid}" style="color:#d43215b0;">#${actid} - ${activity_subject} <i class="fa-solid fa-up-right-from-square"></i></strong><br><small class="text-muted">Owner : ${fullname}</small></a>`,
|
||||
issuedate,
|
||||
expirydate,
|
||||
statusBadge,
|
||||
isval == null
|
||||
? `<div class="text-center"><button type="button" class="btn btn-warning text-dark btn-validate" data-certid="${certid}" data-certname="${certname}" data-productname="${productname}" data-productnumber="${productnumber}" data-issuedate="${issuedate}" data-expirydate="${expirydate}" data-vendor="${vendor}"><i class="fa-solid fa-check-double"></i></button></div>`
|
||||
: `<div class="text-center"><button type="button" class="btn btn-success btn-view" data-certid="${certid}"><i class="fa-regular fa-file-pdf"></i></button></div>`
|
||||
validationBadge,
|
||||
status == 'unvalidated'
|
||||
? `<div class="text-center"><button type="button" class="btn btn-sm btn-warning text-dark btn-validate-modal" data-certid="${certid}"><i class="fa-solid fa-triangle-exclamation me-2"></i>Need Validation</button></div>`
|
||||
: `<div class="text-center mb-1"><button type="button" class="btn btn-sm btn-info btn-validate-modal" data-certid="${certid}"><i class="fa-regular fa-eye me-2"></i>Detail</button></div>
|
||||
<div class="text-center"><button type="button" class="btn btn-sm btn-success btn-view" data-certnumber="${certnumber}"><i class="fa-regular fa-file-pdf me-2"></i>Generated PDF</button></div>`
|
||||
];
|
||||
})
|
||||
});
|
||||
@ -280,19 +227,26 @@ $(function () {
|
||||
callback({ data: [] });
|
||||
});
|
||||
},
|
||||
columnDefs: [{
|
||||
targets: 5,
|
||||
render: function (data, type) {
|
||||
if (type === 'sort') {
|
||||
if (data.includes('Need Validation')) return 1;
|
||||
if (data.includes('Expired')) return 2;
|
||||
if (data.includes('Expiring Soon')) return 3;
|
||||
if (data.includes('Active')) return 4;
|
||||
return 5;
|
||||
columnDefs: [
|
||||
{
|
||||
// Kondisi untuk Kolom 3 (Validation)
|
||||
targets: 3,
|
||||
render: function (data, type) {
|
||||
if (type === 'sort') {
|
||||
let val = data.toLowerCase();
|
||||
if (val.includes('unvalidated')) return 1;
|
||||
if (val.includes('validated')) return 2;
|
||||
return 3;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
return data;
|
||||
},
|
||||
{
|
||||
// Kondisi untuk Kolom 4 (Action)
|
||||
targets: [4],
|
||||
orderable: false
|
||||
}
|
||||
}]
|
||||
]
|
||||
});
|
||||
|
||||
$('#certificatesTable_filter').hide();
|
||||
@ -303,70 +257,111 @@ $(function () {
|
||||
});
|
||||
|
||||
// Type filter using DataTables column filter
|
||||
$('#typeFilter').on('change', function () {
|
||||
$('#productFilter').on('change', function () {
|
||||
let type = $(this).val();
|
||||
|
||||
// Filter by type column (index 1 - Certificate Name contains type info)
|
||||
if (type === '') {
|
||||
table.column(1).search('').draw();
|
||||
table.column(0).search('').draw();
|
||||
} else {
|
||||
// Capitalize first letter for search
|
||||
let typeText = type.charAt(0).toUpperCase() + type.slice(1);
|
||||
table.column(1).search(typeText).draw();
|
||||
table.column(0).search(typeText).draw();
|
||||
}
|
||||
});
|
||||
|
||||
// Status filter
|
||||
$('#statusFilter').on('change', function () {
|
||||
let map = {
|
||||
active: 'Active',
|
||||
expired: 'Expired',
|
||||
expiring: 'Expiring Soon',
|
||||
isval: 'Need Validation'
|
||||
};
|
||||
table.column(5).search(map[this.value] || '').draw();
|
||||
$('#validationFilter').on('change', function () {
|
||||
let validation = $(this).val();
|
||||
if (validation === '') {
|
||||
table.column(3).search('').draw();
|
||||
} else if (validation === 'unval') {
|
||||
table.column(3).search('unv').draw();
|
||||
} else if (validation === 'valid') {
|
||||
table.column(3).search('^validated$', true, false).draw();
|
||||
}
|
||||
});
|
||||
|
||||
// Reset
|
||||
window.resetFilters = function () {
|
||||
$('#searchInput, #statusFilter').val('');
|
||||
table.search('').columns().search('').order([5,'asc']).draw();
|
||||
$('#searchInput, #productFilter, #validationFilter').val('');
|
||||
table.search('').columns().search('').draw();
|
||||
};
|
||||
|
||||
// View PDF
|
||||
$(document).on('click', '.btn-view', function () {
|
||||
let certid = $(this).data('certid');
|
||||
window.open('<?= base_url('certificates/training/show/') ?>' + certid, '_blank');
|
||||
let certnumber = $(this).data('certnumber');
|
||||
window.open('<?= base_url('certificates/number/') ?>' + certnumber, '_blank');
|
||||
});
|
||||
|
||||
// Activity report
|
||||
$(document).on('click', '.activity-report-link', function () {
|
||||
let certid = $(this).data('certid');
|
||||
let actid = $(this).data('actid');
|
||||
window.open(
|
||||
'<?= base_url('certificates/training/activity/') ?>' + certid,
|
||||
'<?= base_url('activities/detail/') ?>' + actid,
|
||||
'_blank',
|
||||
'width=1200,height=800,scrollbars=yes,resizable=yes'
|
||||
);
|
||||
});
|
||||
|
||||
// Open modal
|
||||
$(document).on('click', '.btn-validate', function () {
|
||||
$(document).on('click', '.btn-validate-modal', function () {
|
||||
|
||||
let btn = $(this);
|
||||
let certid = btn.data('certid');
|
||||
|
||||
$('#modalCertId').text(btn.data('certid'));
|
||||
$('#modalCertName').text(btn.data('certname'));
|
||||
$('#modalProductName').text(btn.data('productname'));
|
||||
$('#modalProductNumber').text(btn.data('productnumber'));
|
||||
$('#modalIssueDate').text(btn.data('issuedate'));
|
||||
$('#modalExpiryDate').text(btn.data('expirydate'));
|
||||
$('#modalVendor').text(btn.data('vendor'));
|
||||
// POST API call to fetch certificate data
|
||||
$.post(
|
||||
'<?= base_url('certificates/api/showtraining') ?>',
|
||||
{ certid },
|
||||
function (data) {
|
||||
|
||||
$('#confirmValidateBtn').data('certid', btn.data('certid'));
|
||||
$('#certificatePreview').attr(
|
||||
'src',
|
||||
'<?= base_url('certificates/training/show/') ?>' + btn.data('certid')
|
||||
);
|
||||
// console.log(data);
|
||||
$('#modalCertName').text(data.cert_name || '-');
|
||||
$('#modalCertNumber').text(data.cert_number || '-');
|
||||
$('#modalProductName').text(data.productname || '-');
|
||||
$('#modalProductNumber').text(data.productnumber || '-');
|
||||
$('#modalIssueDate').text(data.issued_date || '-');
|
||||
$('#modalAnalystName').text(data.fullname || '-');
|
||||
$('#modalSiteName').text(data.sitename || '-');
|
||||
|
||||
// Cek status validasi
|
||||
const isValid = data.status === 'validated';
|
||||
const theme = isValid ? 'success' : 'warning';
|
||||
const icon = isValid ? 'fa-regular fa-circle-check' : 'fa-solid fa-triangle-exclamation';
|
||||
const note = isValid
|
||||
? 'Sertifikat Sudah Divalidasi'
|
||||
: 'Review data berikut dengan teliti, setelah divalidasi maka sertifikat akan dinyatakan <strong>Valid</strong> dan <strong>sah secara sistem.</strong>';
|
||||
|
||||
$('#modalHeader').removeClass('bg-warning bg-success').addClass(`bg-${theme} text-dark`);
|
||||
$('#modalValidation').html(
|
||||
`<span class="badge bg-${theme} text-dark py-2 px-3">
|
||||
<i class="${icon} me-2"></i>${data.status || '-'}
|
||||
</span>`
|
||||
);
|
||||
|
||||
$('#modalInfo').html(
|
||||
`<div class="alert alert-${theme} border-0 shadow-sm d-flex align-items-center">
|
||||
<i class="${icon} fs-4 me-3"></i>
|
||||
<div>
|
||||
<strong>Validation Note:</strong><br>
|
||||
${note}
|
||||
</div>
|
||||
</div>`
|
||||
);
|
||||
|
||||
$('#modalActivity').text(data.actid ? `#${data.actid} - ${data.subject || '-'}` : '-');
|
||||
$('#modalActivityLink').attr('data-actid', data.actid || '');
|
||||
$('#modalValOwner').html(data.user_validation_at ? `${data.username} - ${data.user_validation_at}<i class="fa-solid fa-circle-check text-success ms-2"></i>` : '-');
|
||||
$('#modalValSpv').html(data.spv_validation_at ? `${data.spvname} - ${data.spv_validation_at}<i class="fa-solid fa-circle-check text-success ms-2"></i>` : '-');
|
||||
$('#modalValManager').html(data.manager_validation_at ? `${data.managername} - ${data.manager_validation_at}<i class="fa-solid fa-circle-check text-success ms-2"></i>` : '-');
|
||||
},
|
||||
'json'
|
||||
).fail(function (xhr) {
|
||||
console.log(xhr);
|
||||
alert(xhr.responseText);
|
||||
});
|
||||
|
||||
// INI JANGAN DIUBAH
|
||||
$('#confirmValidateBtn').data('certid', certid);
|
||||
$('#certificatePreview').attr('src','<?= base_url('certificates/training/show/') ?>' + certid);
|
||||
|
||||
$('#validateModal').modal('show');
|
||||
});
|
||||
@ -379,63 +374,25 @@ $(function () {
|
||||
if (!confirm('Are you sure?')) return;
|
||||
|
||||
$.post(
|
||||
'<?= base_url('certificates/api/validateCertificate') ?>',
|
||||
'<?= base_url('certificates/api/validatecertificate') ?>',
|
||||
{ certid, certificateType},
|
||||
function (response) {
|
||||
|
||||
if (response.success) {
|
||||
$('#validateModal').modal('hide');
|
||||
alert(response.message);
|
||||
|
||||
// Generate and save PDF after successful validation
|
||||
$.post(
|
||||
'<?= base_url('certificates/api/generatepdf') ?>',
|
||||
{ certid, certificateType },
|
||||
function (pdfResponse) {
|
||||
if (pdfResponse.success) {
|
||||
alert('PDF generated and saved successfully!');
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Validation successful but PDF generation failed: ' + (pdfResponse.message || 'Unknown error'));
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
'json'
|
||||
).fail(function () {
|
||||
alert('Validation successful but failed to generate PDF');
|
||||
location.reload();
|
||||
});
|
||||
|
||||
location.reload();
|
||||
} else {
|
||||
alert(response.message || 'Validation failed');
|
||||
}
|
||||
|
||||
}, 'json'
|
||||
).fail(function () {
|
||||
$('#validateModal').modal('hide');
|
||||
alert('Server error.');
|
||||
).fail(function (xhr) {
|
||||
console.log(xhr);
|
||||
alert(xhr.responseText);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Delete training user
|
||||
window.deleteTrainingUser = function(btn) {
|
||||
if(confirm('Are you sure you want to delete this user?')) {
|
||||
var row = btn.closest('tr');
|
||||
row.remove();
|
||||
updateRowNumbers();
|
||||
}
|
||||
};
|
||||
|
||||
// Update row numbers after deletion
|
||||
function updateRowNumbers() {
|
||||
var tbody = $('#training-table');
|
||||
var rows = tbody.find('tr');
|
||||
rows.each(function(index) {
|
||||
$(this).find('td:first').text(index + 1);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
<?= $this->endSection() ?>
|
||||
@ -2,14 +2,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Maintenance Certificate - <?= $certificate['certname'] ?></title>
|
||||
<title><?= $certificate['certname'] ?></title>
|
||||
<style>
|
||||
@page {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
body {
|
||||
font-family: Arial;
|
||||
/* font-family: Arial; */
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
/* font-size: 12px; */
|
||||
@ -42,6 +43,18 @@
|
||||
color:#336600;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin :0;
|
||||
padding:0;
|
||||
color:#336600;
|
||||
}
|
||||
|
||||
.instrument-font {
|
||||
margin :0;
|
||||
padding:0;
|
||||
color:black;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 100%;
|
||||
margin: 0;
|
||||
@ -51,16 +64,17 @@
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: 230px;
|
||||
margin-bottom: 25px;
|
||||
margin-top: 235px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.site-name {
|
||||
text-align: center;
|
||||
margin-bottom: 55px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.detail-information {
|
||||
text-align: center;
|
||||
margin-bottom: 67px;
|
||||
/* margin-bottom: 137px; */
|
||||
margin-bottom: 26px;
|
||||
}
|
||||
h4 {
|
||||
margin :0;
|
||||
@ -73,12 +87,11 @@
|
||||
.signature-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-left: 17%;
|
||||
margin-bottom: 0px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.signature-table td {
|
||||
width: 50%; /* Membagi dua sisi sama rata */
|
||||
text-align: left;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
}
|
||||
.name {
|
||||
@ -98,57 +111,104 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Untuk DEV -->
|
||||
<!-- <div class="bg-container">
|
||||
<img src="<?=base_url();?>/assets/images/background_certificate/maintenance.jpeg">
|
||||
</div> -->
|
||||
|
||||
<?php for($i=0; $i<$count; $i++) : ?>
|
||||
<!-- Untuk PROD -->
|
||||
<div class="bg-container">
|
||||
<?php $bgPath = FCPATH . 'assets/images/background_certificate/maintenance.jpeg'; ?>
|
||||
<img src="<?php echo($bgPath) ?>">
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="instument-name">
|
||||
<h1> <<Nama Analis>> </h1>
|
||||
<h1><?= $certificate['fullname'] ?><?= $certificate['title'] ?></h1>
|
||||
</div>
|
||||
|
||||
<div class="site-name">
|
||||
<h1> at <<Nama Rumah Sakit / Laboratorium - Kota>> </h1>
|
||||
<h2> <?= $certificate['sitename'] ?> ~ <?= $certificate['city'] ?></h2>
|
||||
</div>
|
||||
|
||||
<div class="detail-information">
|
||||
<h4>In Recording of Participation and Successful</h4>
|
||||
<h4>Completion of Mindray Hematology Analyzer Training</h4>
|
||||
<h2>BC5140</h2>
|
||||
<h3>Date : February 05, 2026</h3>
|
||||
<!-- <h4>Serial Number: <?= $certificate['productnumber'] ?></h4> -->
|
||||
|
||||
<!-- <h4>has completed through a series of <?= $certificate['certtype'] ?></h4> -->
|
||||
<h3>In Recording of Participation and Successful Completion of</h3>
|
||||
<h3>User Training</h3>
|
||||
<h2 class='instrument-font'><?= $certificate['productname'] ?></h2>
|
||||
<h3>Date: <?= $certificate['issueddate'] ?></h3>
|
||||
|
||||
</div>
|
||||
|
||||
<table class="signature-table">
|
||||
<tr>
|
||||
<td>
|
||||
<span class="name"><br></span>
|
||||
<span class="name"><br></span>
|
||||
<span class="name"><br></span>
|
||||
<span class="name"><br></span>
|
||||
<img src="<?= $certificate['qrcode'] ?>">
|
||||
</td>
|
||||
<!-- <td>
|
||||
<span class="name">Adhitya Pranata Putra</span>
|
||||
<span class="position">Technical Support Manager</span>
|
||||
</td>
|
||||
</td> -->
|
||||
|
||||
<td>
|
||||
<span class="position">Trainer,</span>
|
||||
<span class="name"><br></span>
|
||||
<span class="name"><br></span>
|
||||
<span class="name"><br></span>
|
||||
<span class="name"><<Nama TSO>></span>
|
||||
<span class="position"><<Jabatan>></span>
|
||||
</td>
|
||||
<!-- <td>
|
||||
<span class="name"></span>
|
||||
<span class="position"></span>
|
||||
</td> -->
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="fo-wrapper">
|
||||
<p><<FO>></p>
|
||||
<p>FO.III.12/14.00/2020</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="bg-container">
|
||||
<img src="<?=base_url();?>/assets/images/background_certificate/maintenance.jpeg">
|
||||
<!-- Untuk Tanda Export PDF atau tidak -->
|
||||
<?php if (!isset($certificate['exportToPDF'])) : ?>
|
||||
<div class="container">
|
||||
<div class="instument-name">
|
||||
<h1><?= $certificate['fullname'] ?><?= $certificate['title'] ?></h1>
|
||||
</div>
|
||||
|
||||
<div class="site-name">
|
||||
<h2> <?= $certificate['sitename'] ?> ~ <?= $certificate['city'] ?></h2>
|
||||
</div>
|
||||
|
||||
<div class="detail-information">
|
||||
<!-- <h4>Serial Number: <?= $certificate['productnumber'] ?></h4> -->
|
||||
|
||||
<!-- <h4>has completed through a series of <?= $certificate['certtype'] ?></h4> -->
|
||||
<h3>In Recording of Participation and Successful Completion of</h3>
|
||||
<h3>User Training</h3>
|
||||
<h2 class='instrument-font'><?= $certificate['productname'] ?></h2>
|
||||
<h3>Date: <?= $certificate['issueddate'] ?></h3>
|
||||
|
||||
</div>
|
||||
|
||||
<table class="signature-table">
|
||||
<tr>
|
||||
<td>
|
||||
<img src="<?= $certificate['qrcode'] ?>">
|
||||
</td>
|
||||
<!-- <td>
|
||||
<span class="name">Adhitya Pranata Putra</span>
|
||||
<span class="position">Technical Support Manager</span>
|
||||
</td> -->
|
||||
|
||||
<!-- <td>
|
||||
<span class="name"></span>
|
||||
<span class="position"></span>
|
||||
</td> -->
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="fo-wrapper">
|
||||
<p>FO.III.12/14.00/2020</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php endfor ?>
|
||||
|
||||
<?php endif ?>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -42,11 +42,15 @@
|
||||
<ul aria-expanded="false" class="collapse">
|
||||
<li><a href="<?=base_url();?>certificates/installation">Installation</a></li>
|
||||
<li><a href="<?=base_url();?>certificates/maintenance">Maintenance</a></li>
|
||||
<!-- <li><a href="<?=base_url();?>certificates/training">Training</a></li> -->
|
||||
<li><a href="<?=base_url();?>certificates/training">Training</a></li>
|
||||
<!-- <li><a href="<?=base_url();?>certificates/calibration">Callibration</a></li> -->
|
||||
<!-- <li><a href="<?=base_url();?>certificates/official-report">Official Report</a></li> -->
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<?php if ( !($isTSM || $isPS) ): ?>
|
||||
<li> <a class="waves-effect waves-dark" href='<?=base_url();?>contacts' aria-expanded="false"> <i class="fa-solid fa-address-book"></i><span class="hide-menu">Contact</span></a> </li>
|
||||
<?php endif ?>
|
||||
|
||||
<li> <a class="waves-effect waves-dark" href='<?=base_url();?>guidebook' aria-expanded="false"> <i class="fa-solid fa-book"></i><span class='hide-menu'>Guidebook</span> </a> </li>
|
||||
<li> <a class="waves-effect waves-dark" href='https://clqms.services-summit.my.id/' aria-expanded="false"> <i class="fa-solid fa-microscope"></i><span class='hide-menu'>CLQMS</span> </a> </li>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user