add projet
This commit is contained in:
+767
@@ -0,0 +1,767 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\AuthorizedUser;
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\EmergencyContact;
|
||||
use App\Models\Enrollment;
|
||||
use App\Models\EventCharges;
|
||||
use App\Models\Event;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\ParentAttendanceReport;
|
||||
use App\Models\PromotionQueue;
|
||||
use App\Models\Refund;
|
||||
use App\Models\StudentAllergy;
|
||||
use App\Models\StudentClass;
|
||||
use App\Models\StudentMedicalCondition;
|
||||
use App\Models\Student;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Throwable;
|
||||
|
||||
class ParentController extends BaseApiController
|
||||
{
|
||||
protected User $user;
|
||||
protected Student $student;
|
||||
protected StudentClass $studentClass;
|
||||
protected Enrollment $enrollment;
|
||||
protected Configuration $config;
|
||||
protected EventCharges $charges;
|
||||
protected Event $event;
|
||||
protected StudentMedicalCondition $medicalCondition;
|
||||
protected StudentAllergy $allergy;
|
||||
protected Refund $refund;
|
||||
protected Invoice $invoice;
|
||||
protected ClassSection $classSection;
|
||||
protected PromotionQueue $promotion;
|
||||
protected EmergencyContact $emergencyContact;
|
||||
protected AuthorizedUser $authorizedUser;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->user = model(User::class);
|
||||
$this->student = model(Student::class);
|
||||
$this->studentClass = model(StudentClass::class);
|
||||
$this->enrollment = model(Enrollment::class);
|
||||
$this->config = model(Configuration::class);
|
||||
$this->charges = model(EventCharges::class);
|
||||
$this->event = model(Event::class);
|
||||
$this->medicalCondition = model(StudentMedicalCondition::class);
|
||||
$this->allergy = model(StudentAllergy::class);
|
||||
$this->refund = model(Refund::class);
|
||||
$this->invoice = model(Invoice::class);
|
||||
$this->classSection = model(ClassSection::class);
|
||||
$this->promotion = model(PromotionQueue::class);
|
||||
$this->emergencyContact = model(EmergencyContact::class);
|
||||
$this->authorizedUser = model(AuthorizedUser::class);
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$page = max(1, (int) ($this->request->getGet('page') ?? 1));
|
||||
$perPage = min(100, max(1, (int) ($this->request->getGet('per_page') ?? 20)));
|
||||
|
||||
$query = $this->user->newQuery()
|
||||
->select('users.*')
|
||||
->join('user_roles', 'user_roles.user_id', '=', 'users.id')
|
||||
->join('roles', 'roles.id', '=', 'user_roles.role_id')
|
||||
->where('roles.name', 'parent')
|
||||
->groupBy('users.id');
|
||||
|
||||
$result = $this->paginate($query, $page, $perPage);
|
||||
foreach ($result['data'] as &$parent) {
|
||||
unset($parent['password'], $parent['token']);
|
||||
}
|
||||
|
||||
return $this->success($result, 'Parents retrieved successfully');
|
||||
}
|
||||
|
||||
public function enrollClassesData($id)
|
||||
{
|
||||
try {
|
||||
$parentId = (int) $id;
|
||||
$parent = $this->user->find($parentId);
|
||||
if (!$parent) {
|
||||
return $this->error('Parent not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$schoolYear = (string) ($this->config->getConfig('school_year'));
|
||||
$semester = (string) ($this->config->getConfig('semester'));
|
||||
$lastDayOfRegistration = (string) ($this->config->getConfig('enrollment_deadline'));
|
||||
$schoolStartDate = (string) ($this->config->getConfig('school_start_date'));
|
||||
$withdrawalDeadline = (string) ($this->config->getConfig('refund_deadline'));
|
||||
|
||||
$selectedYear = (string) ($this->request->getGet('school_year') ?? $schoolYear);
|
||||
$isEditable = ($selectedYear === $schoolYear);
|
||||
|
||||
$students = DB::table('students')
|
||||
->where('parent_id', $parentId)
|
||||
->get()
|
||||
->map(fn($row) => (array) $row)
|
||||
->toArray();
|
||||
|
||||
$statusMap = [
|
||||
'admission under review' => 'admission under review',
|
||||
'payment pending' => 'payment pending',
|
||||
'enrolled' => 'enrolled',
|
||||
'withdraw under review' => 'withdraw under review',
|
||||
'refund pending' => 'refund pending',
|
||||
'withdrawn' => 'withdrawn',
|
||||
'denied' => 'denied',
|
||||
'waitlist' => 'waitlist',
|
||||
];
|
||||
|
||||
foreach ($students as &$student) {
|
||||
$studentId = (int) ($student['id'] ?? 0);
|
||||
|
||||
$classRow = DB::table('student_class')
|
||||
->select('class_section_id')
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $selectedYear)
|
||||
->first();
|
||||
$classSectionId = $classRow->class_section_id ?? null;
|
||||
$student['class_section'] = $classSectionId
|
||||
? ($this->classSection->getClassSectionNameBySectionId($classSectionId) ?? 'Class not Assigned')
|
||||
: 'Class not Assigned';
|
||||
|
||||
$enr = DB::table('enrollments')
|
||||
->select('enrollment_status', 'admission_status', 'is_withdrawn')
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $selectedYear)
|
||||
->orderByDesc('updated_at')
|
||||
->first();
|
||||
|
||||
if ($enr && isset($enr->admission_status)) {
|
||||
$student['admission_status'] = $enr->admission_status;
|
||||
if ($enr->admission_status === 'denied') {
|
||||
$student['enrollment_status'] = 'denied';
|
||||
} else {
|
||||
$est = $enr->enrollment_status ?? '';
|
||||
$student['enrollment_status'] = $statusMap[$est] ?? 'not enrolled';
|
||||
}
|
||||
} else {
|
||||
$student['admission_status'] = null;
|
||||
$student['enrollment_status'] = 'not enrolled';
|
||||
}
|
||||
|
||||
$student['disable_enroll'] = in_array(
|
||||
$student['enrollment_status'],
|
||||
['admission under review', 'payment pending', 'enrolled', 'withdraw under review', 'denied'],
|
||||
true
|
||||
);
|
||||
}
|
||||
unset($student);
|
||||
|
||||
$schoolYears = DB::table('enrollments')
|
||||
->select('school_year')
|
||||
->distinct()
|
||||
->orderByDesc('school_year')
|
||||
->get()
|
||||
->map(fn($row) => (array) $row)
|
||||
->toArray();
|
||||
if (empty($schoolYears)) {
|
||||
$schoolYears[] = ['school_year' => $schoolYear];
|
||||
}
|
||||
|
||||
return $this->success([
|
||||
'students' => $students,
|
||||
'schoolYears' => $schoolYears,
|
||||
'selectedYear' => $selectedYear,
|
||||
'isEditable' => $isEditable,
|
||||
'withdrawalDeadline' => $withdrawalDeadline,
|
||||
'lastDayOfRegistration'=> $lastDayOfRegistration,
|
||||
'schoolStartDate' => $schoolStartDate,
|
||||
], 'Enroll classes data');
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'enrollClassesData error: ' . $e->getMessage());
|
||||
return $this->error('Server error', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateEnrollments($id)
|
||||
{
|
||||
$parentId = (int) $id;
|
||||
$parent = $this->user->find($parentId);
|
||||
if (!$parent) {
|
||||
return $this->error('Parent not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$payload = $this->payloadData();
|
||||
$enroll = array_map('intval', (array) ($payload['enroll'] ?? []));
|
||||
$withdraw = array_map('intval', (array) ($payload['withdraw'] ?? []));
|
||||
|
||||
if (empty($enroll) && empty($withdraw)) {
|
||||
return $this->error('No students selected for enrollment or withdrawal.', Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$result = $this->processEnrollmentUpdate($parentId, $enroll, $withdraw);
|
||||
return $this->success($result, 'Enrollment updates processed');
|
||||
}
|
||||
|
||||
public function emergencyContacts($id)
|
||||
{
|
||||
$parentId = (int) $id;
|
||||
$rows = $this->emergencyContact->getEmergencyContactsByParentId($parentId);
|
||||
return $this->success($rows, 'Emergency contacts retrieved');
|
||||
}
|
||||
|
||||
public function saveEmergencyContact($id)
|
||||
{
|
||||
$parentId = (int) $id;
|
||||
$data = $this->payloadData();
|
||||
|
||||
$payload = [
|
||||
'parent_id' => $parentId,
|
||||
'emergency_contact_name' => trim((string) ($data['emergency_contact_name'] ?? '')),
|
||||
'cellphone' => trim((string) ($data['cellphone'] ?? '')),
|
||||
'email' => trim((string) ($data['email'] ?? '')) ?: null,
|
||||
'relation' => trim((string) ($data['relation'] ?? '')) ?: null,
|
||||
'semester' => (string) $this->config->getConfig('semester'),
|
||||
'school_year' => (string) $this->config->getConfig('school_year'),
|
||||
];
|
||||
|
||||
if ($payload['emergency_contact_name'] === '' || $payload['cellphone'] === '') {
|
||||
return $this->error('Name and cellphone are required', Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$idToUpdate = isset($data['id']) ? (int) $data['id'] : 0;
|
||||
if ($idToUpdate > 0) {
|
||||
$row = $this->emergencyContact->find($idToUpdate);
|
||||
if (!$row || (int) $row['parent_id'] !== $parentId) {
|
||||
return $this->error('Contact not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
$this->emergencyContact->update($idToUpdate, $payload);
|
||||
return $this->success(['id' => $idToUpdate], 'Emergency contact updated');
|
||||
}
|
||||
|
||||
$newId = $this->emergencyContact->insert($payload);
|
||||
if (!$newId) {
|
||||
return $this->error('Failed to save emergency contact', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
return $this->success(['id' => $newId], 'Emergency contact created');
|
||||
}
|
||||
|
||||
public function authorizedUsers($id)
|
||||
{
|
||||
$parentId = (int) $id;
|
||||
$rows = $this->authorizedUser->newQuery()
|
||||
->where('user_id', $parentId)
|
||||
->orderByDesc('created_at')
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
return $this->success($rows, 'Authorized users retrieved');
|
||||
}
|
||||
|
||||
public function addAuthorizedUser($id)
|
||||
{
|
||||
$parentId = (int) $id;
|
||||
$data = $this->payloadData();
|
||||
|
||||
$payload = [
|
||||
'user_id' => $parentId,
|
||||
'firstname' => trim((string) ($data['firstname'] ?? '')),
|
||||
'lastname' => trim((string) ($data['lastname'] ?? '')),
|
||||
'email' => trim((string) ($data['email'] ?? '')),
|
||||
'phone_number' => trim((string) ($data['phone_number'] ?? '')),
|
||||
'relation_to_user'=> trim((string) ($data['relation_to_user'] ?? '')),
|
||||
'status' => 'Pending',
|
||||
];
|
||||
|
||||
if ($payload['firstname'] === '' || $payload['lastname'] === '' || $payload['email'] === '' || $payload['phone_number'] === '') {
|
||||
return $this->error('Missing required fields', Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
if (!$this->authorizedUser->insert($payload)) {
|
||||
return $this->error('Failed to create authorized user', Response::HTTP_INTERNAL_SERVER_ERROR, $this->authorizedUser->errors());
|
||||
}
|
||||
return $this->success([], 'Authorized user request created');
|
||||
}
|
||||
|
||||
public function createStudent($id)
|
||||
{
|
||||
$parentId = (int) $id;
|
||||
$data = $this->payloadData();
|
||||
|
||||
$allowed = [
|
||||
'firstname', 'lastname', 'dob', 'age', 'gender', 'registration_grade', 'photo_consent', 'rfid_tag',
|
||||
];
|
||||
$payload = array_intersect_key($data, array_flip($allowed));
|
||||
$payload['parent_id'] = $parentId;
|
||||
$payload['is_new'] = isset($data['is_new']) ? (int) $data['is_new'] : 1;
|
||||
$payload['school_year'] = (string) $this->config->getConfig('school_year');
|
||||
$payload['semester'] = (string) $this->config->getConfig('semester');
|
||||
$payload['registration_date'] = Carbon::now('UTC')->format('Y-m-d');
|
||||
|
||||
if (empty($payload['firstname']) || empty($payload['lastname']) || empty($payload['gender'])) {
|
||||
return $this->error('firstname, lastname, and gender are required', Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$student = $this->student->create($payload);
|
||||
if (!$student) {
|
||||
return $this->error('Failed to create student', Response::HTTP_INTERNAL_SERVER_ERROR, $this->student->errors());
|
||||
}
|
||||
return $this->success(['id' => $student->id], 'Student created');
|
||||
}
|
||||
|
||||
public function updateStudent($id, $studentId)
|
||||
{
|
||||
$parentId = (int) $id;
|
||||
$studentId = (int) $studentId;
|
||||
|
||||
$row = $this->student->find($studentId);
|
||||
if (!$row || (int) $row['parent_id'] !== $parentId) {
|
||||
return $this->error('Student not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$data = $this->payloadData();
|
||||
$allowed = ['firstname', 'lastname', 'dob', 'age', 'gender', 'registration_grade', 'photo_consent', 'rfid_tag'];
|
||||
$payload = array_intersect_key($data, array_flip($allowed));
|
||||
if (empty($payload)) {
|
||||
return $this->error('No valid fields to update', Response::HTTP_UNPROCESSABLE_ENTITY);
|
||||
}
|
||||
|
||||
$ok = $this->student->update($studentId, $payload);
|
||||
if (!$ok) {
|
||||
return $this->error('Failed to update student', Response::HTTP_INTERNAL_SERVER_ERROR, $this->student->errors());
|
||||
}
|
||||
|
||||
return $this->success([], 'Student updated');
|
||||
}
|
||||
|
||||
public function deleteStudent($id, $studentId)
|
||||
{
|
||||
$parentId = (int) $id;
|
||||
$studentId = (int) $studentId;
|
||||
|
||||
$row = $this->student->find($studentId);
|
||||
if (!$row || (int) $row['parent_id'] !== $parentId) {
|
||||
return $this->error('Student not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$ok = $this->student->delete($studentId);
|
||||
if (!$ok) {
|
||||
return $this->error('Failed to delete student', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return $this->success([], 'Student deleted');
|
||||
}
|
||||
|
||||
private function processEnrollmentUpdate(int $parentId, array $enroll, array $withdraw): array
|
||||
{
|
||||
$schoolYear = (string) $this->config->getConfig('school_year');
|
||||
$semester = (string) $this->config->getConfig('semester');
|
||||
$lastDayOfRegistration = (string) $this->config->getConfig('enrollment_deadline');
|
||||
$today = Carbon::now('UTC')->format('Y-m-d');
|
||||
|
||||
if ($lastDayOfRegistration && $today > date('Y-m-d', strtotime($lastDayOfRegistration))) {
|
||||
if (!empty($enroll)) {
|
||||
return [
|
||||
'enrolled' => [],
|
||||
'withdrawn' => [],
|
||||
'messages' => ['Enrollment deadline has passed. New enrollments are not allowed.'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$enrolled = [];
|
||||
$withdrawn = [];
|
||||
$messages = [];
|
||||
|
||||
foreach ($enroll as $studentId) {
|
||||
$studentId = (int) $studentId;
|
||||
if ($studentId <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$existing = $this->enrollment->newQuery()
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->where('semester', $semester)
|
||||
->first();
|
||||
|
||||
if ($existing) {
|
||||
if ((int) ($existing['is_withdrawn'] ?? 0) === 1) {
|
||||
$ok = $this->enrollment->update((int) $existing['id'], [
|
||||
'is_withdrawn' => 0,
|
||||
'withdrawal_date' => null,
|
||||
'enrollment_status' => 'payment pending',
|
||||
'updated_at' => Carbon::now('UTC')->toDateTimeString(),
|
||||
]);
|
||||
if ($ok) {
|
||||
$enrolled[] = $studentId;
|
||||
$messages[] = "Re-enrolled student {$studentId}.";
|
||||
}
|
||||
} else {
|
||||
$messages[] = "Student {$studentId} already enrolled.";
|
||||
}
|
||||
} else {
|
||||
$ok = $this->enrollment->insert([
|
||||
'student_id' => $studentId,
|
||||
'parent_id' => $parentId,
|
||||
'school_year' => $schoolYear,
|
||||
'semester' => $semester,
|
||||
'enrollment_date' => $today,
|
||||
'is_withdrawn' => 0,
|
||||
'enrollment_status' => 'admission under review',
|
||||
'admission_status' => 'pending',
|
||||
'created_at' => Carbon::now('UTC')->toDateTimeString(),
|
||||
]);
|
||||
if ($ok) {
|
||||
$enrolled[] = $studentId;
|
||||
$messages[] = "Enrolled student {$studentId}.";
|
||||
}
|
||||
}
|
||||
|
||||
$this->applyPromotionAssignment($studentId, $schoolYear);
|
||||
}
|
||||
|
||||
foreach ($withdraw as $studentId) {
|
||||
$studentId = (int) $studentId;
|
||||
if ($studentId <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$enrollment = $this->enrollment->newQuery()
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->where('semester', $semester)
|
||||
->where('is_withdrawn', 0)
|
||||
->first();
|
||||
|
||||
if ($enrollment) {
|
||||
$ok = $this->enrollment->update((int) $enrollment['id'], [
|
||||
'withdrawal_date' => $today,
|
||||
'enrollment_status' => 'withdraw under review',
|
||||
'updated_at' => Carbon::now('UTC')->toDateTimeString(),
|
||||
]);
|
||||
if ($ok) {
|
||||
$withdrawn[] = $studentId;
|
||||
$messages[] = "Withdrawn student {$studentId}.";
|
||||
}
|
||||
|
||||
$invoice = $this->invoice->newQuery()
|
||||
->where('parent_id', $parentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->orderByDesc('created_at')
|
||||
->first();
|
||||
|
||||
if ($invoice) {
|
||||
$existingRefund = $this->refund->newQuery()
|
||||
->where('parent_id', $parentId)
|
||||
->where('invoice_id', $invoice['id'])
|
||||
->where('school_year', $schoolYear)
|
||||
->first();
|
||||
|
||||
if ($existingRefund) {
|
||||
$this->refund->update((int) $existingRefund['id'], [
|
||||
'reason' => 'Withdrawal under review for student ID ' . $studentId,
|
||||
'note' => null,
|
||||
'updated_by' => $this->getCurrentUserId(),
|
||||
]);
|
||||
} else {
|
||||
$this->refund->insert([
|
||||
'parent_id' => $parentId,
|
||||
'invoice_id' => $invoice['id'],
|
||||
'requested_at' => Carbon::now('UTC')->toDateTimeString(),
|
||||
'school_year' => $schoolYear,
|
||||
'status' => 'Pending review',
|
||||
'reason' => 'Withdrawal under review for student ID ' . $studentId,
|
||||
'request' => 'new',
|
||||
'semester' => $semester,
|
||||
'refund_paid_amount' => 0.0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'enrolled' => $enrolled,
|
||||
'withdrawn' => $withdrawn,
|
||||
'messages' => $messages,
|
||||
];
|
||||
}
|
||||
|
||||
private function applyPromotionAssignment(int $studentId, string $year): void
|
||||
{
|
||||
try {
|
||||
$row = $this->promotion->newQuery()
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year_to', $year)
|
||||
->first();
|
||||
if (!$row) {
|
||||
return;
|
||||
}
|
||||
|
||||
$targetSectionId = (int) ($row['to_class_section_id'] ?? 0);
|
||||
if ($targetSectionId <= 0) {
|
||||
$base = $this->classSection->getBaseSectionByClassId((int) $row['to_class_id']);
|
||||
if (!$base) {
|
||||
return;
|
||||
}
|
||||
$targetSectionId = (int) ($base['class_section_id'] ?? 0);
|
||||
}
|
||||
if ($targetSectionId <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$semester = (string) $this->config->getConfig('semester');
|
||||
$exists = $this->studentClass->newQuery()
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $year)
|
||||
->where('semester', $semester)
|
||||
->first();
|
||||
|
||||
$payload = [
|
||||
'student_id' => $studentId,
|
||||
'class_section_id' => $targetSectionId,
|
||||
'school_year' => $year,
|
||||
'semester' => $semester,
|
||||
'updated_by' => $this->getCurrentUserId(),
|
||||
'updated_at' => Carbon::now('UTC')->toDateTimeString(),
|
||||
];
|
||||
|
||||
if ($exists) {
|
||||
$this->studentClass->update((int) $exists['id'], $payload);
|
||||
} else {
|
||||
$payload['created_at'] = Carbon::now('UTC')->toDateTimeString();
|
||||
$this->studentClass->insert($payload);
|
||||
}
|
||||
|
||||
$this->promotion->update((int) $row['id'], [
|
||||
'status' => 'applied',
|
||||
'updated_at' => Carbon::now('UTC')->toDateTimeString(),
|
||||
'updated_by' => $this->getCurrentUserId(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'applyPromotionAssignment (API) failed: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function show($id = null)
|
||||
{
|
||||
$parent = $this->user->newQuery()
|
||||
->select('users.*')
|
||||
->join('user_roles', 'user_roles.user_id', '=', 'users.id')
|
||||
->join('roles', 'roles.id', '=', 'user_roles.role_id')
|
||||
->where('roles.name', 'parent')
|
||||
->where('users.id', $id)
|
||||
->first();
|
||||
|
||||
if (!$parent) {
|
||||
return $this->error('Parent not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
unset($parent['password'], $parent['token']);
|
||||
return $this->success($parent, 'Parent retrieved successfully');
|
||||
}
|
||||
|
||||
public function getStudents($id = null)
|
||||
{
|
||||
$parent = $this->user->find($id);
|
||||
if (!$parent) {
|
||||
return $this->error('Parent not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$students = $this->student->newQuery()
|
||||
->where('parent_id', $id)
|
||||
->get()
|
||||
->map(fn($row) => (array) $row)
|
||||
->toArray();
|
||||
|
||||
foreach ($students as &$student) {
|
||||
$classInfo = DB::table('student_class')
|
||||
->select('class_section.*', 'classes.name as class_name')
|
||||
->join('class_section', 'class_section.id', '=', 'student_class.class_section_id', 'left')
|
||||
->join('classes', 'classes.id', '=', 'class_section.class_id', 'left')
|
||||
->where('student_class.student_id', $student['id'])
|
||||
->orderByDesc('student_class.school_year')
|
||||
->first();
|
||||
|
||||
$student['current_class'] = $classInfo ? (array) $classInfo : null;
|
||||
|
||||
$student['medical_conditions'] = $this->medicalCondition
|
||||
->where('student_id', $student['id'])
|
||||
->findColumn('condition_name') ?? [];
|
||||
|
||||
$student['allergies'] = $this->allergy
|
||||
->where('student_id', $student['id'])
|
||||
->findColumn('allergy') ?? [];
|
||||
}
|
||||
|
||||
return $this->success($students, 'Students retrieved successfully');
|
||||
}
|
||||
|
||||
public function attendance($id)
|
||||
{
|
||||
try {
|
||||
$year = $this->request->getGet('school_year') ?? $this->config->getConfig('school_year');
|
||||
|
||||
$records = DB::table('attendance_data')
|
||||
->select('students.firstname', 'students.lastname', 'attendance_data.date', 'attendance_data.status', 'attendance_data.reason')
|
||||
->join('students', 'students.id', '=', 'attendance_data.student_id')
|
||||
->where('students.parent_id', $id)
|
||||
->where('attendance_data.school_year', $year)
|
||||
->orderByDesc('attendance_data.date')
|
||||
->get()
|
||||
->map(fn($row) => (array) $row)
|
||||
->toArray();
|
||||
|
||||
return $this->success($records, 'Attendance data retrieved successfully');
|
||||
} catch (Throwable $e) {
|
||||
return $this->error('Error fetching attendance: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function payments($id)
|
||||
{
|
||||
$invoices = DB::table('invoices')
|
||||
->where('parent_id', $id)
|
||||
->orderByDesc('created_at')
|
||||
->get()
|
||||
->map(fn($row) => (array) $row)
|
||||
->toArray();
|
||||
|
||||
return $this->success($invoices, 'Payments retrieved successfully');
|
||||
}
|
||||
|
||||
public function enrollments($id)
|
||||
{
|
||||
$schoolYear = $this->request->getGet('school_year') ?? $this->config->getConfig('school_year');
|
||||
$students = $this->student->where('parent_id', $id)->findAll();
|
||||
|
||||
$results = [];
|
||||
foreach ($students as $student) {
|
||||
$enrollment = $this->enrollment->newQuery()
|
||||
->where('student_id', $student['id'])
|
||||
->where('school_year', $schoolYear)
|
||||
->orderByDesc('created_at')
|
||||
->first();
|
||||
|
||||
$student['enrollment'] = $enrollment ?? [
|
||||
'enrollment_status' => 'not enrolled',
|
||||
'admission_status' => null,
|
||||
];
|
||||
$results[] = $student;
|
||||
}
|
||||
|
||||
return $this->success($results, 'Enrollment data retrieved successfully');
|
||||
}
|
||||
|
||||
public function enroll($id)
|
||||
{
|
||||
try {
|
||||
$data = $this->payloadData();
|
||||
if (empty($data['student_ids']) || !is_array($data['student_ids'])) {
|
||||
return $this->error('Invalid student_ids payload', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$parentId = (int) $id;
|
||||
$result = $this->processEnrollmentUpdate($parentId, array_map('intval', $data['student_ids']), []);
|
||||
return $this->success($result, 'Enrollment submitted successfully');
|
||||
} catch (Throwable $e) {
|
||||
return $this->error('Failed to enroll: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public function events($id)
|
||||
{
|
||||
$schoolYear = $this->config->getConfig('school_year');
|
||||
$semester = $this->config->getConfig('semester');
|
||||
|
||||
$events = $this->event->getActiveEvents($schoolYear, $semester);
|
||||
$charges = $this->charges->getChargesWithEventInfo($id, $schoolYear);
|
||||
|
||||
$chargeMap = [];
|
||||
foreach ($charges as $charge) {
|
||||
$chargeMap[$charge['student_id'] . ':' . $charge['event_id']] = $charge;
|
||||
}
|
||||
|
||||
return $this->success([
|
||||
'events' => $events,
|
||||
'charges' => $chargeMap,
|
||||
], 'Event participation data retrieved');
|
||||
}
|
||||
|
||||
public function updateParticipation($id)
|
||||
{
|
||||
try {
|
||||
$payload = $this->payloadData();
|
||||
$participations = $payload['participation'] ?? [];
|
||||
$schoolYear = $this->config->getConfig('school_year');
|
||||
$semester = $this->config->getConfig('semester');
|
||||
|
||||
foreach ($participations as $key => $value) {
|
||||
[$studentId, $eventId] = explode(':', $key);
|
||||
$existing = $this->charges->where([
|
||||
'parent_id' => $id,
|
||||
'student_id' => $studentId,
|
||||
'event_id' => $eventId,
|
||||
])->first();
|
||||
|
||||
if ($value === 'no') {
|
||||
if ($existing) {
|
||||
$this->charges->delete($existing['id']);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$event = $this->event->getEvent($eventId, $schoolYear);
|
||||
if ($existing) {
|
||||
$this->charges->update($existing['id'], ['participation' => $value]);
|
||||
} else {
|
||||
$this->charges->insert([
|
||||
'parent_id' => $id,
|
||||
'student_id' => $studentId,
|
||||
'event_id' => $eventId,
|
||||
'participation' => $value,
|
||||
'charged' => $event['amount'],
|
||||
'school_year' => $schoolYear,
|
||||
'semester' => $semester,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->success([], 'Participation updated successfully');
|
||||
} catch (Throwable $e) {
|
||||
return $this->error('Failed to update participation: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public function profile($id)
|
||||
{
|
||||
$user = $this->user->find($id);
|
||||
if (!$user) {
|
||||
return $this->error('Parent not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
unset($user['password'], $user['token']);
|
||||
return $this->success($user, 'Profile retrieved successfully');
|
||||
}
|
||||
|
||||
public function updateProfile($id)
|
||||
{
|
||||
try {
|
||||
$data = $this->payloadData();
|
||||
if (!$data) {
|
||||
return $this->error('Invalid JSON payload', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$allowed = ['firstname', 'lastname', 'cellphone', 'address_street', 'city', 'state', 'zip'];
|
||||
$update = array_intersect_key($data, array_flip($allowed));
|
||||
if (empty($update)) {
|
||||
return $this->error('No valid fields to update', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$this->user->update($id, $update);
|
||||
return $this->success([], 'Profile updated successfully');
|
||||
} catch (Throwable $e) {
|
||||
return $this->error('Failed to update profile: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user