init backend presensi
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Discipline\Controllers;
|
||||
|
||||
use App\Core\BaseApiController;
|
||||
use App\Modules\Discipline\Models\DisciplineLevelModel;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
|
||||
/**
|
||||
* API untuk config level disiplin (rentang poin -> tindakan sekolah).
|
||||
*/
|
||||
class DisciplineLevelController extends BaseApiController
|
||||
{
|
||||
/**
|
||||
* GET /api/discipline/levels
|
||||
*/
|
||||
public function index(): ResponseInterface
|
||||
{
|
||||
$model = new DisciplineLevelModel();
|
||||
$rows = $model->where('is_active', 1)
|
||||
->orderBy('min_score', 'ASC')
|
||||
->findAll();
|
||||
|
||||
$data = array_map(static function (array $r) {
|
||||
return [
|
||||
'id' => (int) $r['id'],
|
||||
'min_score' => (int) $r['min_score'],
|
||||
'max_score' => $r['max_score'] !== null ? (int) $r['max_score'] : null,
|
||||
'title' => $r['title'],
|
||||
'school_action'=> $r['school_action'],
|
||||
'executor' => $r['executor'],
|
||||
];
|
||||
}, $rows);
|
||||
|
||||
return $this->successResponse($data, 'Discipline levels');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Discipline\Controllers;
|
||||
|
||||
use App\Core\BaseApiController;
|
||||
use App\Modules\Academic\Models\ClassModel;
|
||||
use App\Modules\Academic\Models\StudentModel;
|
||||
use App\Modules\Auth\Services\AuthService;
|
||||
use App\Modules\Discipline\Models\StudentViolationModel;
|
||||
use App\Modules\Discipline\Models\ViolationModel;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Pencatatan pelanggaran siswa.
|
||||
*/
|
||||
class StudentViolationController extends BaseApiController
|
||||
{
|
||||
/**
|
||||
* GET /api/discipline/student-violations
|
||||
* Query: student_id?, class_id?, from_date?, to_date?
|
||||
*/
|
||||
public function index(): ResponseInterface
|
||||
{
|
||||
$auth = new AuthService();
|
||||
$user = $auth->currentUser();
|
||||
if (! $user) {
|
||||
return $this->errorResponse('Unauthorized', null, null, ResponseInterface::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
$studentId = (int) $this->request->getGet('student_id');
|
||||
$classId = (int) $this->request->getGet('class_id');
|
||||
$fromDate = $this->request->getGet('from_date');
|
||||
$toDate = $this->request->getGet('to_date');
|
||||
|
||||
$db = \Config\Database::connect();
|
||||
$builder = $db->table('student_violations AS sv')
|
||||
->select('sv.id, sv.student_id, sv.class_id, sv.violation_id, sv.reported_by_user_id, sv.occurred_at, sv.notes,
|
||||
s.name AS student_name, c.grade AS class_grade, c.major AS class_major, c.name AS class_name,
|
||||
v.title AS violation_title, v.score AS violation_score,
|
||||
vc.code AS category_code, vc.name AS category_name,
|
||||
u.name AS reporter_name')
|
||||
->join('students AS s', 's.id = sv.student_id', 'left')
|
||||
->join('classes AS c', 'c.id = sv.class_id', 'left')
|
||||
->join('violations AS v', 'v.id = sv.violation_id', 'left')
|
||||
->join('violation_categories AS vc', 'vc.id = v.category_id', 'left')
|
||||
->join('users AS u', 'u.id = sv.reported_by_user_id', 'left')
|
||||
->orderBy('sv.occurred_at', 'DESC')
|
||||
->orderBy('sv.id', 'DESC');
|
||||
|
||||
if ($studentId > 0) {
|
||||
$builder->where('sv.student_id', $studentId);
|
||||
}
|
||||
if ($classId > 0) {
|
||||
$builder->where('sv.class_id', $classId);
|
||||
}
|
||||
if ($fromDate) {
|
||||
$builder->where('sv.occurred_at >=', $fromDate . ' 00:00:00');
|
||||
}
|
||||
if ($toDate) {
|
||||
$builder->where('sv.occurred_at <=', $toDate . ' 23:59:59');
|
||||
}
|
||||
|
||||
$rows = $builder->get()->getResultArray();
|
||||
$data = array_map(static function (array $r) {
|
||||
$classLabel = null;
|
||||
if ($r['class_grade'] !== null || $r['class_major'] !== null || $r['class_name'] !== null) {
|
||||
$parts = array_filter([
|
||||
trim((string) ($r['class_grade'] ?? '')),
|
||||
trim((string) ($r['class_major'] ?? '')),
|
||||
trim((string) ($r['class_name'] ?? '')),
|
||||
]);
|
||||
$classLabel = implode(' ', $parts);
|
||||
}
|
||||
return [
|
||||
'id' => (int) $r['id'],
|
||||
'student_id' => (int) $r['student_id'],
|
||||
'student_name' => (string) $r['student_name'],
|
||||
'class_id' => $r['class_id'] !== null ? (int) $r['class_id'] : null,
|
||||
'class_label' => $classLabel,
|
||||
'violation_id' => (int) $r['violation_id'],
|
||||
'category_code' => $r['category_code'],
|
||||
'category_name' => $r['category_name'],
|
||||
'violation_title' => $r['violation_title'],
|
||||
'violation_score' => (int) $r['violation_score'],
|
||||
'reported_by_user_id' => $r['reported_by_user_id'] !== null ? (int) $r['reported_by_user_id'] : null,
|
||||
'reported_by_name' => $r['reporter_name'],
|
||||
'occurred_at' => $r['occurred_at'],
|
||||
'notes' => $r['notes'],
|
||||
];
|
||||
}, $rows);
|
||||
|
||||
return $this->successResponse($data, 'Student violations');
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/discipline/student-violations
|
||||
* Body: { student_id, violation_id, occurred_at?, notes? }
|
||||
* Hanya ADMIN, GURU_MAPEL, WALI_KELAS.
|
||||
*/
|
||||
public function create(): ResponseInterface
|
||||
{
|
||||
$auth = new AuthService();
|
||||
$user = $auth->currentUser();
|
||||
if (! $user) {
|
||||
return $this->errorResponse('Unauthorized', null, null, ResponseInterface::HTTP_UNAUTHORIZED);
|
||||
}
|
||||
$roleCodes = array_column($user['roles'], 'role_code');
|
||||
$allowedRoles = ['ADMIN', 'GURU_MAPEL', 'WALI_KELAS'];
|
||||
if (! array_intersect($allowedRoles, $roleCodes)) {
|
||||
return $this->errorResponse('Forbidden', null, null, ResponseInterface::HTTP_FORBIDDEN);
|
||||
}
|
||||
|
||||
$payload = $this->request->getJSON(true) ?? [];
|
||||
$studentId = (int) ($payload['student_id'] ?? 0);
|
||||
$violationId = (int) ($payload['violation_id'] ?? 0);
|
||||
$occurredAt = $payload['occurred_at'] ?? null;
|
||||
$notes = $payload['notes'] ?? null;
|
||||
|
||||
if ($studentId <= 0 || $violationId <= 0) {
|
||||
return $this->errorResponse('student_id dan violation_id wajib diisi', null, null, ResponseInterface::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$studentModel = new StudentModel();
|
||||
$classModel = new ClassModel();
|
||||
$violationModel = new ViolationModel();
|
||||
|
||||
$student = $studentModel->find($studentId);
|
||||
if (! $student) {
|
||||
return $this->errorResponse('Siswa tidak ditemukan', null, null, ResponseInterface::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$violation = $violationModel->find($violationId);
|
||||
if (! $violation || (int) $violation['is_active'] !== 1) {
|
||||
return $this->errorResponse('Pelanggaran tidak ditemukan atau tidak aktif', null, null, ResponseInterface::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$classId = $student->class_id !== null ? (int) $student->class_id : null;
|
||||
|
||||
if ($occurredAt === null || trim($occurredAt) === '') {
|
||||
$occurredAt = date('Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
$model = new StudentViolationModel();
|
||||
$model->insert([
|
||||
'student_id' => $studentId,
|
||||
'class_id' => $classId,
|
||||
'violation_id' => $violationId,
|
||||
'reported_by_user_id' => (int) $user['id'],
|
||||
'occurred_at' => $occurredAt,
|
||||
'notes' => $notes,
|
||||
]);
|
||||
|
||||
if ($model->errors()) {
|
||||
return $this->errorResponse(implode(' ', $model->errors()), $model->errors(), null, ResponseInterface::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
return $this->successResponse(null, 'Pelanggaran siswa berhasil dicatat');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Discipline\Controllers;
|
||||
|
||||
use App\Core\BaseApiController;
|
||||
use App\Modules\Discipline\Models\ViolationModel;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Admin CRUD untuk master violations (jenis pelanggaran).
|
||||
* Akses via /api/discipline/violations-admin (hanya ADMIN).
|
||||
*/
|
||||
class ViolationAdminController extends BaseApiController
|
||||
{
|
||||
/**
|
||||
* POST /api/discipline/violations-admin
|
||||
*/
|
||||
public function create(): ResponseInterface
|
||||
{
|
||||
$payload = $this->request->getJSON(true) ?? [];
|
||||
$categoryId = (int) ($payload['category_id'] ?? 0);
|
||||
$title = trim((string) ($payload['title'] ?? ''));
|
||||
$score = (int) ($payload['score'] ?? 0);
|
||||
$description = $payload['description'] ?? null;
|
||||
$isActive = array_key_exists('is_active', $payload) ? (int) (bool) $payload['is_active'] : 1;
|
||||
|
||||
if ($categoryId <= 0 || $title === '') {
|
||||
return $this->errorResponse('category_id dan title wajib diisi', null, null, ResponseInterface::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$model = new ViolationModel();
|
||||
$model->insert([
|
||||
'category_id' => $categoryId,
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
'score' => $score,
|
||||
'is_active' => $isActive,
|
||||
]);
|
||||
|
||||
if ($model->errors()) {
|
||||
return $this->errorResponse(implode(' ', $model->errors()), $model->errors(), null, ResponseInterface::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
return $this->successResponse(null, 'Pelanggaran berhasil ditambahkan');
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT /api/discipline/violations-admin/{id}
|
||||
*/
|
||||
public function update(int $id): ResponseInterface
|
||||
{
|
||||
$model = new ViolationModel();
|
||||
$row = $model->find($id);
|
||||
if (! $row) {
|
||||
return $this->errorResponse('Pelanggaran tidak ditemukan', null, null, ResponseInterface::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$payload = $this->request->getJSON(true) ?? [];
|
||||
$data = [];
|
||||
|
||||
if (isset($payload['category_id'])) {
|
||||
$data['category_id'] = (int) $payload['category_id'];
|
||||
}
|
||||
if (isset($payload['title'])) {
|
||||
$data['title'] = trim((string) $payload['title']);
|
||||
}
|
||||
if (isset($payload['description'])) {
|
||||
$data['description'] = $payload['description'];
|
||||
}
|
||||
if (isset($payload['score'])) {
|
||||
$data['score'] = (int) $payload['score'];
|
||||
}
|
||||
if (isset($payload['is_active'])) {
|
||||
$data['is_active'] = (int) (bool) $payload['is_active'];
|
||||
}
|
||||
|
||||
if ($data === []) {
|
||||
return $this->successResponse(null, 'Tidak ada perubahan');
|
||||
}
|
||||
|
||||
$model->update($id, $data);
|
||||
|
||||
if ($model->errors()) {
|
||||
return $this->errorResponse(implode(' ', $model->errors()), $model->errors(), null, ResponseInterface::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
return $this->successResponse(null, 'Pelanggaran berhasil diperbarui');
|
||||
}
|
||||
}
|
||||
|
||||
59
app/Modules/Discipline/Controllers/ViolationController.php
Normal file
59
app/Modules/Discipline/Controllers/ViolationController.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modules\Discipline\Controllers;
|
||||
|
||||
use App\Core\BaseApiController;
|
||||
use App\Modules\Discipline\Models\ViolationCategoryModel;
|
||||
use App\Modules\Discipline\Models\ViolationModel;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
|
||||
/**
|
||||
* Master data pelanggaran (kategori + item).
|
||||
* Biasanya diakses ADMIN / BK.
|
||||
*/
|
||||
class ViolationController extends BaseApiController
|
||||
{
|
||||
public function index(): ResponseInterface
|
||||
{
|
||||
$categoryModel = new ViolationCategoryModel();
|
||||
$violationModel = new ViolationModel();
|
||||
|
||||
$categories = $categoryModel->orderBy('code', 'ASC')->findAll();
|
||||
$violations = $violationModel
|
||||
->where('is_active', 1)
|
||||
->orderBy('category_id', 'ASC')
|
||||
->orderBy('score', 'DESC')
|
||||
->findAll();
|
||||
|
||||
// Group violations per category
|
||||
$byCategory = [];
|
||||
foreach ($categories as $cat) {
|
||||
$byCategory[$cat['id']] = [
|
||||
'id' => (int) $cat['id'],
|
||||
'code' => $cat['code'],
|
||||
'name' => $cat['name'],
|
||||
'description' => $cat['description'],
|
||||
'items' => [],
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($violations as $v) {
|
||||
$cid = (int) $v['category_id'];
|
||||
if (! isset($byCategory[$cid])) {
|
||||
continue;
|
||||
}
|
||||
$byCategory[$cid]['items'][] = [
|
||||
'id' => (int) $v['id'],
|
||||
'code' => $v['code'],
|
||||
'title' => $v['title'],
|
||||
'description' => $v['description'],
|
||||
'score' => (int) $v['score'],
|
||||
];
|
||||
}
|
||||
|
||||
$out = array_values($byCategory);
|
||||
|
||||
return $this->successResponse($out, 'Violation master data');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user