reconstruction of the project
This commit is contained in:
+276
-292
@@ -2,12 +2,15 @@
|
||||
|
||||
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 $primaryKey = 'id';
|
||||
|
||||
protected $fillable = [
|
||||
'class_section_id',
|
||||
'teacher_id',
|
||||
@@ -19,361 +22,342 @@ class TeacherClass extends BaseModel
|
||||
'updated_at',
|
||||
'updated_by',
|
||||
];
|
||||
|
||||
public $timestamps = true;
|
||||
const CREATED_AT = 'created_at';
|
||||
const UPDATED_AT = 'updated_at';
|
||||
protected $useSoftDeletes = false;
|
||||
protected $skipValidation = false;
|
||||
/** Request-lifetime memo cache */
|
||||
protected array $assignedCache = [];
|
||||
protected array $assignedBySectionCache = [];
|
||||
|
||||
protected $validationRules = [
|
||||
'teacher_id' => 'required|integer',
|
||||
'class_section_id' => 'required|integer',
|
||||
'semester' => 'required|string|max_length[255]',
|
||||
'school_year' => 'required|string|max_length[9]',
|
||||
'position' => 'required|in_list[main,ta]',
|
||||
protected $casts = [
|
||||
'teacher_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected $validationMessages = [
|
||||
'teacher_id' => [
|
||||
'required' => 'The teacher ID is required.',
|
||||
'integer' => 'The teacher ID must be an integer.',
|
||||
],
|
||||
'class_section_id' => [
|
||||
'required' => 'The class section ID is required.',
|
||||
'integer' => 'The class section ID must be an integer.',
|
||||
],
|
||||
'semester' => [
|
||||
'required' => 'The semester is required.',
|
||||
],
|
||||
'school_year' => [
|
||||
'required' => 'The school year is required.',
|
||||
'max_length' => 'The school year cannot exceed 9 characters.',
|
||||
],
|
||||
'position' => [
|
||||
'required' => 'The position (main or ta) is required.',
|
||||
'in_list' => 'The position must be either "main" or "ta".',
|
||||
],
|
||||
];
|
||||
|
||||
/* ============================================================
|
||||
* Constants
|
||||
* ============================================================
|
||||
*/
|
||||
public const POS_MAIN = 'main';
|
||||
public const POS_TA = 'ta';
|
||||
|
||||
public function getClassSectionIdByUserId($user_id)
|
||||
public static function allowedPositions(): array
|
||||
{
|
||||
$result = $this->where('teacher_id', $user_id)->first();
|
||||
|
||||
if (!$result) {
|
||||
log_message('error', "No class section found for user ID: $user_id");
|
||||
return null;
|
||||
}
|
||||
|
||||
return $result;
|
||||
return [self::POS_MAIN, self::POS_TA];
|
||||
}
|
||||
|
||||
public function getClassAssignmentsByUserId(int $userId, ?string $schoolYear = null, ?string $semester = null): array
|
||||
|
||||
/* ============================================================
|
||||
* Relationships (optional)
|
||||
* ============================================================
|
||||
*/
|
||||
public function teacher(): BelongsTo
|
||||
{
|
||||
$builder = $this->db->table('teacher_class tc')
|
||||
->select([
|
||||
'cs.class_section_name',
|
||||
'cs.id AS class_section_pk',
|
||||
'cs.class_section_id',
|
||||
'tc.teacher_id',
|
||||
'tc.position',
|
||||
'tc.school_year',
|
||||
'tc.semester',
|
||||
])
|
||||
->join('classSection cs', 'tc.class_section_id = cs.class_section_id', 'inner')
|
||||
// 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)
|
||||
->where('tc.class_section_id IS NOT NULL', null, false)
|
||||
->orderBy('cs.class_section_name', 'ASC');
|
||||
->whereNotNull('tc.class_section_id')
|
||||
->orderBy('cs.class_section_name', 'asc');
|
||||
|
||||
if ($schoolYear) $builder->where('tc.school_year', $schoolYear);
|
||||
if ($semester) $builder->where('tc.semester', $semester);
|
||||
|
||||
$rows = $builder->get()->getResultArray();
|
||||
|
||||
$out = [];
|
||||
foreach ($rows as $r) {
|
||||
$out[] = [
|
||||
'class_section_pk' => (int)$r['class_section_pk'],
|
||||
'class_section_id' => (int)$r['class_section_id'],
|
||||
'class_section_name' => $r['class_section_name'],
|
||||
'teacher_id' => (int)$r['teacher_id'],
|
||||
'teacher_role' => ucfirst($r['position']), // "Main" or "Ta"
|
||||
'school_year' => $r['school_year'],
|
||||
'semester' => $r['semester'],
|
||||
];
|
||||
if ($schoolYear) {
|
||||
$q->where('tc.school_year', $schoolYear);
|
||||
}
|
||||
|
||||
return $out;
|
||||
$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();
|
||||
}
|
||||
|
||||
public function getClassSectionsByTeacherId($teacherId)
|
||||
/** CI: getClassSectionsByTeacherId() */
|
||||
public static function getClassSectionsByTeacherId(int $teacherId): array
|
||||
{
|
||||
$builder = $this->db->table('teacher_class')
|
||||
->select('classSection.class_section_name, teacher_class.teacher_id, teacher_class.position')
|
||||
->join('classSection', 'teacher_class.class_section_id = classSection.class_section_id')
|
||||
->where('teacher_class.teacher_id', $teacherId)
|
||||
->where('teacher_class.class_section_id IS NOT NULL', null, false);
|
||||
$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();
|
||||
|
||||
$result = $builder->get()->getResultArray();
|
||||
|
||||
if ($result) {
|
||||
$sectionNames = array_map(fn($row) => $row['class_section_name'], $result);
|
||||
$position = $result[0]['position'] ?? '';
|
||||
|
||||
return [
|
||||
'role' => ucfirst($position),
|
||||
'class_section_name' => implode(', ', $sectionNames)
|
||||
];
|
||||
} else {
|
||||
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),
|
||||
];
|
||||
}
|
||||
|
||||
public function getClassByTeacherId($teacherId)
|
||||
/** CI: getClassByTeacherId() */
|
||||
public static function getClassByTeacherId(int $teacherId): array
|
||||
{
|
||||
$builder = $this->db->table('teacher_class')
|
||||
->select('classSection.class_section_id, classSection.class_section_name')
|
||||
->join('classSection', 'teacher_class.class_section_id = classSection.class_section_id')
|
||||
->where('teacher_class.teacher_id', $teacherId)
|
||||
->where('teacher_class.class_section_id IS NOT NULL', null, false);
|
||||
|
||||
return $builder->get()->getResultArray() ?? [];
|
||||
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();
|
||||
}
|
||||
|
||||
public function getTeacherIdByClassSection(string $classSectionName, string $semester, string $schoolYear)
|
||||
/** CI: getTeacherIdByClassSection($classSectionName, $semester, $schoolYear) */
|
||||
public static function getTeacherIdByClassSection(string $classSectionName, string $semester, string $schoolYear): ?int
|
||||
{
|
||||
$db = \Config\Database::connect();
|
||||
$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;
|
||||
|
||||
$section = $db->table('classSection')
|
||||
->select('class_section_id')
|
||||
$sectionCode = DB::table('classSection')
|
||||
->where('class_section_name', $classSectionName)
|
||||
->get()
|
||||
->getRowArray();
|
||||
->value('class_section_id');
|
||||
|
||||
if (!$section) return null;
|
||||
if (!$sectionCode) return null;
|
||||
|
||||
$result = $db->table('teacher_class')
|
||||
->select('teacher_id')
|
||||
->where([
|
||||
'class_section_id' => $section['class_section_id'],
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'position' => 'main'
|
||||
])
|
||||
->get()
|
||||
->getRowArray();
|
||||
$teacherId = DB::table('teacher_class')
|
||||
->where('class_section_id', $sectionCode)
|
||||
->where('school_year', $schoolYear)
|
||||
->where('position', self::POS_MAIN)
|
||||
->value('teacher_id');
|
||||
|
||||
return $result['teacher_id'] ?? null;
|
||||
return $teacherId ? (int) $teacherId : null;
|
||||
}
|
||||
|
||||
public function getMainTeacherBySection(string $classSectionName, string $semester, string $schoolYear): ?array
|
||||
/** CI: getMainTeacherBySection($classSectionName, $semester, $schoolYear) */
|
||||
public static function getMainTeacherBySection(string $classSectionName, string $semester, string $schoolYear): ?array
|
||||
{
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
// Adjust table/column names if yours differ (e.g., cs.id vs cs.class_section_id)
|
||||
$row = $db->table('classSection cs')
|
||||
->select('u.id AS teacher_id, u.firstname, u.lastname')
|
||||
->join('teacher_class tc', 'tc.class_section_id = cs.id', 'inner')
|
||||
->join('users u', 'u.id = tc.teacher_id', 'inner')
|
||||
$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.semester', $semester)
|
||||
->where('tc.school_year', $schoolYear)
|
||||
->where('tc.position', 'main')
|
||||
->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("FIELD(tc.position,'main','ta')")
|
||||
->get()
|
||||
->getRowArray();
|
||||
|
||||
return $row ?: null; // ['teacher_id' => ..., 'firstname' => ..., 'lastname' => ...] or null
|
||||
->map(fn ($r) => (array) $r)
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return teacher + TAs for a class section in the current term.
|
||||
* Output:
|
||||
* [
|
||||
* 'teacher_id' => int|null,
|
||||
* 'teacher_name' => string, // 'N/A' if none found
|
||||
* 'tas' => [ ['id'=>int,'name'=>string], ... ],
|
||||
* ]
|
||||
*/
|
||||
public function getTeacherTABySection(int|string $classSectionId, string $semester, string $schoolYear): array
|
||||
{
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
// We can read everything straight from teacher_class; no need to join classSection.
|
||||
// The previous version failed because it filtered on cs.class_section_id even though
|
||||
// the PK is cs.id. We avoid that by filtering on tc.class_section_id directly.
|
||||
$rows = $db->table('teacher_class tc')
|
||||
->select('u.id AS user_id, u.firstname, u.lastname, tc.position')
|
||||
->join('users u', 'u.id = tc.teacher_id', 'inner')
|
||||
->where('tc.class_section_id', $classSectionId)
|
||||
->where('tc.semester', $semester)
|
||||
->where('tc.school_year', $schoolYear)
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
$teacherId = null;
|
||||
$teacherName = 'N/A';
|
||||
$tas = [];
|
||||
$firstSeen = null; // fallback if no explicit "main"/"teacher"
|
||||
|
||||
foreach ($rows as $r) {
|
||||
$full = trim(($r['firstname'] ?? '') . ' ' . ($r['lastname'] ?? ''));
|
||||
if ($full === '') continue;
|
||||
|
||||
if ($firstSeen === null) {
|
||||
$firstSeen = ['id' => (int)$r['user_id'], 'name' => $full];
|
||||
}
|
||||
|
||||
$pos = strtolower((string)($r['position'] ?? ''));
|
||||
|
||||
// Treat either 'main' or legacy 'teacher' as the main teacher role.
|
||||
if (in_array($pos, ['main', 'teacher'], true)) {
|
||||
// Keep the first "main/teacher" as the teacher, ignore additional conflicts.
|
||||
if ($teacherId === null) {
|
||||
$teacherId = (int)$r['user_id'];
|
||||
$teacherName = $full;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Treat 'ta', 'assistant', 'teacher_assistant' (and similar) as TA roles.
|
||||
if (in_array($pos, ['ta', 'assistant', 'teacher_assistant'], true)) {
|
||||
$tas[] = ['id' => (int)$r['user_id'], 'name' => $full];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Unknown/missing position: don't discard; we’ll use firstSeen as a fallback later.
|
||||
}
|
||||
|
||||
// Fallback: if no explicit main teacher found, use the first record seen.
|
||||
if ($teacherId === null && $firstSeen !== null) {
|
||||
$teacherId = $firstSeen['id'];
|
||||
$teacherName = $firstSeen['name'];
|
||||
}
|
||||
|
||||
return [
|
||||
'teacher_id' => $teacherId,
|
||||
'teacher_name' => $teacherName,
|
||||
'tas' => $tas,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function assignTeacherToClass($teacherId, $classSectionId, $semester, $schoolYear, $position = 'main')
|
||||
{
|
||||
if (!in_array($position, ['main', 'ta'])) {
|
||||
throw new \InvalidArgumentException('Position must be either "main" or "ta"');
|
||||
}
|
||||
|
||||
$existing = $this->where([
|
||||
'teacher_id' => $teacherId,
|
||||
'class_section_id' => $classSectionId,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'position' => $position
|
||||
])->first();
|
||||
|
||||
if ($existing) {
|
||||
return $this->update($existing['id'], ['updated_at' => utc_now()]);
|
||||
}
|
||||
|
||||
return $this->insert([
|
||||
'teacher_id' => $teacherId,
|
||||
'class_section_id' => $classSectionId,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'position' => $position,
|
||||
'created_at' => utc_now(),
|
||||
'updated_at' => utc_now()
|
||||
]);
|
||||
}
|
||||
|
||||
public function findAll($limit = 0, $offset = 0)
|
||||
{
|
||||
return parent::findAll($limit, $offset);
|
||||
}
|
||||
|
||||
public function getAssignedClassSections(int $teacherId, string $schoolYear, string $semester)
|
||||
{
|
||||
return $this->select('teacher_class.class_section_id, teacher_class.position, classSection.class_section_name')
|
||||
->join('classSection', 'classSection.id = teacher_class.class_section_id')
|
||||
->where('teacher_class.teacher_id', $teacherId)
|
||||
->where('teacher_class.school_year', $schoolYear)
|
||||
->where('teacher_class.semester', $semester)
|
||||
->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get assigned teachers (with names) for ONE section code + term.
|
||||
* CI: assignedForSectionTerm()
|
||||
* Returns rows: class_section_id, teacher_id, position, firstname, lastname
|
||||
*/
|
||||
public function assignedForSectionTerm(int $sectionCode, string $semester, string $schoolYear): array
|
||||
public static function assignedForSectionTerm(int $sectionCode, string $semester, string $schoolYear): array
|
||||
{
|
||||
$key = $sectionCode . '|' . $semester . '|' . $schoolYear;
|
||||
if (isset($this->assignedCache[$key])) {
|
||||
return $this->assignedCache[$key];
|
||||
}
|
||||
|
||||
$rows = $this->db->table('teacher_class tc')
|
||||
->select('tc.class_section_id, tc.teacher_id, tc.position, u.firstname, u.lastname')
|
||||
->join('users u', 'u.id = tc.teacher_id', 'left')
|
||||
->where('tc.class_section_id', $sectionCode) // SECTION CODE
|
||||
->where('tc.semester', $semester)
|
||||
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)
|
||||
->orderBy("FIELD(tc.position, 'main','ta')", '', false) // main → ta
|
||||
->orderBy('u.firstname', 'ASC')
|
||||
->get()->getResultArray();
|
||||
|
||||
return $this->assignedCache[$key] = $rows;
|
||||
->orderByRaw("FIELD(tc.position,'main','ta')")
|
||||
->orderBy('u.firstname', 'asc')
|
||||
->get()
|
||||
->map(fn ($r) => (array) $r)
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience: same as above but keyed by teacher_id.
|
||||
* Returns: [teacher_id] => row
|
||||
*/
|
||||
public function assignedMapForSectionTerm(int $sectionCode, string $semester, string $schoolYear): array
|
||||
/** CI: assignedMapForSectionTerm() */
|
||||
public static function assignedMapForSectionTerm(int $sectionCode, string $semester, string $schoolYear): array
|
||||
{
|
||||
$out = [];
|
||||
foreach ($this->assignedForSectionTerm($sectionCode, $semester, $schoolYear) as $r) {
|
||||
$out[(int)$r['teacher_id']] = $r;
|
||||
foreach (static::assignedForSectionTerm($sectionCode, $semester, $schoolYear) as $r) {
|
||||
$out[(int) $r['teacher_id']] = $r;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch helper for a whole term (optionally filtered to some sections).
|
||||
* CI: assignedBySectionForTerm()
|
||||
* Returns: [sectionCode] => [rows...]
|
||||
*/
|
||||
public function assignedBySectionForTerm(string $semester, string $schoolYear, ?array $onlySectionCodes = null): array
|
||||
public static function assignedBySectionForTerm(string $semester, string $schoolYear, ?array $onlySectionCodes = null): array
|
||||
{
|
||||
$cacheKey = ($onlySectionCodes ? implode(',', array_map('intval', $onlySectionCodes)) : '*') . '|' . $semester . '|' . $schoolYear;
|
||||
if (isset($this->assignedBySectionCache[$cacheKey])) {
|
||||
return $this->assignedBySectionCache[$cacheKey];
|
||||
}
|
||||
|
||||
$qb = $this->db->table('teacher_class tc')
|
||||
->select('tc.class_section_id, tc.teacher_id, tc.position, u.firstname, u.lastname')
|
||||
->join('users u', 'u.id = tc.teacher_id', 'left')
|
||||
->where('tc.semester', $semester)
|
||||
$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')
|
||||
->orderBy("FIELD(tc.position, 'main','ta')", '', false)
|
||||
->orderBy('u.firstname', 'ASC');
|
||||
->orderBy('tc.class_section_id', 'asc')
|
||||
->orderByRaw("FIELD(tc.position,'main','ta')")
|
||||
->orderBy('u.firstname', 'asc');
|
||||
|
||||
if (!empty($onlySectionCodes)) {
|
||||
$qb->whereIn('tc.class_section_id', array_map('intval', $onlySectionCodes));
|
||||
$ids = array_values(array_unique(array_filter(array_map('intval', $onlySectionCodes))));
|
||||
if (!empty($ids)) $q->whereIn('tc.class_section_id', $ids);
|
||||
}
|
||||
|
||||
$rows = $qb->get()->getResultArray();
|
||||
$rows = $q->get()->map(fn ($r) => (array) $r)->all();
|
||||
|
||||
$out = [];
|
||||
foreach ($rows as $r) {
|
||||
$code = (int)$r['class_section_id'];
|
||||
$code = (int) ($r['class_section_id'] ?? 0);
|
||||
if ($code <= 0) continue;
|
||||
$out[$code][] = $r;
|
||||
}
|
||||
|
||||
return $this->assignedBySectionCache[$cacheKey] = $out;
|
||||
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'],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user