364 lines
13 KiB
PHP
364 lines
13 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use App\Models\BaseModel;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class TeacherClass extends BaseModel
|
|
{
|
|
protected $table = 'teacher_class';
|
|
|
|
protected $fillable = [
|
|
'class_section_id',
|
|
'teacher_id',
|
|
'position',
|
|
'semester',
|
|
'school_year',
|
|
'description',
|
|
'created_at',
|
|
'updated_at',
|
|
'updated_by',
|
|
];
|
|
|
|
public $timestamps = true;
|
|
|
|
protected $casts = [
|
|
'teacher_id' => 'integer',
|
|
'class_section_id' => 'integer',
|
|
'updated_by' => 'integer',
|
|
'created_at' => 'datetime',
|
|
'updated_at' => 'datetime',
|
|
];
|
|
|
|
|
|
/* ============================================================
|
|
* Constants
|
|
* ============================================================
|
|
*/
|
|
public const POS_MAIN = 'main';
|
|
public const POS_TA = 'ta';
|
|
|
|
public static function allowedPositions(): array
|
|
{
|
|
return [self::POS_MAIN, self::POS_TA];
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
* Relationships (optional)
|
|
* ============================================================
|
|
*/
|
|
public function teacher(): BelongsTo
|
|
{
|
|
// your teachers are users in most of your joins
|
|
return $this->belongsTo(User::class, 'teacher_id');
|
|
}
|
|
|
|
public function classSection(): BelongsTo
|
|
{
|
|
// CI frequently joins on classSection.class_section_id
|
|
return $this->belongsTo(ClassSection::class, 'class_section_id', 'class_section_id');
|
|
}
|
|
|
|
public function updater(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'updated_by'); // change to Admin if needed
|
|
}
|
|
|
|
/* ============================================================
|
|
* Scopes
|
|
* ============================================================
|
|
*/
|
|
public function scopeForTeacher(Builder $q, int $teacherId): Builder
|
|
{
|
|
return $q->where('teacher_id', $teacherId);
|
|
}
|
|
|
|
public function scopeForSchoolYear(Builder $q, string $schoolYear): Builder
|
|
{
|
|
return $q->where('school_year', $schoolYear);
|
|
}
|
|
|
|
public function scopeForSectionCode(Builder $q, int $sectionCode): Builder
|
|
{
|
|
return $q->where('class_section_id', $sectionCode);
|
|
}
|
|
|
|
public function scopeMain(Builder $q): Builder
|
|
{
|
|
return $q->where('position', self::POS_MAIN);
|
|
}
|
|
|
|
public function scopeTa(Builder $q): Builder
|
|
{
|
|
return $q->where('position', self::POS_TA);
|
|
}
|
|
|
|
/* ============================================================
|
|
* CI-compatible methods (converted)
|
|
* ============================================================
|
|
*/
|
|
|
|
/** CI: getClassSectionIdByUserId() */
|
|
public static function getClassSectionIdByUserId(int $userId): ?self
|
|
{
|
|
return static::query()->forTeacher($userId)->first();
|
|
}
|
|
|
|
/**
|
|
* CI: getClassAssignmentsByUserId()
|
|
* Returns array rows with:
|
|
* class_section_pk, class_section_id, class_section_name, class_id, class_name, teacher_id, teacher_role, school_year, semester
|
|
*/
|
|
public static function getClassAssignmentsByUserId(int $userId, ?string $schoolYear = null, ?string $semester = null): array
|
|
{
|
|
$q = DB::table('teacher_class as tc')
|
|
->selectRaw('
|
|
cs.class_section_name,
|
|
cs.id AS class_section_pk,
|
|
cs.class_section_id,
|
|
c.id AS class_id,
|
|
c.class_name,
|
|
tc.teacher_id,
|
|
tc.position,
|
|
tc.school_year
|
|
')
|
|
->join('classSection as cs', 'tc.class_section_id', '=', 'cs.class_section_id')
|
|
->leftJoin('classes as c', 'cs.class_id', '=', 'c.id')
|
|
->where('tc.teacher_id', $userId)
|
|
->whereNotNull('tc.class_section_id')
|
|
->orderBy('cs.class_section_name', 'asc');
|
|
|
|
if ($schoolYear) {
|
|
$q->where('tc.school_year', $schoolYear);
|
|
}
|
|
|
|
$rows = $q->get();
|
|
|
|
return $rows->map(function ($r) use ($semester) {
|
|
return [
|
|
'class_section_pk' => isset($r->class_section_pk) ? (int) $r->class_section_pk : null,
|
|
'class_section_id' => (int) $r->class_section_id,
|
|
'class_section_name' => (string) $r->class_section_name,
|
|
'class_id' => isset($r->class_id) ? (int) $r->class_id : null,
|
|
'class_name' => $r->class_name ?? null,
|
|
'teacher_id' => (int) $r->teacher_id,
|
|
'teacher_role' => ucfirst((string) $r->position), // Main / Ta
|
|
'school_year' => (string) $r->school_year,
|
|
'semester' => $semester,
|
|
];
|
|
})->all();
|
|
}
|
|
|
|
/** CI: getClassSectionsByTeacherId() */
|
|
public static function getClassSectionsByTeacherId(int $teacherId): array
|
|
{
|
|
$rows = DB::table('teacher_class as tc')
|
|
->selectRaw('cs.class_section_name, tc.teacher_id, tc.position')
|
|
->join('classSection as cs', 'tc.class_section_id', '=', 'cs.class_section_id')
|
|
->where('tc.teacher_id', $teacherId)
|
|
->whereNotNull('tc.class_section_id')
|
|
->get();
|
|
|
|
if ($rows->isEmpty()) {
|
|
return ['role' => '', 'class_section_name' => 'No class assigned'];
|
|
}
|
|
|
|
$sectionNames = $rows->pluck('class_section_name')->filter()->all();
|
|
$position = (string) ($rows[0]->position ?? '');
|
|
|
|
return [
|
|
'role' => ucfirst($position),
|
|
'class_section_name' => implode(', ', $sectionNames),
|
|
];
|
|
}
|
|
|
|
/** CI: getClassByTeacherId() */
|
|
public static function getClassByTeacherId(int $teacherId): array
|
|
{
|
|
return DB::table('teacher_class as tc')
|
|
->selectRaw('cs.class_section_id, cs.class_section_name')
|
|
->join('classSection as cs', 'tc.class_section_id', '=', 'cs.class_section_id')
|
|
->where('tc.teacher_id', $teacherId)
|
|
->whereNotNull('tc.class_section_id')
|
|
->get()
|
|
->map(fn ($r) => (array) $r)
|
|
->all();
|
|
}
|
|
|
|
/** CI: getTeacherIdByClassSection($classSectionName, $semester, $schoolYear) */
|
|
public static function getTeacherIdByClassSection(string $classSectionName, string $semester, string $schoolYear): ?int
|
|
{
|
|
$classSectionName = trim($classSectionName);
|
|
if (str_contains($classSectionName, ',')) {
|
|
$parts = array_values(array_filter(array_map('trim', explode(',', $classSectionName))));
|
|
if (!empty($parts)) $classSectionName = $parts[0];
|
|
}
|
|
if ($classSectionName === '') return null;
|
|
|
|
$sectionCode = DB::table('classSection')
|
|
->where('class_section_name', $classSectionName)
|
|
->value('class_section_id');
|
|
|
|
if (!$sectionCode) return null;
|
|
|
|
$teacherId = DB::table('teacher_class')
|
|
->where('class_section_id', $sectionCode)
|
|
->where('school_year', $schoolYear)
|
|
->where('position', self::POS_MAIN)
|
|
->value('teacher_id');
|
|
|
|
return $teacherId ? (int) $teacherId : null;
|
|
}
|
|
|
|
/** CI: getMainTeacherBySection($classSectionName, $semester, $schoolYear) */
|
|
public static function getMainTeacherBySection(string $classSectionName, string $semester, string $schoolYear): ?array
|
|
{
|
|
$row = DB::table('classSection as cs')
|
|
->selectRaw('u.id AS teacher_id, u.firstname, u.lastname')
|
|
// IMPORTANT: your CI code had tc.class_section_id = cs.id in one place (PK join),
|
|
// but most of your code uses class_section_id code join.
|
|
// Here we keep the "code join" for consistency:
|
|
->join('teacher_class as tc', 'tc.class_section_id', '=', 'cs.class_section_id')
|
|
->join('users as u', 'u.id', '=', 'tc.teacher_id')
|
|
->where('cs.class_section_name', $classSectionName)
|
|
->where('tc.school_year', $schoolYear)
|
|
->where('tc.position', self::POS_MAIN)
|
|
->first();
|
|
|
|
return $row ? (array) $row : null;
|
|
}
|
|
|
|
/**
|
|
* CI: assignTeacherToClass()
|
|
* Upsert by (teacher_id, class_section_id, school_year, position) and touch updated_at.
|
|
*/
|
|
public static function assignTeacherToClass(
|
|
int $teacherId,
|
|
int $sectionCode,
|
|
string $semester,
|
|
string $schoolYear,
|
|
string $position = self::POS_MAIN,
|
|
?int $updatedBy = null
|
|
): bool {
|
|
$position = strtolower(trim($position));
|
|
if (!in_array($position, self::allowedPositions(), true)) {
|
|
throw new \InvalidArgumentException('Position must be either "main" or "ta".');
|
|
}
|
|
|
|
$updatedBy = $updatedBy ?? (auth()->id() ?? null);
|
|
|
|
static::query()->updateOrCreate(
|
|
[
|
|
'teacher_id' => $teacherId,
|
|
'class_section_id' => $sectionCode,
|
|
'school_year' => $schoolYear,
|
|
'position' => $position,
|
|
],
|
|
[
|
|
'updated_by' => $updatedBy,
|
|
'updated_at' => now(),
|
|
]
|
|
);
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* CI: getAssignedClassSections()
|
|
* NOTE: your CI joins classSection.id = teacher_class.class_section_id (PK join).
|
|
* If your teacher_class.class_section_id is actually a section CODE, change join to cs.class_section_id.
|
|
*/
|
|
public static function getAssignedClassSections(int $teacherId, string $schoolYear, string $semester): array
|
|
{
|
|
return DB::table('teacher_class as tc')
|
|
->selectRaw('tc.class_section_id, tc.position, cs.class_section_name')
|
|
->join('classSection as cs', 'cs.class_section_id', '=', 'tc.class_section_id')
|
|
->where('tc.teacher_id', $teacherId)
|
|
->where('tc.school_year', $schoolYear)
|
|
->orderByRaw("CASE tc.position WHEN 'main' THEN 0 WHEN 'ta' THEN 1 ELSE 2 END")
|
|
->get()
|
|
->map(fn ($r) => (array) $r)
|
|
->all();
|
|
}
|
|
|
|
/**
|
|
* CI: assignedForSectionTerm()
|
|
* Returns rows: class_section_id, teacher_id, position, firstname, lastname
|
|
*/
|
|
public static function assignedForSectionTerm(int $sectionCode, string $semester, string $schoolYear): array
|
|
{
|
|
return DB::table('teacher_class as tc')
|
|
->selectRaw('tc.class_section_id, tc.teacher_id, tc.position, u.firstname, u.lastname')
|
|
->leftJoin('users as u', 'u.id', '=', 'tc.teacher_id')
|
|
->where('tc.class_section_id', $sectionCode)
|
|
->where('tc.school_year', $schoolYear)
|
|
->orderByRaw("CASE tc.position WHEN 'main' THEN 0 WHEN 'ta' THEN 1 ELSE 2 END")
|
|
->orderBy('u.firstname', 'asc')
|
|
->get()
|
|
->map(fn ($r) => (array) $r)
|
|
->all();
|
|
}
|
|
|
|
/** CI: assignedMapForSectionTerm() */
|
|
public static function assignedMapForSectionTerm(int $sectionCode, string $semester, string $schoolYear): array
|
|
{
|
|
$out = [];
|
|
foreach (static::assignedForSectionTerm($sectionCode, $semester, $schoolYear) as $r) {
|
|
$out[(int) $r['teacher_id']] = $r;
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
/**
|
|
* CI: assignedBySectionForTerm()
|
|
* Returns: [sectionCode] => [rows...]
|
|
*/
|
|
public static function assignedBySectionForTerm(string $semester, string $schoolYear, ?array $onlySectionCodes = null): array
|
|
{
|
|
$q = DB::table('teacher_class as tc')
|
|
->selectRaw('tc.class_section_id, tc.teacher_id, tc.position, u.firstname, u.lastname')
|
|
->leftJoin('users as u', 'u.id', '=', 'tc.teacher_id')
|
|
->where('tc.school_year', $schoolYear)
|
|
->orderBy('tc.class_section_id', 'asc')
|
|
->orderByRaw("CASE tc.position WHEN 'main' THEN 0 WHEN 'ta' THEN 1 ELSE 2 END")
|
|
->orderBy('u.firstname', 'asc');
|
|
|
|
if (!empty($onlySectionCodes)) {
|
|
$ids = array_values(array_unique(array_filter(array_map('intval', $onlySectionCodes))));
|
|
if (!empty($ids)) $q->whereIn('tc.class_section_id', $ids);
|
|
}
|
|
|
|
$rows = $q->get()->map(fn ($r) => (array) $r)->all();
|
|
|
|
$out = [];
|
|
foreach ($rows as $r) {
|
|
$code = (int) ($r['class_section_id'] ?? 0);
|
|
if ($code <= 0) continue;
|
|
$out[$code][] = $r;
|
|
}
|
|
|
|
return $out;
|
|
}
|
|
|
|
/* ============================================================
|
|
* Optional validation helper (FormRequest/controller)
|
|
* ============================================================
|
|
*/
|
|
public static function rules(bool $updating = false): array
|
|
{
|
|
$req = $updating ? 'sometimes' : 'required';
|
|
|
|
return [
|
|
'teacher_id' => [$req, 'integer', 'min:1', 'exists:users,id'],
|
|
'class_section_id' => [$req, 'integer', 'min:1'],
|
|
'school_year' => [$req, 'string', 'max:9'],
|
|
'position' => [$req, 'string', 'in:' . implode(',', self::allowedPositions())],
|
|
'updated_by' => ['nullable', 'integer'],
|
|
];
|
|
}
|
|
}
|