reconstruction of the project
This commit is contained in:
@@ -0,0 +1,353 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Assignment;
|
||||
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\Configuration;
|
||||
use App\Models\StudentClass;
|
||||
use App\Models\TeacherClass;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AssignmentService
|
||||
{
|
||||
public function __construct(
|
||||
protected Configuration $configurationModel,
|
||||
protected TeacherClass $teacherClassModel,
|
||||
protected StudentClass $studentClassModel,
|
||||
protected ClassSection $classSectionModel,
|
||||
) {}
|
||||
|
||||
public function getCurrentSemester(): string
|
||||
{
|
||||
return (string) ($this->getConfigValue('semester') ?? '');
|
||||
}
|
||||
|
||||
public function getCurrentSchoolYear(): string
|
||||
{
|
||||
return (string) ($this->getConfigValue('school_year') ?? '');
|
||||
}
|
||||
|
||||
protected function getConfigValue(string $key): mixed
|
||||
{
|
||||
return $this->configurationModel
|
||||
->newQuery()
|
||||
->where('config_key', $key)
|
||||
->value('config_value');
|
||||
}
|
||||
|
||||
public function getAssignmentsOverview(?string $schoolYear = null, ?string $semester = null): array
|
||||
{
|
||||
$currentSemester = $this->getCurrentSemester();
|
||||
$currentSchoolYear = $this->getCurrentSchoolYear();
|
||||
|
||||
$selectedSemester = (string) ($semester ?? $currentSemester);
|
||||
$selectedYear = (string) ($schoolYear ?? $currentSchoolYear);
|
||||
|
||||
$teacherClasses = $this->loadTeacherClasses($selectedYear);
|
||||
$studentClasses = $this->loadStudentClasses($selectedYear);
|
||||
|
||||
$teacherBySection = $teacherClasses->groupBy('class_section_id');
|
||||
$studentBySection = $studentClasses->groupBy('class_section_id');
|
||||
|
||||
$allSectionIds = $teacherBySection->keys()
|
||||
->merge($studentBySection->keys())
|
||||
->unique()
|
||||
->filter()
|
||||
->values();
|
||||
|
||||
$sectionNames = $this->getSectionNamesMap($allSectionIds->all());
|
||||
|
||||
$classSections = $allSectionIds->map(function ($sectionId) use (
|
||||
$teacherBySection,
|
||||
$studentBySection,
|
||||
$sectionNames,
|
||||
$currentSemester,
|
||||
$currentSchoolYear
|
||||
) {
|
||||
$teacherRows = $teacherBySection->get($sectionId, collect());
|
||||
$studentRows = $studentBySection->get($sectionId, collect());
|
||||
|
||||
if ($teacherRows->isEmpty() && $studentRows->isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$mainTeachers = $teacherRows
|
||||
->where('position', 'main')
|
||||
->pluck('teacher_full_name')
|
||||
->filter()
|
||||
->unique()
|
||||
->values();
|
||||
|
||||
$teacherAssistants = $teacherRows
|
||||
->where('position', 'ta')
|
||||
->pluck('teacher_full_name')
|
||||
->filter()
|
||||
->unique()
|
||||
->values();
|
||||
|
||||
$semesterMeta = $this->firstNonEmpty([
|
||||
$teacherRows->pluck('semester')->first(fn ($v) => filled($v)),
|
||||
$studentRows->pluck('semester')->first(fn ($v) => filled($v)),
|
||||
$currentSemester,
|
||||
]);
|
||||
|
||||
$schoolYearMeta = $this->firstNonEmpty([
|
||||
$teacherRows->pluck('school_year')->first(fn ($v) => filled($v)),
|
||||
$studentRows->pluck('school_year')->first(fn ($v) => filled($v)),
|
||||
$currentSchoolYear,
|
||||
]);
|
||||
|
||||
$descriptionMeta = $this->firstNonEmpty([
|
||||
$teacherRows->pluck('description')->first(fn ($v) => filled($v)),
|
||||
$studentRows->pluck('description')->first(fn ($v) => filled($v)),
|
||||
'',
|
||||
]);
|
||||
|
||||
$students = $studentRows
|
||||
->filter(fn ($row) => !empty($row->student))
|
||||
->map(function ($row) {
|
||||
$student = $row->student;
|
||||
|
||||
return [
|
||||
'id' => (int) $student->id,
|
||||
'firstname' => (string) ($student->firstname ?? ''),
|
||||
'lastname' => (string) ($student->lastname ?? ''),
|
||||
'age' => $student->age,
|
||||
'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 ?? ''),
|
||||
];
|
||||
})
|
||||
->values();
|
||||
|
||||
return [
|
||||
'class_section_id' => (int) $sectionId,
|
||||
'class_section_name' => (string) ($sectionNames[$sectionId] ?? ''),
|
||||
'main_teachers' => $mainTeachers->all(),
|
||||
'teacher_assistants' => $teacherAssistants->all(),
|
||||
'students' => $students->all(),
|
||||
'semester' => (string) $semesterMeta,
|
||||
'school_year' => (string) $schoolYearMeta,
|
||||
'description' => (string) $descriptionMeta,
|
||||
];
|
||||
})
|
||||
->filter()
|
||||
->sortBy('class_section_name', SORT_NATURAL | SORT_FLAG_CASE)
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return [
|
||||
'classSections' => $classSections,
|
||||
'schoolYears' => $this->getSchoolYears($currentSchoolYear),
|
||||
'schoolYear' => $selectedYear,
|
||||
'selectedYear' => $selectedYear,
|
||||
'selectedSemester' => $selectedSemester,
|
||||
'semester' => $currentSemester,
|
||||
'current_school_year' => $currentSchoolYear,
|
||||
];
|
||||
}
|
||||
|
||||
public function storeAssignment(array $data, int|string|null $updatedBy = null): StudentClass
|
||||
{
|
||||
return $this->studentClassModel->newQuery()->updateOrCreate(
|
||||
[
|
||||
'student_id' => $data['student_id'],
|
||||
'class_section_id' => $data['class_section_id'],
|
||||
'semester' => $data['semester'],
|
||||
'school_year' => $data['school_year'],
|
||||
],
|
||||
[
|
||||
'description' => $data['description'] ?? null,
|
||||
'updated_by' => $updatedBy,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getClassAssignmentData(): array
|
||||
{
|
||||
$currentSemester = $this->getCurrentSemester();
|
||||
$currentSchoolYear = $this->getCurrentSchoolYear();
|
||||
|
||||
$teacherClasses = $this->loadTeacherClasses();
|
||||
$studentClasses = $this->loadStudentClasses();
|
||||
|
||||
$teacherBySection = $teacherClasses->groupBy('class_section_id');
|
||||
$studentBySection = $studentClasses->groupBy('class_section_id');
|
||||
|
||||
$allSectionIds = $teacherBySection->keys()
|
||||
->merge($studentBySection->keys())
|
||||
->unique()
|
||||
->filter()
|
||||
->values();
|
||||
|
||||
$sectionNames = $this->getSectionNamesMap($allSectionIds->all());
|
||||
|
||||
$classSections = $allSectionIds->map(function ($sectionId) use (
|
||||
$teacherBySection,
|
||||
$studentBySection,
|
||||
$sectionNames,
|
||||
$currentSemester,
|
||||
$currentSchoolYear
|
||||
) {
|
||||
$teacherRows = $teacherBySection->get($sectionId, collect());
|
||||
$studentRows = $studentBySection->get($sectionId, collect());
|
||||
|
||||
if ($teacherRows->isEmpty() && $studentRows->isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$mainTeachers = $teacherRows
|
||||
->where('position', 'main')
|
||||
->pluck('teacher_full_name')
|
||||
->filter()
|
||||
->unique()
|
||||
->values();
|
||||
|
||||
$teacherAssistants = $teacherRows
|
||||
->where('position', 'ta')
|
||||
->pluck('teacher_full_name')
|
||||
->filter()
|
||||
->unique()
|
||||
->values();
|
||||
|
||||
$semesterMeta = $this->firstNonEmpty([
|
||||
$teacherRows->pluck('semester')->first(fn ($v) => filled($v)),
|
||||
$studentRows->pluck('semester')->first(fn ($v) => filled($v)),
|
||||
$currentSemester,
|
||||
]);
|
||||
|
||||
$schoolYearMeta = $this->firstNonEmpty([
|
||||
$teacherRows->pluck('school_year')->first(fn ($v) => filled($v)),
|
||||
$studentRows->pluck('school_year')->first(fn ($v) => filled($v)),
|
||||
$currentSchoolYear,
|
||||
]);
|
||||
|
||||
$descriptionMeta = $this->firstNonEmpty([
|
||||
$teacherRows->pluck('description')->first(fn ($v) => filled($v)),
|
||||
$studentRows->pluck('description')->first(fn ($v) => filled($v)),
|
||||
'',
|
||||
]);
|
||||
|
||||
$students = $studentRows
|
||||
->filter(fn ($row) => !empty($row->student))
|
||||
->map(function ($row) {
|
||||
$student = $row->student;
|
||||
|
||||
return [
|
||||
'id' => (int) $student->id,
|
||||
'firstname' => (string) ($student->firstname ?? ''),
|
||||
'lastname' => (string) ($student->lastname ?? ''),
|
||||
'age' => $student->age,
|
||||
'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 ?? ''),
|
||||
];
|
||||
})
|
||||
->values();
|
||||
|
||||
return [
|
||||
'class_section_id' => (int) $sectionId,
|
||||
'class_section_name' => (string) ($sectionNames[$sectionId] ?? ''),
|
||||
'main_teachers' => $mainTeachers->all(),
|
||||
'teacher_assistants' => $teacherAssistants->all(),
|
||||
'students' => $students->all(),
|
||||
'semester' => (string) $semesterMeta,
|
||||
'school_year' => (string) $schoolYearMeta,
|
||||
'description' => (string) $descriptionMeta,
|
||||
];
|
||||
})
|
||||
->filter()
|
||||
->sortBy('class_section_name', SORT_NATURAL | SORT_FLAG_CASE)
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return [
|
||||
'classSections' => $classSections,
|
||||
'semester' => $currentSemester,
|
||||
'school_year' => $currentSchoolYear,
|
||||
];
|
||||
}
|
||||
|
||||
protected function loadTeacherClasses(?string $schoolYear = null): Collection
|
||||
{
|
||||
return $this->teacherClassModel
|
||||
->newQuery()
|
||||
->with([
|
||||
'teacher:id,firstname,lastname',
|
||||
])
|
||||
->when(filled($schoolYear), fn ($q) => $q->where('school_year', $schoolYear))
|
||||
->get()
|
||||
->map(function ($row) {
|
||||
$row->teacher_full_name = trim(
|
||||
((string) optional($row->teacher)->firstname) . ' ' .
|
||||
((string) optional($row->teacher)->lastname)
|
||||
);
|
||||
|
||||
return $row;
|
||||
});
|
||||
}
|
||||
|
||||
protected function loadStudentClasses(?string $schoolYear = null): Collection
|
||||
{
|
||||
return $this->studentClassModel
|
||||
->newQuery()
|
||||
->with([
|
||||
'student:id,firstname,lastname,age,gender,registration_grade,photo_consent,tuition_paid,school_id,is_active',
|
||||
])
|
||||
->whereHas('student', fn ($q) => $q->where('is_active', 1))
|
||||
->when(filled($schoolYear), fn ($q) => $q->where('school_year', $schoolYear))
|
||||
->get();
|
||||
}
|
||||
|
||||
protected function getSectionNamesMap(array $sectionIds): array
|
||||
{
|
||||
if (empty($sectionIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->classSectionModel
|
||||
->newQuery()
|
||||
->whereIn('id', $sectionIds)
|
||||
->get()
|
||||
->mapWithKeys(function ($section) {
|
||||
$name = $section->section_name ?? $section->name ?? '';
|
||||
return [(int) $section->id => (string) $name];
|
||||
})
|
||||
->all();
|
||||
}
|
||||
|
||||
protected function getSchoolYears(string $fallbackYear = ''): array
|
||||
{
|
||||
$years = DB::table('teacher_class')
|
||||
->selectRaw('DISTINCT school_year')
|
||||
->whereNotNull('school_year')
|
||||
->orderByDesc('school_year')
|
||||
->pluck('school_year')
|
||||
->map(fn ($year) => (string) $year)
|
||||
->filter()
|
||||
->values()
|
||||
->all();
|
||||
|
||||
if (empty($years) && $fallbackYear !== '') {
|
||||
$years[] = $fallbackYear;
|
||||
}
|
||||
|
||||
return $years;
|
||||
}
|
||||
|
||||
protected function firstNonEmpty(array $values): mixed
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
if (filled($value)) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user