Drag & drop files here
+Help Documents
+documents to generate your CSV file
+diff --git a/README.md b/README.md index 5db8389..077c597 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ Aplikasi Web Sistem Absensi Sekolah Berbasis QR Code adalah sebuah proyek yang b - **Tambah, Ubah, Hapus(CRUD) data kelas.** - **Lihat, Tambah, Ubah, Hapus(CRUD) data petugas.** (khusus petugas yang login sebagai **`superadmin`**). - **Generate Laporan.** Generate laporan dalam bentuk pdf. +- **Import Banyak Siswa.** Menggunakan CSV delimiter koma (,), Contoh: [CSV](https://github.com/ikhsan3adi/absensi-sekolah-qr-code/blob/141ef728f01b14b89b43aee2c0c38680b0b60528/public/assets/file/csv_siswa_example.csv). + > [!NOTE] > diff --git a/app/Common.php b/app/Common.php index b5cd6c7..df02e3a 100644 --- a/app/Common.php +++ b/app/Common.php @@ -283,4 +283,20 @@ function countItems($items) } return 0; } +} + +//get csv value +if (!function_exists('getCSVInputValue')) { + function getCSVInputValue($array, $key, $dataType = 'string') + { + if (!empty($array)) { + if (!empty($array[$key])) { + return $array[$key]; + } + } + if ($dataType == 'int') { + return 0; + } + return ''; + } } \ No newline at end of file diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 2568fb0..aada782 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -43,6 +43,8 @@ $routes->post('cek', 'Scan::cekKode'); }); + + // Admin $routes->group('admin', function (RouteCollection $routes) { // Admin dashboard @@ -82,6 +84,16 @@ $routes->post('siswa/edit', 'Admin\DataSiswa::updateSiswa'); // admin hapus data siswa $routes->delete('siswa/delete/(:any)', 'Admin\DataSiswa::delete/$1'); + $routes->get('siswa/bulk', 'Admin\DataSiswa::bulkPostSiswa'); + + // POST Data Siswa + + $routes->group('siswa', ['namespace' => 'App\Controllers\Admin'], function ($routes) { + $routes->post('downloadCSVFilePost', 'DataSiswa::downloadCSVFilePost'); + $routes->post('generateCSVObjectPost', 'DataSiswa::generateCSVObjectPost'); + $routes->post('importCSVItemPost', 'DataSiswa::importCSVItemPost'); + $routes->post('deleteSelectedSiswa', 'DataSiswa::deleteSelectedSiswa'); + }); // admin lihat data guru @@ -143,7 +155,7 @@ $routes->group('general-settings', ['namespace' => 'App\Controllers\Admin'], function ($routes) { $routes->get('/', 'GeneralSettings::index'); $routes->post('update', 'GeneralSettings::generalSettingsPost'); - }); + }); }); diff --git a/app/Controllers/Admin/DataSiswa.php b/app/Controllers/Admin/DataSiswa.php index 05ec525..144f9d5 100644 --- a/app/Controllers/Admin/DataSiswa.php +++ b/app/Controllers/Admin/DataSiswa.php @@ -7,6 +7,7 @@ use App\Controllers\BaseController; use App\Models\JurusanModel; +use App\Models\UploadModel; use CodeIgniter\Exceptions\PageNotFoundException; class DataSiswa extends BaseController @@ -215,4 +216,98 @@ public function delete($id) ]); return redirect()->to('/admin/siswa'); } + + /** + * Delete Selected Posts + */ + public function deleteSelectedSiswa() + { + $siswaIds = inputPost('siswa_ids'); + $this->siswaModel->deleteMultiSelected($siswaIds); + } + + /* + *------------------------------------------------------------------------------------------------- + * IMPORT SISWA + *------------------------------------------------------------------------------------------------- + */ + + /** + * Bulk Post Upload + */ + public function bulkPostSiswa() + { + $data['title'] = 'Import Siswa'; + $data['ctx'] = 'siswa'; + $data['kelas'] = $this->kelasModel->getDataKelas(); + + return view('/admin/data/import-siswa', $data); + } + + /** + * Generate CSV Object Post + */ + public function generateCSVObjectPost() + { + $uploadModel = new UploadModel(); + //delete old txt files + $files = glob(FCPATH . 'uploads/tmp/*.txt'); + if (!empty($files)) { + foreach ($files as $item) { + @unlink($item); + } + } + $file = $uploadModel->uploadCSVFile('file'); + if (!empty($file) && !empty($file['path'])) { + $obj = $this->siswaModel->generateCSVObject($file['path']); + if (!empty($obj)) { + $data = [ + 'result' => 1, + 'numberOfItems' => $obj->numberOfItems, + 'txtFileName' => $obj->txtFileName, + ]; + echo json_encode($data); + exit(); + } + } + echo json_encode(['result' => 0]); + } + + /** + * Import CSV Item Post + */ + public function importCSVItemPost() + { + $txtFileName = inputPost('txtFileName'); + $index = inputPost('index'); + $siswa = $this->siswaModel->importCSVItem($txtFileName, $index); + if (!empty($siswa)) { + $data = [ + 'result' => 1, + 'siswa' => $siswa, + 'index' => $index + ]; + echo json_encode($data); + } else { + $data = [ + 'result' => 0, + 'index' => $index + ]; + echo json_encode($data); + } + } + + /** + * Download CSV File Post + */ + public function downloadCSVFilePost() + { + $submit = inputPost('submit'); + $response = \Config\Services::response(); + if ($submit == 'csv_siswa_template') { + return $response->download(FCPATH . 'assets/file/csv_siswa_template.csv', null); + } elseif ($submit == 'csv_guru_template') { + return $response->download(FCPATH . 'assets/file/csv_guru_template.csv', null); + } + } } diff --git a/app/Controllers/Admin/QRGenerator.php b/app/Controllers/Admin/QRGenerator.php index c649a52..7b34f31 100644 --- a/app/Controllers/Admin/QRGenerator.php +++ b/app/Controllers/Admin/QRGenerator.php @@ -162,6 +162,7 @@ public function downloadQrSiswa($idSiswa = null) ]); return redirect()->back(); } + try { $kelas = $this->getKelasJurusanSlug($siswa['id_kelas']) ?? 'tmp'; $this->qrCodeFilePath .= "qr-siswa/$kelas/"; @@ -330,11 +331,9 @@ protected function kelas(string $unique_code) protected function getKelasJurusanSlug(string $idKelas) { - $kelas = (new KelasModel) - ->join('tb_jurusan', 'tb_kelas.id_jurusan = tb_jurusan.id', 'left') - ->find($idKelas); + $kelas = (new KelasModel)->getKelas($idKelas);; if ($kelas) { - return url_title($kelas['kelas'] . ' ' . $kelas['jurusan'], lowercase: true); + return url_title($kelas->kelas . ' ' . $kelas->jurusan, lowercase: true); } else { return false; } diff --git a/app/Models/KelasModel.php b/app/Models/KelasModel.php index 56d0148..8179f24 100644 --- a/app/Models/KelasModel.php +++ b/app/Models/KelasModel.php @@ -46,7 +46,7 @@ public function getDataKelas() public function getKelas($id) { - return $this->builder->where('id_kelas', cleanNumber($id))->get()->getRow(); + return $this->builder->join('tb_jurusan', 'tb_kelas.id_jurusan = tb_jurusan.id')->where('id_kelas', cleanNumber($id))->get()->getRow(); } public function getCategoryTree($categoryId, $categories) diff --git a/app/Models/SiswaModel.php b/app/Models/SiswaModel.php index 122c246..d20d150 100644 --- a/app/Models/SiswaModel.php +++ b/app/Models/SiswaModel.php @@ -87,7 +87,7 @@ public function createSiswa($nis, $nama, $idKelas, $jenisKelamin, $noHp) 'id_kelas' => $idKelas, 'jenis_kelamin' => $jenisKelamin, 'no_hp' => $noHp, - 'unique_code' => sha1($nama . md5($nis . $noHp . $nama)) . substr(sha1($nis . rand(0, 100)), 0, 24) + 'unique_code' => generateToken() ]); } @@ -118,4 +118,94 @@ public function getSiswaCountByKelas($kelasId) return $this->whereIn('tb_siswa.id_kelas', $kelasIds, false)->countAllResults(); } + + //generate CSV object + public function generateCSVObject($filePath) + { + $array = array(); + $fields = array(); + $txtName = uniqid() . '.txt'; + $i = 0; + $handle = fopen($filePath, 'r'); + if ($handle) { + while (($row = fgetcsv($handle)) !== false) { + if (empty($fields)) { + $fields = $row; + continue; + } + foreach ($row as $k => $value) { + $array[$i][$fields[$k]] = $value; + } + $i++; + } + if (!feof($handle)) { + return false; + } + fclose($handle); + if (!empty($array)) { + $txtFile = fopen(FCPATH . 'uploads/tmp/' . $txtName, 'w'); + fwrite($txtFile, serialize($array)); + fclose($txtFile); + $obj = new \stdClass(); + $obj->numberOfItems = countItems($array); + $obj->txtFileName = $txtName; + @unlink($filePath); + return $obj; + } + } + return false; + } + + //import csv item + public function importCSVItem($txtFileName, $index) + { + $filePath = FCPATH . 'uploads/tmp/' . $txtFileName; + $file = fopen($filePath, 'r'); + $content = fread($file, filesize($filePath)); + $array = @unserialize($content); + if (!empty($array)) { + $i = 1; + foreach ($array as $item) { + if ($i == $index) { + $data = array(); + $data['nis'] = getCSVInputValue($item, 'nis', 'int'); + $data['nama_siswa'] = getCSVInputValue($item, 'nama_siswa'); + $data['id_kelas'] = getCSVInputValue($item, 'id_kelas', 'int'); + $data['jenis_kelamin'] = getCSVInputValue($item, 'jenis_kelamin'); + $data['no_hp'] = getCSVInputValue($item, 'no_hp'); + $data['unique_code'] = generateToken(); + + $this->insert($data); + return $data; + } + $i++; + } + } + } + + public function getSiswa($id) + { + return $this->where('id_siswa', cleanNumber($id))->get()->getRow(); + } + + //delete post + public function deleteSiswa($id) + { + $siswa = $this->getSiswa($id); + if (!empty($siswa)) { + //delete siswa + return $this->where('id_siswa', $siswa->id_siswa)->delete(); + } + return false; + } + + //delete multi post + public function deleteMultiSelected($siswaIds) + { + if (!empty($siswaIds)) { + foreach ($siswaIds as $id) { + $this->deleteSiswa($id); + } + } + } } diff --git a/app/Models/UploadModel.php b/app/Models/UploadModel.php index dc847be..d7b6640 100644 --- a/app/Models/UploadModel.php +++ b/app/Models/UploadModel.php @@ -55,6 +55,12 @@ public function uploadLogo($inputName) return $this->upload($inputName, "uploads/logo/", "logo_", ['jpg', 'jpeg', 'png', 'gif', 'svg']); } + //upload CSV file + public function uploadCSVFile($inputName) + { + return $this->upload($inputName, 'uploads/tmp/', 'temp_', ['csv']); + } + //check allowed file types public function checkAllowedFileTypes($fileName, $allowedTypes) { diff --git a/app/Views/admin/data/data-siswa.php b/app/Views/admin/data/data-siswa.php index 11f256e..fd9358f 100644 --- a/app/Views/admin/data/data-siswa.php +++ b/app/Views/admin/data/data-siswa.php @@ -17,6 +17,10 @@ add Tambah data siswa + + add Import CSV + +