Files
bij/app/Services/Admin/AdminExtraApiService.php
2026-04-21 05:59:39 +07:00

1107 lines
42 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\Admin;
use CodeIgniter\Database\BaseBuilder;
use CodeIgniter\Database\BaseConnection;
use Config\Database;
use Config\Services;
/**
* API admin tambahan: master perusahaan, presensi (lapangan/lembur/libur/jadwal/aktivitas), panel Ion, util backup.
*/
class AdminExtraApiService
{
protected BaseConnection $db;
public function __construct(?BaseConnection $db = null)
{
$this->db = $db ?? Database::connect();
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function kantorList(): array
{
$rows = $this->db->table('kantor')->orderBy('nama_kantor', 'ASC')->get()->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function kantorSave(array $input, ?int $id = null): array
{
$rules = [
'kode_kantor' => 'required|max_length[100]',
'nama_kantor' => 'required|max_length[50]',
'alamat_kantor' => 'required|max_length[255]',
'tipe' => 'required|max_length[50]',
'lat' => 'required',
'lng' => 'required',
'jarak_rekam_presensi' => 'permit_empty|integer',
];
$v = Services::validation();
$v->setRules($rules);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$row = [
'kode_kantor' => (string) $input['kode_kantor'],
'nama_kantor' => (string) $input['nama_kantor'],
'alamat_kantor' => (string) $input['alamat_kantor'],
'tipe' => (string) $input['tipe'],
'lat' => (float) $input['lat'],
'lng' => (float) $input['lng'],
'jarak_rekam_presensi' => (int) ($input['jarak_rekam_presensi'] ?? 30),
];
if ($id === null) {
$this->db->table('kantor')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_kantor' => (int) $this->db->insertID()]];
}
$this->db->table('kantor')->where('id_kantor', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function kantorDelete(int $id): array
{
$n = (int) $this->db->table('pegawai')->where('kantor', $id)->countAllResults();
if ($n > 0) {
return ['status' => 0, 'pesan' => 'Kantor masih dipakai ' . $n . ' pegawai.'];
}
$this->db->table('kantor')->where('id_kantor', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function unitKerjaList(): array
{
$rows = $this->db->table('unit_kerja')->orderBy('nama_unit_kerja', 'ASC')->get()->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function unitKerjaSave(array $input, ?int $id = null): array
{
$v = Services::validation();
$v->setRules(['nama_unit_kerja' => 'required|max_length[50]']);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$row = ['nama_unit_kerja' => (string) $input['nama_unit_kerja']];
if ($id === null) {
$this->db->table('unit_kerja')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_unit_kerja' => (int) $this->db->insertID()]];
}
$this->db->table('unit_kerja')->where('id_unit_kerja', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function unitKerjaDelete(int $id): array
{
$n = (int) $this->db->table('pegawai')->where('unit_kerja', $id)->countAllResults();
if ($n > 0) {
return ['status' => 0, 'pesan' => 'Unit masih dipakai pegawai.'];
}
$this->db->table('unit_kerja')->where('id_unit_kerja', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function golonganList(): array
{
$rows = $this->db->table('golongan')->orderBy('nama_golongan', 'ASC')->get()->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function golonganSave(array $input, ?int $id = null): array
{
$v = Services::validation();
$v->setRules(['nama_golongan' => 'permit_empty|max_length[100]']);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$row = ['nama_golongan' => (string) ($input['nama_golongan'] ?? '')];
if ($id === null) {
$this->db->table('golongan')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_golongan' => (int) $this->db->insertID()]];
}
$this->db->table('golongan')->where('id_golongan', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function golonganDelete(int $id): array
{
$n = (int) $this->db->table('pegawai')->where('golongan_pekerjaan', $id)->countAllResults();
if ($n > 0) {
return ['status' => 0, 'pesan' => 'Golongan masih dipakai pegawai.'];
}
$this->db->table('golongan')->where('id_golongan', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function jabatanList(): array
{
$rows = $this->db->table('jabatan')->orderBy('nama_jabatan', 'ASC')->get()->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function jabatanSave(array $input, ?int $id = null): array
{
$v = Services::validation();
$v->setRules(['nama_jabatan' => 'required|max_length[50]']);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$row = ['nama_jabatan' => (string) $input['nama_jabatan']];
if ($id === null) {
$this->db->table('jabatan')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_jabatan' => (int) $this->db->insertID()]];
}
$this->db->table('jabatan')->where('id_jabatan', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function jabatanDelete(int $id): array
{
$n = (int) $this->db->table('pegawai')->where('jabatan', $id)->countAllResults();
if ($n > 0) {
return ['status' => 0, 'pesan' => 'Jabatan masih dipakai pegawai.'];
}
$this->db->table('jabatan')->where('id_jabatan', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function beritaList(): array
{
$rows = $this->db->table('berita')->orderBy('tanggal', 'DESC')->get()->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function beritaSave(array $input, ?int $id = null): array
{
$v = Services::validation();
$v->setRules([
'tanggal' => 'required|valid_date',
'judul' => 'required|max_length[255]',
'isi' => 'required',
'photo' => 'permit_empty|max_length[255]',
]);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$photo = trim((string) ($input['photo'] ?? ''));
if ($photo === '') {
$photo = '-';
}
$row = [
'tanggal' => (string) $input['tanggal'],
'judul' => (string) $input['judul'],
'isi' => (string) $input['isi'],
'photo' => $photo,
];
if ($id === null) {
$this->db->table('berita')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_berita' => (int) $this->db->insertID()]];
}
$this->db->table('berita')->where('id_berita', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function beritaDelete(int $id): array
{
$this->db->table('berita')->where('id_berita', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function dilapanganList(?int $cabangKantorId = null): array
{
$b = $this->db->table('dilapangan d')
->select('d.*, p.nama_lengkap, p.nip')
->join('pegawai p', 'p.id_pegawai = d.pegawai', 'left');
$this->applyCabangPegawaiAlias($b, 'p', $cabangKantorId);
$rows = $b->orderBy('d.id_dilapangan', 'DESC')
->get()
->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function dilapanganSave(array $input, ?int $id = null, ?int $cabangKantorId = null): array
{
$v = Services::validation();
$v->setRules([
'pegawai' => 'required|integer',
'alasan' => 'required|max_length[255]',
]);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$pegawaiId = (int) $input['pegawai'];
if (! $this->pegawaiIdAllowedCabang($pegawaiId, $cabangKantorId)) {
return ['status' => 0, 'pesan' => 'Pegawai tidak termasuk cabang Anda.'];
}
if ($id !== null && $id > 0) {
$ex = $this->db->table('dilapangan')->select('pegawai')->where('id_dilapangan', $id)->get()->getRowArray();
if ($ex === null) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
if (! $this->pegawaiIdAllowedCabang((int) $ex['pegawai'], $cabangKantorId)) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
}
$row = [
'pegawai' => $pegawaiId,
'alasan' => (string) $input['alasan'],
];
if ($id === null) {
$this->db->table('dilapangan')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_dilapangan' => (int) $this->db->insertID()]];
}
$this->db->table('dilapangan')->where('id_dilapangan', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function dilapanganDelete(int $id, ?int $cabangKantorId = null): array
{
$ex = $this->db->table('dilapangan')->select('pegawai')->where('id_dilapangan', $id)->get()->getRowArray();
if ($ex === null) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
if (! $this->pegawaiIdAllowedCabang((int) $ex['pegawai'], $cabangKantorId)) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
$this->db->table('dilapangan')->where('id_dilapangan', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function lemburList(?int $cabangKantorId = null): array
{
$b = $this->db->table('lembur l')
->select('l.*, p.nama_lengkap, p.nip')
->join('pegawai p', 'p.id_pegawai = l.pegawai', 'left');
$this->applyCabangPegawaiAlias($b, 'p', $cabangKantorId);
$rows = $b->orderBy('l.tanggal_lembur', 'DESC')
->get()
->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function lemburSave(array $input, ?int $id = null, ?int $cabangKantorId = null): array
{
$v = Services::validation();
$v->setRules([
'tanggal_lembur' => 'required|valid_date',
'pegawai' => 'required|integer',
'masuk' => 'required|max_length[5]',
'beres' => 'required|max_length[5]',
'keterangan' => 'required|max_length[255]',
]);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$pegawaiId = (int) $input['pegawai'];
if (! $this->pegawaiIdAllowedCabang($pegawaiId, $cabangKantorId)) {
return ['status' => 0, 'pesan' => 'Pegawai tidak termasuk cabang Anda.'];
}
if ($id !== null && $id > 0) {
$ex = $this->db->table('lembur')->select('pegawai')->where('id_lembur', $id)->get()->getRowArray();
if ($ex === null) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
if (! $this->pegawaiIdAllowedCabang((int) $ex['pegawai'], $cabangKantorId)) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
}
$row = [
'tanggal_lembur' => (string) $input['tanggal_lembur'],
'pegawai' => $pegawaiId,
'masuk' => (string) $input['masuk'],
'beres' => (string) $input['beres'],
'keterangan' => (string) $input['keterangan'],
];
if ($id === null) {
$this->db->table('lembur')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_lembur' => (int) $this->db->insertID()]];
}
$this->db->table('lembur')->where('id_lembur', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function lemburDelete(int $id, ?int $cabangKantorId = null): array
{
$ex = $this->db->table('lembur')->select('pegawai')->where('id_lembur', $id)->get()->getRowArray();
if ($ex === null) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
if (! $this->pegawaiIdAllowedCabang((int) $ex['pegawai'], $cabangKantorId)) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
$this->db->table('lembur')->where('id_lembur', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function liburList(): array
{
$rows = $this->db->table('libur')->orderBy('tanggal_libur', 'DESC')->get()->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function liburSave(array $input, ?int $id = null): array
{
$v = Services::validation();
$v->setRules([
'tanggal_libur' => 'required|valid_date',
'keterangan_libur' => 'required|max_length[255]',
]);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$row = [
'tanggal_libur' => (string) $input['tanggal_libur'],
'keterangan_libur' => (string) $input['keterangan_libur'],
];
if ($id === null) {
$this->db->table('libur')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_libur' => (int) $this->db->insertID()]];
}
$this->db->table('libur')->where('id_libur', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function liburDelete(int $id): array
{
$this->db->table('libur')->where('id_libur', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function jadwalList(): array
{
$rows = $this->db->table('jadwal')->orderBy('nama_jadwal', 'ASC')->get()->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function jadwalSave(array $input, ?int $id = null): array
{
$v = Services::validation();
$v->setRules([
'nama_jadwal' => 'required|max_length[50]',
'toleransi_terlambat' => 'required|integer',
'toleransi_pulang_cepat' => 'required|integer',
'1_in' => 'required|max_length[5]',
'1_out' => 'required|max_length[5]',
'2_in' => 'required|max_length[5]',
'2_out' => 'required|max_length[5]',
'3_in' => 'required|max_length[5]',
'3_out' => 'required|max_length[5]',
'4_in' => 'required|max_length[5]',
'4_out' => 'required|max_length[5]',
'5_in' => 'required|max_length[5]',
'5_out' => 'required|max_length[5]',
'6_in' => 'permit_empty|max_length[5]',
'6_out' => 'permit_empty|max_length[5]',
'7_in' => 'permit_empty|max_length[5]',
'7_out' => 'permit_empty|max_length[5]',
]);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$row = [
'nama_jadwal' => (string) $input['nama_jadwal'],
'toleransi_terlambat' => (int) $input['toleransi_terlambat'],
'toleransi_pulang_cepat' => (int) $input['toleransi_pulang_cepat'],
'1_in' => (string) $input['1_in'],
'1_out' => (string) $input['1_out'],
'2_in' => (string) $input['2_in'],
'2_out' => (string) $input['2_out'],
'3_in' => (string) $input['3_in'],
'3_out' => (string) $input['3_out'],
'4_in' => (string) $input['4_in'],
'4_out' => (string) $input['4_out'],
'5_in' => (string) $input['5_in'],
'5_out' => (string) $input['5_out'],
'6_in' => (string) ($input['6_in'] ?? ''),
'6_out' => (string) ($input['6_out'] ?? ''),
'7_in' => (string) ($input['7_in'] ?? ''),
'7_out' => (string) ($input['7_out'] ?? ''),
];
if ($id === null) {
$this->db->table('jadwal')->insert($row);
return ['status' => 1, 'pesan' => 'Disimpan.', 'data' => ['id_jadwal' => (int) $this->db->insertID()]];
}
$this->db->table('jadwal')->where('id_jadwal', $id)->update($row);
return ['status' => 1, 'pesan' => 'Diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function jadwalDelete(int $id): array
{
$n = (int) $this->db->table('pegawai')->where('jadwal', $id)->countAllResults();
if ($n > 0) {
return ['status' => 0, 'pesan' => 'Jadwal dipakai ' . $n . ' pegawai.'];
}
$this->db->table('jadwal')->where('id_jadwal', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function aktifitasList(int $page, int $perPage, ?int $cabangKantorId = null): array
{
$perPage = max(5, min(100, $perPage));
$page = max(1, $page);
$offset = ($page - 1) * $perPage;
$countB = $this->db->table('aktifitas_harian a')->join('pegawai p', 'p.id_pegawai = a.pegawai', 'left');
$this->applyCabangPegawaiAlias($countB, 'p', $cabangKantorId);
$total = (int) $countB->countAllResults();
$rowsB = $this->db->table('aktifitas_harian a')
->select('a.*, p.nama_lengkap, p.nip')
->join('pegawai p', 'p.id_pegawai = a.pegawai', 'left');
$this->applyCabangPegawaiAlias($rowsB, 'p', $cabangKantorId);
$rows = $rowsB->orderBy('a.waktu_aktifitas', 'DESC')
->limit($perPage, $offset)
->get()
->getResultArray();
return [
'status' => 1,
'pesan' => 'OK',
'data' => [
'rows' => $rows,
'total' => $total,
'page' => $page,
'per_page' => $perPage,
'total_page' => (int) ceil($total / $perPage),
],
];
}
/**
* @return array{status: int, pesan: string}
*/
public function aktifitasDelete(int $id, ?int $cabangKantorId = null): array
{
$ex = $this->db->table('aktifitas_harian')->select('pegawai')->where('id_aktifitas_harian', $id)->get()->getRowArray();
if ($ex === null) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
if (! $this->pegawaiIdAllowedCabang((int) $ex['pegawai'], $cabangKantorId)) {
return ['status' => 0, 'pesan' => 'Data tidak ditemukan.'];
}
$this->db->table('aktifitas_harian')->where('id_aktifitas_harian', $id)->delete();
return ['status' => 1, 'pesan' => 'Dihapus.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function laporanCutiRentang(string $dari, string $sampai, ?int $cabangKantorId = null): array
{
$b = $this->db->table('cuti c')
->select('c.*, p.nama_lengkap, p.nip')
->join('pegawai p', 'p.id_pegawai = c.pegawai', 'left')
->where('c.tanggal_cuti >=', $dari)
->where('c.tanggal_cuti <=', $sampai);
$this->applyCabangPegawaiAlias($b, 'p', $cabangKantorId);
$rows = $b->orderBy('c.tanggal_cuti', 'DESC')
->get()
->getResultArray();
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows, 'dari' => $dari, 'sampai' => $sampai]];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function adminUsersList(): array
{
if (! $this->db->tableExists('admin_users')) {
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => []]];
}
$users = $this->db->table('admin_users')->orderBy('id', 'ASC')->get()->getResultArray();
$hasPegawaiCol = $this->db->fieldExists('id_pegawai', 'admin_users');
foreach ($users as &$u) {
unset($u['password'], $u['remember_code'], $u['activation_code'], $u['forgotten_password_code']);
$u['groups'] = $this->adminUserGroupNames((int) $u['id']);
$u['pegawai_proxy'] = null;
if ($hasPegawaiCol && $this->db->tableExists('pegawai')) {
$pid = (int) ($u['id_pegawai'] ?? 0);
if ($pid > 0) {
$p = $this->db->table('pegawai')
->select('nip, nama_lengkap')
->where('id_pegawai', $pid)
->get()
->getRowArray();
if ($p !== null) {
$u['pegawai_proxy'] = trim((string) ($p['nama_lengkap'] ?? '')) . ' (NIP ' . (string) ($p['nip'] ?? '') . ')';
}
}
}
}
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $users]];
}
/**
* @return list<string>
*/
public function adminUserGroupNames(int $userId): array
{
if (! $this->db->tableExists('admin_users_groups') || ! $this->db->tableExists('admin_groups')) {
return [];
}
$q = $this->db->table('admin_users_groups ug')
->select('g.name')
->join('admin_groups g', 'g.id = ug.group_id', 'inner')
->where('ug.user_id', $userId)
->get()
->getResultArray();
return array_values(array_filter(array_map(static fn ($r) => (string) ($r['name'] ?? ''), $q)));
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function adminGroupsList(): array
{
if (! $this->db->tableExists('admin_groups')) {
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => []]];
}
$rows = $this->db->table('admin_groups')->orderBy('id', 'ASC')->get()->getResultArray();
if ($this->db->tableExists('admin_users_groups')) {
foreach ($rows as &$r) {
$r['user_count'] = (int) $this->db->table('admin_users_groups')
->where('group_id', (int) ($r['id'] ?? 0))
->countAllResults();
}
} else {
foreach ($rows as &$r) {
$r['user_count'] = 0;
}
}
unset($r);
return ['status' => 1, 'pesan' => 'OK', 'data' => ['rows' => $rows]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function adminGroupCreate(array $input): array
{
if (! $this->db->tableExists('admin_groups')) {
return ['status' => 0, 'pesan' => 'Tabel admin_groups tidak ada.'];
}
$v = Services::validation();
$v->setRules([
'name' => 'required|max_length[20]|regex_match[/^[a-zA-Z0-9_]+$/]',
'description' => 'required|max_length[100]',
]);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$name = strtolower(trim((string) $input['name']));
if ($name === 'webmaster') {
return ['status' => 0, 'pesan' => 'Nama grup webmaster sudah dipakai sistem.'];
}
$exists = $this->db->table('admin_groups')->where('name', $name)->countAllResults();
if ($exists > 0) {
return ['status' => 0, 'pesan' => 'Nama grup sudah dipakai.'];
}
$this->db->table('admin_groups')->insert([
'name' => $name,
'description' => trim((string) $input['description']),
]);
return ['status' => 1, 'pesan' => 'Grup dibuat.', 'data' => ['id' => (int) $this->db->insertID()]];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string}
*/
public function adminGroupUpdate(int $groupId, array $input): array
{
if (! $this->db->tableExists('admin_groups')) {
return ['status' => 0, 'pesan' => 'Tabel admin_groups tidak ada.'];
}
$row = $this->db->table('admin_groups')->where('id', $groupId)->get()->getRowArray();
if ($row === null) {
return ['status' => 0, 'pesan' => 'Grup tidak ditemukan.'];
}
$v = Services::validation();
$v->setRules([
'name' => "required|max_length[20]|regex_match[/^[a-zA-Z0-9_]+$/]|is_unique[admin_groups.name,id,{$groupId}]",
'description' => 'required|max_length[100]',
]);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$name = strtolower(trim((string) $input['name']));
if (strtolower((string) $row['name']) === 'webmaster' && $name !== 'webmaster') {
return ['status' => 0, 'pesan' => 'Grup webmaster tidak boleh diubah namanya.'];
}
if ($name === 'webmaster' && strtolower((string) $row['name']) !== 'webmaster') {
return ['status' => 0, 'pesan' => 'Tidak boleh mengubah nama grup menjadi webmaster.'];
}
$this->db->table('admin_groups')->where('id', $groupId)->update([
'name' => $name,
'description' => trim((string) $input['description']),
]);
return ['status' => 1, 'pesan' => 'Grup diperbarui.'];
}
/**
* @return array{status: int, pesan: string}
*/
public function adminGroupDelete(int $groupId): array
{
if (! $this->db->tableExists('admin_groups')) {
return ['status' => 0, 'pesan' => 'Tabel admin_groups tidak ada.'];
}
$row = $this->db->table('admin_groups')->where('id', $groupId)->get()->getRowArray();
if ($row === null) {
return ['status' => 0, 'pesan' => 'Grup tidak ditemukan.'];
}
if (strtolower((string) $row['name']) === 'webmaster') {
return ['status' => 0, 'pesan' => 'Grup webmaster tidak boleh dihapus.'];
}
if ($this->db->tableExists('admin_users_groups')) {
$n = (int) $this->db->table('admin_users_groups')->where('group_id', $groupId)->countAllResults();
if ($n > 0) {
return ['status' => 0, 'pesan' => 'Grup masih dipakai ' . $n . ' pengguna. Pindahkan pengguna dulu.'];
}
}
$this->db->table('admin_groups')->where('id', $groupId)->delete();
return ['status' => 1, 'pesan' => 'Grup dihapus.'];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function adminUserCreate(array $input): array
{
if (! $this->db->tableExists('admin_users')) {
return ['status' => 0, 'pesan' => 'Tabel admin_users tidak ada.'];
}
$hasPegawaiCol = $this->db->fieldExists('id_pegawai', 'admin_users');
$rules = [
'username' => 'required|max_length[100]|is_unique[admin_users.username]',
'email' => 'permit_empty|max_length[100]',
'password' => 'required|min_length[6]',
'nama_lengkap' => 'required|max_length[100]',
'no_telepon' => 'permit_empty|max_length[25]',
'group_id' => 'required|integer',
];
if ($hasPegawaiCol) {
$rules['id_pegawai'] = 'permit_empty|integer';
}
$v = Services::validation();
$v->setRules($rules);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$gid = (int) $input['group_id'];
$g = $this->db->table('admin_groups')->where('id', $gid)->get()->getRowArray();
if ($g === null) {
return ['status' => 0, 'pesan' => 'Grup tidak valid.'];
}
if (strtolower((string) $g['name']) === 'webmaster') {
return ['status' => 0, 'pesan' => 'Tidak boleh membuat akun webmaster dari sini.'];
}
$idPegawaiInsert = null;
if ($hasPegawaiCol && $this->db->tableExists('pegawai')) {
$pid = (int) ($input['id_pegawai'] ?? 0);
if ($pid > 0) {
$okP = $this->db->table('pegawai')->where('id_pegawai', $pid)->countAllResults() > 0;
if (! $okP) {
return ['status' => 0, 'pesan' => 'Pegawai (proxy API) tidak ditemukan.'];
}
$idPegawaiInsert = $pid;
}
}
$hash = password_hash((string) $input['password'], PASSWORD_BCRYPT);
$rowInsert = [
'ip_address' => $this->db->escapeString(service('request')->getIPAddress()),
'username' => (string) $input['username'],
'password' => $hash,
'email' => (string) ($input['email'] ?? ''),
'created_on' => time(),
'active' => 1,
'first_name' => '',
'last_name' => '',
'photo' => '',
'nama_lengkap' => (string) $input['nama_lengkap'],
'no_telepon' => (string) ($input['no_telepon'] ?? ''),
];
if ($hasPegawaiCol) {
$rowInsert['id_pegawai'] = $idPegawaiInsert;
}
$this->db->table('admin_users')->insert($rowInsert);
$uid = (int) $this->db->insertID();
if ($this->db->tableExists('admin_users_groups')) {
$this->db->table('admin_users_groups')->insert(['user_id' => $uid, 'group_id' => $gid]);
}
return ['status' => 1, 'pesan' => 'Pengguna dibuat.', 'data' => ['id' => $uid]];
}
/**
* Satu pengguna untuk form edit (tanpa password).
*
* @return array{status: int, pesan: string, data?: mixed}
*/
public function adminUserShow(int $userId): array
{
if (! $this->db->tableExists('admin_users')) {
return ['status' => 0, 'pesan' => 'Tabel admin_users tidak ada.'];
}
$row = $this->db->table('admin_users')->where('id', $userId)->get()->getRowArray();
if ($row === null) {
return ['status' => 0, 'pesan' => 'Pengguna tidak ditemukan.'];
}
unset($row['password'], $row['remember_code'], $row['activation_code'], $row['forgotten_password_code']);
$row['groups'] = $this->adminUserGroupNames($userId);
$row['group_id'] = null;
if ($this->db->tableExists('admin_users_groups')) {
$ug = $this->db->table('admin_users_groups')
->where('user_id', $userId)
->orderBy('group_id', 'ASC')
->get()
->getRowArray();
if ($ug !== null) {
$row['group_id'] = (int) $ug['group_id'];
}
}
return ['status' => 1, 'pesan' => 'OK', 'data' => $row];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string}
*/
public function adminUserUpdate(int $userId, array $input): array
{
if (! $this->db->tableExists('admin_users')) {
return ['status' => 0, 'pesan' => 'Tabel admin_users tidak ada.'];
}
$existing = $this->db->table('admin_users')->where('id', $userId)->get()->getRowArray();
if ($existing === null) {
return ['status' => 0, 'pesan' => 'Pengguna tidak ditemukan.'];
}
$hasPegawaiCol = $this->db->fieldExists('id_pegawai', 'admin_users');
$rules = [
'username' => "required|max_length[100]|is_unique[admin_users.username,id,{$userId}]",
'email' => 'permit_empty|max_length[100]',
'nama_lengkap' => 'required|max_length[100]',
'no_telepon' => 'permit_empty|max_length[25]',
'group_id' => 'required|integer',
'active' => 'required|in_list[0,1]',
];
if ($hasPegawaiCol) {
$rules['id_pegawai'] = 'permit_empty|integer';
}
$v = Services::validation();
$v->setRules($rules);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$gidNew = (int) $input['group_id'];
$gNew = $this->db->table('admin_groups')->where('id', $gidNew)->get()->getRowArray();
if ($gNew === null) {
return ['status' => 0, 'pesan' => 'Grup tidak valid.'];
}
$currentNames = array_map('strtolower', $this->adminUserGroupNames($userId));
$isWebmaster = in_array('webmaster', $currentNames, true);
$newName = strtolower((string) $gNew['name']);
if ($newName === 'webmaster' && ! $isWebmaster) {
return ['status' => 0, 'pesan' => 'Tidak boleh mengangkat pengguna menjadi webmaster dari sini.'];
}
if ($isWebmaster && $newName !== 'webmaster') {
return ['status' => 0, 'pesan' => 'Tidak boleh mengubah grup akun webmaster.'];
}
$idPegawaiVal = null;
if ($hasPegawaiCol && $this->db->tableExists('pegawai')) {
$pid = (int) ($input['id_pegawai'] ?? 0);
if ($pid > 0) {
$okP = $this->db->table('pegawai')->where('id_pegawai', $pid)->countAllResults() > 0;
if (! $okP) {
return ['status' => 0, 'pesan' => 'Pegawai (proxy API) tidak ditemukan.'];
}
$idPegawaiVal = $pid;
}
}
$update = [
'username' => (string) $input['username'],
'email' => (string) ($input['email'] ?? ''),
'nama_lengkap' => (string) $input['nama_lengkap'],
'no_telepon' => (string) ($input['no_telepon'] ?? ''),
'active' => (int) $input['active'] === 1 ? 1 : 0,
];
if ($hasPegawaiCol) {
$update['id_pegawai'] = $idPegawaiVal;
}
$this->db->table('admin_users')->where('id', $userId)->update($update);
if ($this->db->tableExists('admin_users_groups')) {
$this->db->table('admin_users_groups')->where('user_id', $userId)->delete();
$this->db->table('admin_users_groups')->insert(['user_id' => $userId, 'group_id' => $gidNew]);
}
return ['status' => 1, 'pesan' => 'Pengguna diperbarui.'];
}
/**
* @param array<string, scalar|null> $input
*
* @return array{status: int, pesan: string}
*/
public function adminUserResetPassword(int $userId, array $input): array
{
$v = Services::validation();
$v->setRules(['password' => 'required|min_length[6]']);
if (! $v->run($input)) {
return ['status' => 0, 'pesan' => implode(' ', $v->getErrors())];
}
$exists = $this->db->table('admin_users')->where('id', $userId)->get()->getRowArray();
if ($exists === null) {
return ['status' => 0, 'pesan' => 'Pengguna tidak ditemukan.'];
}
$hash = password_hash((string) $input['password'], PASSWORD_BCRYPT);
$this->db->table('admin_users')->where('id', $userId)->update(['password' => $hash]);
return ['status' => 1, 'pesan' => 'Password diperbarui.'];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function backupListFiles(): array
{
$dir = WRITEPATH . 'admin_db_backup';
if (! is_dir($dir)) {
@mkdir($dir, 0755, true);
}
$files = glob($dir . DIRECTORY_SEPARATOR . '*.sql') ?: [];
rsort($files);
$out = [];
foreach ($files as $f) {
$out[] = [
'name' => basename($f),
'size' => filesize($f) ?: 0,
'mtime'=> date('Y-m-d H:i:s', (int) filemtime($f)),
];
}
return ['status' => 1, 'pesan' => 'OK', 'data' => ['directory' => $dir, 'files' => $out]];
}
/**
* @return array{status: int, pesan: string, data?: mixed}
*/
public function backupRun(bool $alsoLatest): array
{
$dir = WRITEPATH . 'admin_db_backup';
if (! is_dir($dir)) {
@mkdir($dir, 0755, true);
}
try {
$util = \Config\Database::utils();
$backup = $util->backup(['format' => 'sql']);
} catch (\Throwable $e) {
return ['status' => 0, 'pesan' => 'Backup gagal: ' . $e->getMessage()];
}
$name = date('Y-m-d_H-i-s') . '.sql';
$path = $dir . DIRECTORY_SEPARATOR . $name;
if (file_put_contents($path, $backup) === false) {
return ['status' => 0, 'pesan' => 'Gagal menulis file backup.'];
}
if ($alsoLatest) {
file_put_contents($dir . DIRECTORY_SEPARATOR . 'latest.sql', $backup);
}
return ['status' => 1, 'pesan' => 'Backup dibuat.', 'data' => ['file' => $name]];
}
/**
* @return array{status: int, pesan: string}
*/
public function backupDelete(string $filename): array
{
if (! preg_match('/^[a-zA-Z0-9._-]+\\.sql$/', $filename)) {
return ['status' => 0, 'pesan' => 'Nama file tidak valid.'];
}
$path = WRITEPATH . 'admin_db_backup' . DIRECTORY_SEPARATOR . $filename;
if (! is_file($path)) {
return ['status' => 0, 'pesan' => 'File tidak ada.'];
}
@unlink($path);
return ['status' => 1, 'pesan' => 'File dihapus.'];
}
public function backupFilePath(string $filename): ?string
{
if (! preg_match('/^[a-zA-Z0-9._-]+\\.sql$/', $filename)) {
return null;
}
$path = WRITEPATH . 'admin_db_backup' . DIRECTORY_SEPARATOR . $filename;
return is_file($path) ? $path : null;
}
private function applyCabangPegawaiAlias(BaseBuilder $b, string $alias, ?int $cabangKantorId): void
{
if ($cabangKantorId !== null && $cabangKantorId > 0) {
$b->where("{$alias}.kantor", $cabangKantorId);
}
}
private function pegawaiIdAllowedCabang(int $pegawaiId, ?int $cabangKantorId): bool
{
if ($cabangKantorId === null || $cabangKantorId <= 0) {
return true;
}
return $this->db->table('pegawai')->where('id_pegawai', $pegawaiId)->where('kantor', $cabangKantorId)->countAllResults() > 0;
}
}