283 lines
11 KiB
PHP
283 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\ClassSection;
|
|
use App\Models\Configuration;
|
|
use App\Models\Student;
|
|
use App\Models\StudentClass;
|
|
use App\Models\TeacherClass;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class AssignmentService
|
|
{
|
|
public function __construct(
|
|
protected User $userModel,
|
|
protected Configuration $configModel,
|
|
protected Student $studentModel,
|
|
protected ClassSection $classSectionModel,
|
|
protected TeacherClass $teacherClassModel,
|
|
protected StudentClass $studentClassModel
|
|
) {}
|
|
|
|
public function buildClassAssignments(array $filters = []): array
|
|
{
|
|
$currentSemester = (string) ($this->getConfigValue('semester') ?? '');
|
|
$currentSchoolYear = (string) ($this->getConfigValue('school_year') ?? '');
|
|
|
|
$selectedSemester = (string) ($filters['semester'] ?? $currentSemester);
|
|
$selectedYear = (string) ($filters['school_year'] ?? $currentSchoolYear);
|
|
$forApi = (bool) ($filters['for_api'] ?? false);
|
|
|
|
// Teacher classes (year-filtered; no semester filtering like your original code)
|
|
$teacherQ = $this->teacherClassModel->newQuery();
|
|
if ($selectedYear !== '') {
|
|
$teacherQ->where('school_year', $selectedYear);
|
|
}
|
|
$teacherClassesAll = $teacherQ->get()->toArray();
|
|
|
|
// Student classes (active + year-filtered)
|
|
$studentQ = method_exists($this->studentClassModel, 'active')
|
|
? $this->studentClassModel->active()
|
|
: $this->studentClassModel->newQuery()->where('is_active', 1);
|
|
|
|
if ($selectedYear !== '') {
|
|
// If your table is aliased in scopeActive(), you can keep student_class.school_year
|
|
$studentQ->where('school_year', $selectedYear);
|
|
}
|
|
$studentClassesAll = $studentQ->get()->toArray();
|
|
|
|
// Group teacher and student classes by section
|
|
$teacherBySection = [];
|
|
foreach ($teacherClassesAll as $tc) {
|
|
$secId = (int) ($tc['class_section_id'] ?? 0);
|
|
if ($secId > 0) {
|
|
$teacherBySection[$secId][] = $tc;
|
|
}
|
|
}
|
|
|
|
$studentsBySection = [];
|
|
foreach ($studentClassesAll as $sc) {
|
|
$secId = (int) ($sc['class_section_id'] ?? 0);
|
|
if ($secId > 0) {
|
|
$studentsBySection[$secId][] = $sc;
|
|
}
|
|
}
|
|
|
|
$allSectionIds = array_values(array_unique(array_merge(
|
|
array_keys($teacherBySection),
|
|
array_keys($studentsBySection)
|
|
)));
|
|
|
|
$classSections = [];
|
|
|
|
foreach ($allSectionIds as $classSectionId) {
|
|
$teacherClasses = $teacherBySection[$classSectionId] ?? [];
|
|
$studentClasses = $studentsBySection[$classSectionId] ?? [];
|
|
|
|
if (empty($teacherClasses) && empty($studentClasses)) {
|
|
continue;
|
|
}
|
|
|
|
$classSectionName = $this->resolveClassSectionName($classSectionId);
|
|
|
|
$mainTeachers = [];
|
|
$teacherAssistants = [];
|
|
$sectionSemester = '';
|
|
$sectionSchoolYear = '';
|
|
$description = '';
|
|
|
|
// Teacher metadata + names
|
|
foreach ($teacherClasses as $teacherClass) {
|
|
$teacherId = (int) ($teacherClass['teacher_id'] ?? 0);
|
|
if ($teacherId > 0) {
|
|
$teacher = $this->userModel->newQuery()->find($teacherId);
|
|
if ($teacher) {
|
|
$teacherName = trim(
|
|
(string) ($teacher->firstname ?? '') . ' ' . (string) ($teacher->lastname ?? '')
|
|
);
|
|
|
|
if ($teacherName !== '') {
|
|
if (($teacherClass['position'] ?? '') === 'main') {
|
|
$mainTeachers[] = $teacherName;
|
|
} elseif (($teacherClass['position'] ?? '') === 'ta') {
|
|
$teacherAssistants[] = $teacherName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($sectionSemester === '' && !empty($teacherClass['semester'])) {
|
|
$sectionSemester = (string) $teacherClass['semester'];
|
|
}
|
|
if ($sectionSchoolYear === '' && !empty($teacherClass['school_year'])) {
|
|
$sectionSchoolYear = (string) $teacherClass['school_year'];
|
|
}
|
|
if ($description === '' && !empty($teacherClass['description'])) {
|
|
$description = (string) $teacherClass['description'];
|
|
}
|
|
}
|
|
|
|
// Students
|
|
$students = [];
|
|
foreach ($studentClasses as $studentClass) {
|
|
if ($sectionSemester === '' && !empty($studentClass['semester'])) {
|
|
$sectionSemester = (string) $studentClass['semester'];
|
|
}
|
|
if ($sectionSchoolYear === '' && !empty($studentClass['school_year'])) {
|
|
$sectionSchoolYear = (string) $studentClass['school_year'];
|
|
}
|
|
if ($description === '' && !empty($studentClass['description'])) {
|
|
$description = (string) $studentClass['description'];
|
|
}
|
|
|
|
$studentId = (int) ($studentClass['student_id'] ?? 0);
|
|
if ($studentId <= 0) {
|
|
continue;
|
|
}
|
|
|
|
$student = $this->studentModel->newQuery()
|
|
->where('id', $studentId)
|
|
->where('is_active', 1)
|
|
->first();
|
|
|
|
if (!$student) {
|
|
continue;
|
|
}
|
|
|
|
$students[] = $forApi
|
|
? [
|
|
'id' => (int) $student->id,
|
|
'firstname' => (string) ($student->firstname ?? ''),
|
|
'lastname' => (string) ($student->lastname ?? ''),
|
|
'age' => $student->age ?? null,
|
|
'gender' => (string) ($student->gender ?? ''),
|
|
'registration_grade' => (string) ($student->registration_grade ?? ''),
|
|
'photo_consent' => (bool) ($student->photo_consent ?? false),
|
|
'tuition_paid' => (bool) ($student->tuition_paid ?? false),
|
|
'school_id' => (string) ($student->school_id ?? ''),
|
|
]
|
|
: [
|
|
'id' => (int) $student->id,
|
|
'firstname' => e((string) ($student->firstname ?? '')),
|
|
'lastname' => e((string) ($student->lastname ?? '')),
|
|
'age' => e((string) ($student->age ?? '')),
|
|
'gender' => e((string) ($student->gender ?? '')),
|
|
'registration_grade' => e((string) ($student->registration_grade ?? '')),
|
|
'photo_consent' => e(((bool) ($student->photo_consent ?? false)) ? 'Yes' : 'No'),
|
|
'tuition_paid' => e(((bool) ($student->tuition_paid ?? false)) ? 'Yes' : 'No'),
|
|
'school_id' => e((string) ($student->school_id ?? '')),
|
|
];
|
|
}
|
|
|
|
$classSections[] = [
|
|
'class_section_id' => (int) $classSectionId,
|
|
'class_section_name' => (string) $classSectionName,
|
|
'main_teachers' => array_values(array_unique($mainTeachers)),
|
|
'teacher_assistants' => array_values(array_unique($teacherAssistants)),
|
|
'students' => $students,
|
|
'semester' => $sectionSemester !== '' ? $sectionSemester : $currentSemester,
|
|
'school_year' => $sectionSchoolYear !== '' ? $sectionSchoolYear : $currentSchoolYear,
|
|
'description' => $description,
|
|
];
|
|
}
|
|
|
|
// Sort sections by name
|
|
usort($classSections, fn ($a, $b) => strcmp(
|
|
(string) ($a['class_section_name'] ?? ''),
|
|
(string) ($b['class_section_name'] ?? '')
|
|
));
|
|
|
|
$schoolYearsList = $this->getSchoolYearsList($currentSchoolYear);
|
|
|
|
$payload = [
|
|
'classSections' => $classSections,
|
|
'schoolYears' => $schoolYearsList,
|
|
'selectedYear' => $selectedYear,
|
|
'selectedSemester' => $selectedSemester,
|
|
'semester' => $currentSemester,
|
|
'school_year' => $currentSchoolYear,
|
|
];
|
|
|
|
// If you're using Laravel Sanctum/API only, CSRF may not be needed.
|
|
// Keep it if your frontend still expects it:
|
|
if (function_exists('csrf_token')) {
|
|
$payload['csrfToken'] = csrf_token();
|
|
}
|
|
|
|
return $payload;
|
|
}
|
|
|
|
public function saveStudentAssignment(array $data, ?int $updatedBy = null): mixed
|
|
{
|
|
$payload = [
|
|
'student_id' => $data['student_id'],
|
|
'class_section_id' => $data['class_section_id'],
|
|
'semester' => $data['semester'] ?? $this->getConfigValue('semester'),
|
|
'school_year' => $data['school_year'] ?? $this->getConfigValue('school_year'),
|
|
'description' => $data['description'] ?? null,
|
|
'updated_by' => $updatedBy,
|
|
];
|
|
|
|
// If your StudentClass model supports updateOrCreate:
|
|
// adjust unique keys as needed (e.g. student_id + school_year + semester)
|
|
return $this->studentClassModel->newQuery()->updateOrCreate(
|
|
[
|
|
'student_id' => $payload['student_id'],
|
|
'school_year' => $payload['school_year'],
|
|
'semester' => $payload['semester'],
|
|
],
|
|
$payload
|
|
);
|
|
}
|
|
|
|
protected function getConfigValue(string $key): mixed
|
|
{
|
|
// Match your existing model API if present
|
|
if (method_exists($this->configModel, 'getConfig')) {
|
|
return $this->configModel->getConfig($key);
|
|
}
|
|
|
|
// Generic fallback
|
|
return $this->configModel->newQuery()
|
|
->where('key', $key)
|
|
->value('value');
|
|
}
|
|
|
|
protected function resolveClassSectionName(int $classSectionId): string
|
|
{
|
|
if (method_exists($this->classSectionModel, 'getClassSectionNameBySectionId')) {
|
|
return (string) ($this->classSectionModel->getClassSectionNameBySectionId($classSectionId) ?? '');
|
|
}
|
|
|
|
$section = $this->classSectionModel->newQuery()->find($classSectionId);
|
|
|
|
// Adjust to your actual field(s)
|
|
return (string) ($section->name ?? $section->title ?? '');
|
|
}
|
|
|
|
protected function getSchoolYearsList(string $fallbackYear = ''): array
|
|
{
|
|
try {
|
|
$years = DB::table('teacher_class')
|
|
->select('school_year')
|
|
->whereNotNull('school_year')
|
|
->distinct()
|
|
->orderByDesc('school_year')
|
|
->pluck('school_year')
|
|
->map(fn ($y) => (string) $y)
|
|
->filter(fn ($y) => $y !== '')
|
|
->values()
|
|
->all();
|
|
|
|
if (!empty($years)) {
|
|
return $years;
|
|
}
|
|
} catch (\Throwable $e) {
|
|
// fallback below
|
|
}
|
|
|
|
return $fallbackYear !== '' ? [$fallbackYear] : [];
|
|
}
|
|
} |