reconstruction of the project
This commit is contained in:
+261
-60
@@ -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 StudentClass extends BaseModel
|
||||
{
|
||||
protected $table = 'student_class';
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
protected $fillable = [
|
||||
'student_id',
|
||||
'class_section_id',
|
||||
@@ -19,91 +22,289 @@ class StudentClass extends BaseModel
|
||||
'updated_at',
|
||||
'updated_by',
|
||||
];
|
||||
|
||||
public $timestamps = true;
|
||||
const CREATED_AT = 'created_at';
|
||||
const UPDATED_AT = 'updated_at';
|
||||
|
||||
public function getClassSectionNameByStudentId(int $studentId): ?string
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'is_event_only' => 'boolean',
|
||||
'updated_by' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* ============================================================
|
||||
* Relationships (optional but recommended)
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
public function student(): BelongsTo
|
||||
{
|
||||
return $this->db->table($this->table)
|
||||
->select('cs.class_section_name')
|
||||
->join('class_sections as cs', 'cs.class_section_id', '=', 'student_class.class_section_id')
|
||||
->where('student_class.student_id', $studentId)
|
||||
->get()
|
||||
->getRow('class_section_name');
|
||||
return $this->belongsTo(Student::class, 'student_id');
|
||||
}
|
||||
|
||||
|
||||
// Custom findAll() method
|
||||
public function findAll($limit = 0, $offset = 0)
|
||||
public function classSection(): BelongsTo
|
||||
{
|
||||
// Optional: Add custom logic before fetching all records
|
||||
// For example, you can add default conditions:
|
||||
// $this->where('semester', 'Fall');
|
||||
|
||||
// Then call the parent findAll method to fetch the records
|
||||
return parent::findAll($limit, $offset);
|
||||
// Your CI joins on classSection.class_section_id
|
||||
return $this->belongsTo(ClassSection::class, 'class_section_id', 'class_section_id');
|
||||
}
|
||||
|
||||
// Method to get all students in a specific class section
|
||||
public function getClassStudents($classSectionId)
|
||||
public function school(): BelongsTo
|
||||
{
|
||||
return $this->where('class_section_id', $classSectionId)->findAll();
|
||||
return $this->belongsTo(School::class, 'school_id');
|
||||
}
|
||||
|
||||
public function getClassSectionsByStudentId($studentId, string $schoolYear)
|
||||
public function updater(): BelongsTo
|
||||
{
|
||||
// Build the query
|
||||
$builder = $this->db->table('student_class')
|
||||
->select('cs.class_section_name')
|
||||
->join('class_sections as cs', 'student_class.class_section_id', '=', 'cs.class_section_id')
|
||||
->where('student_class.student_id', $studentId) // Filter by student ID
|
||||
->where('student_class.class_section_id IS NOT NULL') // Ensure class_section_id is not null
|
||||
->where('student_class.school_year', $schoolYear); // Filter by school year
|
||||
|
||||
// Fetch the result
|
||||
$result = $builder->get()->getRowArray();
|
||||
|
||||
// Check if the result is not null before accessing the 'class_section_name'
|
||||
if ($result && isset($result['class_section_name'])) {
|
||||
return $result['class_section_name']; // Return the class_section_name
|
||||
} else {
|
||||
return ''; // Return an empty string if no class section is found
|
||||
}
|
||||
return $this->belongsTo(User::class, 'updated_by'); // change to Admin if needed
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Scopes
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
public function getStudentsByClassSectionIds(array $classSectionIds)
|
||||
/**
|
||||
* Scope: only students active for classes/attendance (joins students).
|
||||
* Mirrors CI active().
|
||||
*/
|
||||
public function scopeActive(Builder $q): Builder
|
||||
{
|
||||
return $this->select('students.id as student_id, students.firstname, students.lastname, students.school_id, students.is_new,students.photo_consent ,students.age, student_class.semester, student_class.school_year, student_class.class_section_id')
|
||||
return $q->select('student_class.*')
|
||||
->join('students', 'students.id', '=', 'student_class.student_id')
|
||||
->whereIn('student_class.class_section_id', $classSectionIds)
|
||||
->where('students.is_active', 1);
|
||||
}
|
||||
|
||||
public function scopeForSection(Builder $q, int $classSectionId): Builder
|
||||
{
|
||||
return $q->where('student_class.class_section_id', $classSectionId);
|
||||
}
|
||||
|
||||
public function scopeForYear(Builder $q, ?string $schoolYear): Builder
|
||||
{
|
||||
if ($schoolYear === null || trim($schoolYear) === '') return $q;
|
||||
return $q->where('student_class.school_year', $schoolYear);
|
||||
}
|
||||
|
||||
public function scopeNonEvent(Builder $q): Builder
|
||||
{
|
||||
return $q->where('student_class.is_event_only', 0);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* CI-compatible methods (rewritten Laravel-style)
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
public static function getClassSectionNameByStudentId(int $studentId): ?string
|
||||
{
|
||||
return DB::table('student_class as sc')
|
||||
->join('classSection as cs', 'cs.class_section_id', '=', 'sc.class_section_id')
|
||||
->where('sc.student_id', $studentId)
|
||||
->value('cs.class_section_name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all students in a specific class section (optionally scoped to schoolYear), active students only.
|
||||
* Mirrors getClassStudents()
|
||||
*/
|
||||
public static function getClassStudents(int $classSectionId, ?string $schoolYear = null)
|
||||
{
|
||||
return static::query()
|
||||
->active()
|
||||
->forSection($classSectionId)
|
||||
->forYear($schoolYear)
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return class section names for a student in a given school year.
|
||||
* Mirrors getClassSectionsByStudentId()
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public static function getClassSectionsByStudentId($studentId, string $schoolYear, bool $asArray = false)
|
||||
{
|
||||
$names = DB::table('student_class as sc')
|
||||
->join('classSection as cs', 'cs.class_section_id', '=', 'sc.class_section_id')
|
||||
->where('sc.student_id', $studentId)
|
||||
->whereNotNull('sc.class_section_id')
|
||||
->where('sc.school_year', $schoolYear)
|
||||
->orderBy('cs.class_section_name', 'asc')
|
||||
->pluck('cs.class_section_name')
|
||||
->filter(fn ($v) => $v !== null && trim((string)$v) !== '')
|
||||
->unique()
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return $asArray ? $names : (!empty($names) ? implode(', ', $names) : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return class section names for a student in a given school year, with optional event flag.
|
||||
* Mirrors getClassSectionsByStudentIdWithFlags()
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
public static function getClassSectionsByStudentIdWithFlags($studentId, string $schoolYear, bool $asArray = false)
|
||||
{
|
||||
$rows = DB::table('student_class as sc')
|
||||
->select('cs.class_section_name', 'sc.is_event_only')
|
||||
->join('classSection as cs', 'cs.class_section_id', '=', 'sc.class_section_id')
|
||||
->where('sc.student_id', $studentId)
|
||||
->whereNotNull('sc.class_section_id')
|
||||
->where('sc.school_year', $schoolYear)
|
||||
->orderBy('cs.class_section_name', 'asc')
|
||||
->get();
|
||||
|
||||
$names = [];
|
||||
foreach ($rows as $r) {
|
||||
$name = $r->class_section_name ?? null;
|
||||
if (!$name) continue;
|
||||
|
||||
$isEvent = (int)($r->is_event_only ?? 0) === 1;
|
||||
$names[] = $isEvent ? ($name . ' (Event)') : $name;
|
||||
}
|
||||
|
||||
$names = array_values(array_unique(array_filter($names)));
|
||||
|
||||
return $asArray ? $names : (!empty($names) ? implode(', ', $names) : '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return class_section_id values for a student/year.
|
||||
* Mirrors getClassSectionIdsByStudentId()
|
||||
*/
|
||||
public static function getClassSectionIdsByStudentId($studentId, string $schoolYear): array
|
||||
{
|
||||
$ids = DB::table('student_class')
|
||||
->where('student_id', $studentId)
|
||||
->whereNotNull('class_section_id')
|
||||
->where('school_year', $schoolYear)
|
||||
->pluck('class_section_id')
|
||||
->map(fn ($v) => (int) $v)
|
||||
->filter(fn ($v) => $v > 0)
|
||||
->unique()
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors getStudentsByClassSectionIds()
|
||||
* Returns array rows (not models) like CI.
|
||||
*/
|
||||
public static function getStudentsByClassSectionIds(array $classSectionIds): array
|
||||
{
|
||||
$ids = array_values(array_unique(array_filter(array_map('intval', $classSectionIds))));
|
||||
if (empty($ids)) return [];
|
||||
|
||||
return DB::table('student_class as sc')
|
||||
->selectRaw('
|
||||
students.id as student_id,
|
||||
students.firstname,
|
||||
students.lastname,
|
||||
students.school_id,
|
||||
students.is_new,
|
||||
students.photo_consent,
|
||||
students.age,
|
||||
sc.school_year,
|
||||
sc.class_section_id
|
||||
')
|
||||
->join('students', 'students.id', '=', 'sc.student_id')
|
||||
->whereIn('sc.class_section_id', $ids)
|
||||
->where('students.is_active', 1)
|
||||
->get()
|
||||
->getResultArray();
|
||||
->map(fn ($r) => (array) $r)
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class ID (grade) for a specific student.
|
||||
*
|
||||
* @param int $studentId
|
||||
* @return string class_id or 'N/A'
|
||||
* Mirrors getStudentGrade()
|
||||
*/
|
||||
public function getStudentGrade(int $studentId): string
|
||||
public static function getStudentGrade(int $studentId): string
|
||||
{
|
||||
$studentClass = $this->where('student_id', $studentId)
|
||||
->orderBy('created_at', 'DESC') // in case of multiple entries, get latest
|
||||
$sc = static::query()
|
||||
->where('student_id', $studentId)
|
||||
->where('is_event_only', 0)
|
||||
->orderByDesc('created_at')
|
||||
->first();
|
||||
|
||||
if ($studentClass && isset($studentClass['class_section_id'])) {
|
||||
$classSection = $this->db->table('class_sections')
|
||||
->where('class_section_id', $studentClass['class_section_id'])
|
||||
->get()
|
||||
->getRowArray();
|
||||
|
||||
return $classSection['class_id'] ?? 'N/A';
|
||||
if (!$sc || !$sc->class_section_id) {
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
log_message('error', "Student class or section not found for student ID: $studentId");
|
||||
return 'N/A';
|
||||
$classId = DB::table('classSection')
|
||||
->where('class_section_id', $sc->class_section_id)
|
||||
->value('class_id');
|
||||
|
||||
return $classId ?: 'N/A';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the student has at least one non-event class assignment for the year.
|
||||
* Mirrors hasNonEventAssignment()
|
||||
*/
|
||||
public static function hasNonEventAssignment(int $studentId, string $schoolYear): bool
|
||||
{
|
||||
return static::query()
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $schoolYear)
|
||||
->where('is_event_only', 0)
|
||||
->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return student counts per class_section_id, optionally scoped to a school year.
|
||||
* Mirrors getStudentCountsBySection()
|
||||
*
|
||||
* @return array<int|string,int> Map of class_section_id => count
|
||||
*/
|
||||
public static function getStudentCountsBySection(?string $schoolYear = null): array
|
||||
{
|
||||
$q = DB::table('student_class as sc')
|
||||
->selectRaw('sc.class_section_id, COUNT(*) as total')
|
||||
->join('students', 'students.id', '=', 'sc.student_id')
|
||||
->where('students.is_active', 1)
|
||||
->whereNotNull('sc.class_section_id')
|
||||
->groupBy('sc.class_section_id');
|
||||
|
||||
if ($schoolYear !== null && trim($schoolYear) !== '') {
|
||||
$q->where('sc.school_year', $schoolYear);
|
||||
}
|
||||
|
||||
$rows = $q->get();
|
||||
|
||||
$out = [];
|
||||
foreach ($rows as $r) {
|
||||
$cid = $r->class_section_id;
|
||||
if ($cid === null || $cid === '') continue;
|
||||
$out[$cid] = (int) ($r->total ?? 0);
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* Optional validation helper
|
||||
* ============================================================
|
||||
*/
|
||||
public static function rules(bool $updating = false): array
|
||||
{
|
||||
$req = $updating ? 'sometimes' : 'required';
|
||||
|
||||
return [
|
||||
'student_id' => [$req, 'integer', 'min:1', 'exists:students,id'],
|
||||
'school_id' => ['nullable', 'integer', 'min:1'],
|
||||
'class_section_id' => ['nullable', 'integer'],
|
||||
'school_year' => [$req, 'string', 'max:20'],
|
||||
'is_event_only' => ['nullable', 'boolean'],
|
||||
'description' => ['nullable', 'string', 'max:2000'],
|
||||
'updated_by' => ['nullable', 'integer'],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user