add more controller
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Students;
|
||||
|
||||
use App\Models\ClassSection;
|
||||
use App\Models\Enrollment;
|
||||
use App\Models\Student;
|
||||
use App\Models\StudentClass;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class StudentAssignmentService
|
||||
{
|
||||
public function __construct(private StudentConfigService $configService)
|
||||
{
|
||||
}
|
||||
|
||||
public function assignClasses(int $studentId, array $classSectionIds, bool $isEventOnly, ?int $userId = null): array
|
||||
{
|
||||
$context = $this->configService->context();
|
||||
$semester = (string) ($context['semester'] ?? '');
|
||||
$schoolYear = (string) ($context['school_year'] ?? '');
|
||||
|
||||
$classSectionIds = $this->normalizeIds($classSectionIds);
|
||||
if ($studentId <= 0 || empty($classSectionIds) || $schoolYear === '') {
|
||||
return ['ok' => false, 'message' => 'Missing required data (student/class section).'];
|
||||
}
|
||||
|
||||
$student = Student::query()->find($studentId);
|
||||
if (!$student) {
|
||||
return ['ok' => false, 'message' => 'Student not found.'];
|
||||
}
|
||||
|
||||
$sections = ClassSection::query()
|
||||
->whereIn('class_section_id', $classSectionIds)
|
||||
->orWhereIn('id', $classSectionIds)
|
||||
->get()
|
||||
->toArray();
|
||||
|
||||
if (empty($sections)) {
|
||||
return ['ok' => false, 'message' => 'Class/Section not found.'];
|
||||
}
|
||||
|
||||
$sectionMap = [];
|
||||
foreach ($sections as $section) {
|
||||
$sectionMap[(int) ($section['class_section_id'] ?? 0)] = $section;
|
||||
}
|
||||
|
||||
$missing = array_diff($classSectionIds, array_keys($sectionMap));
|
||||
if (!empty($missing)) {
|
||||
return ['ok' => false, 'message' => 'One or more selected classes do not exist.'];
|
||||
}
|
||||
|
||||
$existing = StudentClass::query()
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->get()
|
||||
->keyBy(fn ($row) => (int) ($row->class_section_id ?? 0));
|
||||
|
||||
$primarySectionId = $classSectionIds[0];
|
||||
$primarySection = $sectionMap[$primarySectionId] ?? reset($sectionMap);
|
||||
$parentClassId = (int) ($primarySection['class_id'] ?? 0);
|
||||
if ($parentClassId <= 0) {
|
||||
$parentClassId = (int) (ClassSection::getClassId($primarySectionId) ?? 0);
|
||||
}
|
||||
|
||||
$attendanceStats = [];
|
||||
$scoreStats = [];
|
||||
|
||||
DB::transaction(function () use (
|
||||
$studentId,
|
||||
$schoolYear,
|
||||
$classSectionIds,
|
||||
$isEventOnly,
|
||||
$userId,
|
||||
$existing,
|
||||
$semester,
|
||||
$primarySectionId,
|
||||
$parentClassId,
|
||||
&$attendanceStats,
|
||||
&$scoreStats
|
||||
): void {
|
||||
foreach ($classSectionIds as $classSectionId) {
|
||||
$eventFlag = $isEventOnly ? 1 : 0;
|
||||
if ($existing->has($classSectionId)) {
|
||||
$eventFlag = (int) ($existing[$classSectionId]->is_event_only ?? 0);
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'student_id' => $studentId,
|
||||
'class_section_id' => $classSectionId,
|
||||
'school_year' => $schoolYear,
|
||||
'is_event_only' => $eventFlag,
|
||||
'updated_by' => $userId,
|
||||
'updated_at' => now(),
|
||||
];
|
||||
|
||||
if ($existing->has($classSectionId)) {
|
||||
$existing[$classSectionId]->fill($payload)->save();
|
||||
} else {
|
||||
StudentClass::query()->create($payload + [
|
||||
'created_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$isEventOnly) {
|
||||
$enrollment = Enrollment::query()
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->when($semester !== '', fn ($q) => $q->where('semester', $semester))
|
||||
->first();
|
||||
|
||||
if ($enrollment) {
|
||||
$enrollment->update([
|
||||
'class_section_id' => $primarySectionId,
|
||||
'enrollment_status' => 'payment pending',
|
||||
'admission_status' => 'accepted',
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
$attendanceStats = $this->updateAttendance(
|
||||
$studentId,
|
||||
$primarySectionId,
|
||||
$parentClassId,
|
||||
$semester,
|
||||
$schoolYear,
|
||||
$userId
|
||||
);
|
||||
|
||||
$scoreStats = $this->updateScores(
|
||||
$studentId,
|
||||
$primarySectionId,
|
||||
$semester,
|
||||
$schoolYear,
|
||||
$userId
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
$displayNames = [];
|
||||
foreach ($classSectionIds as $classSectionId) {
|
||||
$section = $sectionMap[$classSectionId] ?? null;
|
||||
if (!$section) {
|
||||
continue;
|
||||
}
|
||||
$name = (string) ($section['class_section_name'] ?? '');
|
||||
if ($name === '') {
|
||||
$name = 'Section #' . $classSectionId;
|
||||
}
|
||||
$displayNames[] = $name;
|
||||
}
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'student_id' => $studentId,
|
||||
'class_section_id' => $primarySectionId,
|
||||
'class_section_ids' => $classSectionIds,
|
||||
'class_section_names' => $displayNames,
|
||||
'attendance_updates' => $attendanceStats,
|
||||
'score_updates' => $scoreStats,
|
||||
];
|
||||
}
|
||||
|
||||
public function removeClass(int $studentId, int $classSectionId, ?int $userId = null): array
|
||||
{
|
||||
$context = $this->configService->context();
|
||||
$semester = (string) ($context['semester'] ?? '');
|
||||
$schoolYear = (string) ($context['school_year'] ?? '');
|
||||
|
||||
if ($studentId <= 0 || $classSectionId <= 0 || $schoolYear === '') {
|
||||
return ['ok' => false, 'message' => 'Missing required data (student/class section).'];
|
||||
}
|
||||
|
||||
$row = StudentClass::query()
|
||||
->where('student_id', $studentId)
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $schoolYear)
|
||||
->first();
|
||||
|
||||
if (!$row) {
|
||||
return ['ok' => false, 'message' => 'Assignment not found for this student/class.'];
|
||||
}
|
||||
|
||||
$remainingIds = [];
|
||||
$remainingNames = [];
|
||||
|
||||
DB::transaction(function () use (
|
||||
$studentId,
|
||||
$classSectionId,
|
||||
$schoolYear,
|
||||
$semester,
|
||||
$userId,
|
||||
&$remainingIds,
|
||||
&$remainingNames
|
||||
): void {
|
||||
StudentClass::query()
|
||||
->where('student_id', $studentId)
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $schoolYear)
|
||||
->delete();
|
||||
|
||||
$remainingIds = StudentClass::getClassSectionIdsByStudentId($studentId, $schoolYear);
|
||||
$remainingNames = StudentClass::getClassSectionsByStudentId($studentId, $schoolYear, true);
|
||||
|
||||
$enrollment = Enrollment::query()
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->when($semester !== '', fn ($q) => $q->where('semester', $semester))
|
||||
->first();
|
||||
|
||||
if ($enrollment) {
|
||||
$newClassId = !empty($remainingIds) ? $remainingIds[0] : null;
|
||||
if ((int) $enrollment->class_section_id === $classSectionId || $newClassId !== null) {
|
||||
$enrollment->update([
|
||||
'class_section_id' => $newClassId,
|
||||
'updated_at' => now(),
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return [
|
||||
'ok' => true,
|
||||
'student_id' => $studentId,
|
||||
'removed_class_id' => $classSectionId,
|
||||
'remaining_ids' => $remainingIds,
|
||||
'remaining_names' => $remainingNames,
|
||||
];
|
||||
}
|
||||
|
||||
private function updateAttendance(
|
||||
int $studentId,
|
||||
int $classSectionId,
|
||||
int $classId,
|
||||
string $semester,
|
||||
string $schoolYear,
|
||||
?int $modifiedBy
|
||||
): array {
|
||||
$now = now()->toDateTimeString();
|
||||
|
||||
$attendanceUpdated = DB::table('attendance_data')
|
||||
->where('student_id', $studentId)
|
||||
->where('semester', $semester)
|
||||
->where('school_year', $schoolYear)
|
||||
->update([
|
||||
'class_section_id' => $classSectionId,
|
||||
'class_id' => $classId,
|
||||
'updated_at' => $now,
|
||||
'modified_by' => $modifiedBy,
|
||||
]);
|
||||
|
||||
$recordUpdated = DB::table('attendance_record')
|
||||
->where('student_id', $studentId)
|
||||
->where('semester', $semester)
|
||||
->where('school_year', $schoolYear)
|
||||
->update([
|
||||
'class_section_id' => $classSectionId,
|
||||
'updated_at' => $now,
|
||||
'modified_by' => $modifiedBy,
|
||||
]);
|
||||
|
||||
return [
|
||||
'attendance_data_updated' => $attendanceUpdated,
|
||||
'attendance_record_updated' => $recordUpdated,
|
||||
];
|
||||
}
|
||||
|
||||
private function updateScores(
|
||||
int $studentId,
|
||||
int $classSectionId,
|
||||
string $semester,
|
||||
string $schoolYear,
|
||||
?int $modifiedBy
|
||||
): array {
|
||||
$now = now()->toDateTimeString();
|
||||
$tables = [
|
||||
'homework',
|
||||
'quiz',
|
||||
'project',
|
||||
'participation',
|
||||
'midterm_exam',
|
||||
'final_exam',
|
||||
'final_score',
|
||||
'semester_scores',
|
||||
];
|
||||
|
||||
$results = [];
|
||||
foreach ($tables as $table) {
|
||||
$payload = [
|
||||
'class_section_id' => $classSectionId,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
if ($modifiedBy !== null && Schema::hasColumn($table, 'updated_by')) {
|
||||
$payload['updated_by'] = $modifiedBy;
|
||||
}
|
||||
|
||||
$results[$table . '_updated'] = DB::table($table)
|
||||
->where('student_id', $studentId)
|
||||
->where('semester', $semester)
|
||||
->where('school_year', $schoolYear)
|
||||
->update($payload);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
private function normalizeIds(array $ids): array
|
||||
{
|
||||
$values = array_map('intval', $ids);
|
||||
$values = array_values(array_unique(array_filter($values, static fn ($v) => $v > 0)));
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user