Fix Laravel Pint formatting
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AdditionalCharge extends BaseModel
|
||||
@@ -28,10 +27,10 @@ class AdditionalCharge extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'parent_id' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'amount' => 'decimal:2', // adjust if you store more precision
|
||||
'due_date' => 'date', // if due_date is DATE/DATETIME
|
||||
'amount' => 'decimal:2', // adjust if you store more precision
|
||||
'due_date' => 'date', // if due_date is DATE/DATETIME
|
||||
'created_by' => 'integer',
|
||||
];
|
||||
|
||||
@@ -120,7 +119,7 @@ class AdditionalCharge extends BaseModel
|
||||
$affected = static::query()
|
||||
->whereIn('id', $ids)
|
||||
->update([
|
||||
'status' => 'applied',
|
||||
'status' => 'applied',
|
||||
'invoice_id' => $invoiceId,
|
||||
]);
|
||||
|
||||
@@ -157,18 +156,18 @@ class AdditionalCharge extends BaseModel
|
||||
$query->where('additional_charges.semester', $semFilter);
|
||||
}
|
||||
|
||||
if (!empty($status)) {
|
||||
if (! empty($status)) {
|
||||
$query->where('additional_charges.status', $status);
|
||||
}
|
||||
|
||||
if (!empty($q)) {
|
||||
if (! empty($q)) {
|
||||
$term = trim($q);
|
||||
$query->where(function ($w) use ($term) {
|
||||
$w->where('additional_charges.title', 'like', "%{$term}%")
|
||||
->orWhere('additional_charges.description', 'like', "%{$term}%")
|
||||
->orWhere('users.firstname', 'like', "%{$term}%")
|
||||
->orWhere('users.lastname', 'like', "%{$term}%")
|
||||
->orWhere('invoices.invoice_number', 'like', "%{$term}%");
|
||||
->orWhere('additional_charges.description', 'like', "%{$term}%")
|
||||
->orWhere('users.firstname', 'like', "%{$term}%")
|
||||
->orWhere('users.lastname', 'like', "%{$term}%")
|
||||
->orWhere('invoices.invoice_number', 'like', "%{$term}%");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class AdminNotificationSubject extends BaseModel
|
||||
{
|
||||
protected $table = 'admin_notification_subjects';
|
||||
@@ -16,7 +14,8 @@ class AdminNotificationSubject extends BaseModel
|
||||
];
|
||||
|
||||
// legacy uses created_at / updated_at
|
||||
public $timestamps = true;
|
||||
public $timestamps = true;
|
||||
|
||||
protected $casts = [
|
||||
'admin_id' => 'integer',
|
||||
];
|
||||
@@ -26,4 +25,4 @@ class AdminNotificationSubject extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'admin_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class AttendanceCommentTemplate extends BaseModel
|
||||
{
|
||||
protected $table = 'attendance_comment_template';
|
||||
@@ -43,4 +41,4 @@ class AttendanceCommentTemplate extends BaseModel
|
||||
{
|
||||
return $q->where('is_active', 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+117
-73
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AttendanceData extends BaseModel
|
||||
{
|
||||
protected $table = 'attendance_data';
|
||||
|
||||
public $timestamps = true; // uses created_at / updated_at
|
||||
|
||||
protected $fillable = [
|
||||
@@ -30,12 +30,12 @@ class AttendanceData extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'class_id' => 'integer',
|
||||
'class_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'modified_by' => 'integer',
|
||||
'date' => 'datetime', // ✅ DATETIME column
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'modified_by' => 'integer',
|
||||
'date' => 'datetime', // ✅ DATETIME column
|
||||
];
|
||||
|
||||
/* =========================
|
||||
@@ -59,6 +59,7 @@ class AttendanceData extends BaseModel
|
||||
$day = substr($day, 0, 10); // YYYY-MM-DD
|
||||
$start = Carbon::parse($day)->startOfDay();
|
||||
$endEx = Carbon::parse($day)->addDay()->startOfDay(); // exclusive
|
||||
|
||||
return [$start, $endEx];
|
||||
}
|
||||
|
||||
@@ -87,6 +88,7 @@ class AttendanceData extends BaseModel
|
||||
public static function updateAttendance(int $attendanceId, array $data): bool
|
||||
{
|
||||
$affected = static::query()->whereKey($attendanceId)->update($data);
|
||||
|
||||
return $affected >= 0;
|
||||
}
|
||||
|
||||
@@ -113,7 +115,7 @@ class AttendanceData extends BaseModel
|
||||
$q = static::query();
|
||||
static::applyReportedFilter($q);
|
||||
|
||||
[$start, ] = static::dayRange($startDate);
|
||||
[$start] = static::dayRange($startDate);
|
||||
|
||||
if ($endDate) {
|
||||
[, $endEx] = static::dayRange($endDate); // end exclusive of next day
|
||||
@@ -134,13 +136,19 @@ class AttendanceData extends BaseModel
|
||||
->where('date', '>=', $start)
|
||||
->where('date', '<', $endEx)
|
||||
->where(function ($w) {
|
||||
$w->whereIn(DB::raw("UPPER(TRIM(status))"), ['ABSENT', 'ABS', 'A'])
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'ABS%'");
|
||||
$w->whereIn(DB::raw('UPPER(TRIM(status))'), ['ABSENT', 'ABS', 'A'])
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'ABS%'");
|
||||
});
|
||||
|
||||
if ($classSectionId !== null) $q->where('class_section_id', $classSectionId);
|
||||
if ($schoolYear !== null) $q->where('school_year', $schoolYear);
|
||||
if ($semester !== null) $q->where('semester', $semester);
|
||||
if ($classSectionId !== null) {
|
||||
$q->where('class_section_id', $classSectionId);
|
||||
}
|
||||
if ($schoolYear !== null) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
if ($semester !== null) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
|
||||
return $q->get();
|
||||
}
|
||||
@@ -153,13 +161,19 @@ class AttendanceData extends BaseModel
|
||||
->where('date', '>=', $start)
|
||||
->where('date', '<', $endEx)
|
||||
->where(function ($w) {
|
||||
$w->whereIn(DB::raw("UPPER(TRIM(status))"), ['LATE', 'L'])
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'LATE%'");
|
||||
$w->whereIn(DB::raw('UPPER(TRIM(status))'), ['LATE', 'L'])
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'LATE%'");
|
||||
});
|
||||
|
||||
if ($classSectionId !== null) $q->where('class_section_id', $classSectionId);
|
||||
if ($schoolYear !== null) $q->where('school_year', $schoolYear);
|
||||
if ($semester !== null) $q->where('semester', $semester);
|
||||
if ($classSectionId !== null) {
|
||||
$q->where('class_section_id', $classSectionId);
|
||||
}
|
||||
if ($schoolYear !== null) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
if ($semester !== null) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
|
||||
return $q->get();
|
||||
}
|
||||
@@ -171,8 +185,8 @@ class AttendanceData extends BaseModel
|
||||
->where('school_year', $schoolYear)
|
||||
->where('semester', $semester)
|
||||
->where(function ($w) {
|
||||
$w->whereIn(DB::raw("UPPER(TRIM(status))"), ['ABSENT', 'ABS', 'A'])
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'ABS%'");
|
||||
$w->whereIn(DB::raw('UPPER(TRIM(status))'), ['ABSENT', 'ABS', 'A'])
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'ABS%'");
|
||||
})
|
||||
->orderByDesc('date')
|
||||
->get();
|
||||
@@ -185,22 +199,26 @@ class AttendanceData extends BaseModel
|
||||
public static function getStudentAttendance(
|
||||
int $studentId,
|
||||
?string $startDate = null,
|
||||
?string $endDate = null,
|
||||
?string $endDate = null,
|
||||
?string $schoolYear = null,
|
||||
?string $semester = null
|
||||
?string $semester = null
|
||||
) {
|
||||
$q = static::query()->where('student_id', $studentId);
|
||||
|
||||
if (!empty($startDate)) {
|
||||
[$start, ] = static::dayRange($startDate);
|
||||
if (! empty($startDate)) {
|
||||
[$start] = static::dayRange($startDate);
|
||||
$q->where('date', '>=', $start);
|
||||
}
|
||||
if (!empty($endDate)) {
|
||||
if (! empty($endDate)) {
|
||||
[, $endEx] = static::dayRange($endDate);
|
||||
$q->where('date', '<', $endEx);
|
||||
}
|
||||
if (!empty($schoolYear)) $q->where('school_year', $schoolYear);
|
||||
if (!empty($semester)) $q->where('semester', $semester);
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
if (! empty($semester)) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
|
||||
return $q->orderByDesc('date')->get();
|
||||
}
|
||||
@@ -225,13 +243,13 @@ class AttendanceData extends BaseModel
|
||||
public static function unreportedTermRows(array $studentIds, string $schoolYear, ?string $semester)
|
||||
{
|
||||
$q = static::query()
|
||||
->select(['id','student_id','class_id','class_section_id','date','status','reason','school_year','semester','is_reported'])
|
||||
->select(['id', 'student_id', 'class_id', 'class_section_id', 'date', 'status', 'reason', 'school_year', 'semester', 'is_reported'])
|
||||
->where('school_year', $schoolYear);
|
||||
|
||||
if ($semester !== null && $semester !== '') {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
if (!empty($studentIds)) {
|
||||
if (! empty($studentIds)) {
|
||||
$q->whereIn('student_id', array_map('intval', $studentIds));
|
||||
}
|
||||
|
||||
@@ -247,26 +265,30 @@ class AttendanceData extends BaseModel
|
||||
public static function getUnreportedAbsencesAndLates(?string $schoolYear = null, ?string $semester = null): array
|
||||
{
|
||||
$q = static::query()
|
||||
->select(['id','student_id','class_id','class_section_id','date','status','reason','school_year','semester','is_reported']);
|
||||
->select(['id', 'student_id', 'class_id', 'class_section_id', 'date', 'status', 'reason', 'school_year', 'semester', 'is_reported']);
|
||||
|
||||
static::applyUnreportedFilter($q);
|
||||
|
||||
// Not notified yet: supports 0/'0'/NULL and string enums like 'yes'
|
||||
$q->where(function ($w) {
|
||||
$w->whereNull('is_notified')
|
||||
->orWhere('is_notified', 0)
|
||||
->orWhere('is_notified', '0')
|
||||
->orWhereRaw("LOWER(TRIM(COALESCE(is_notified, ''))) != 'yes'");
|
||||
->orWhere('is_notified', 0)
|
||||
->orWhere('is_notified', '0')
|
||||
->orWhereRaw("LOWER(TRIM(COALESCE(is_notified, ''))) != 'yes'");
|
||||
});
|
||||
|
||||
if (!empty($schoolYear)) $q->where('school_year', $schoolYear);
|
||||
if (!empty($semester)) $q->where('semester', $semester);
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
if (! empty($semester)) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
|
||||
// Status filter: exact + prefixes (ABS_3, LATE_2, etc.)
|
||||
$q->where(function ($w) {
|
||||
$w->whereIn(DB::raw("UPPER(TRIM(status))"), ['ABS','ABSENT','LATE','A','L'])
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'ABS%'")
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'LATE%'");
|
||||
$w->whereIn(DB::raw('UPPER(TRIM(status))'), ['ABS', 'ABSENT', 'LATE', 'A', 'L'])
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'ABS%'")
|
||||
->orWhereRaw("UPPER(TRIM(status)) LIKE 'LATE%'");
|
||||
});
|
||||
|
||||
$rows = $q->orderBy('student_id')->orderByDesc('date')->get()->toArray();
|
||||
@@ -275,27 +297,27 @@ class AttendanceData extends BaseModel
|
||||
foreach ($rows as $r) {
|
||||
$sid = (int) ($r['student_id'] ?? 0);
|
||||
|
||||
if (!isset($out[$sid])) {
|
||||
if (! isset($out[$sid])) {
|
||||
$out[$sid] = [
|
||||
'absences' => [],
|
||||
'lates' => [],
|
||||
'counts' => ['absences' => 0, 'lates' => 0, 'total' => 0],
|
||||
'lates' => [],
|
||||
'counts' => ['absences' => 0, 'lates' => 0, 'total' => 0],
|
||||
];
|
||||
}
|
||||
|
||||
$st = strtoupper(trim((string)($r['status'] ?? '')));
|
||||
$isAbs = ($st === 'ABS' || $st === 'ABSENT' || $st === 'A' || str_starts_with($st, 'ABS'));
|
||||
$st = strtoupper(trim((string) ($r['status'] ?? '')));
|
||||
$isAbs = ($st === 'ABS' || $st === 'ABSENT' || $st === 'A' || str_starts_with($st, 'ABS'));
|
||||
$isLate = ($st === 'LATE' || $st === 'L' || str_starts_with($st, 'LATE'));
|
||||
|
||||
$rec = [
|
||||
'id' => $r['id'] ?? null,
|
||||
'date' => $r['date'] ?? null,
|
||||
'status' => $r['status'] ?? null,
|
||||
'reason' => $r['reason'] ?? null,
|
||||
'class_id' => $r['class_id'] ?? null,
|
||||
'id' => $r['id'] ?? null,
|
||||
'date' => $r['date'] ?? null,
|
||||
'status' => $r['status'] ?? null,
|
||||
'reason' => $r['reason'] ?? null,
|
||||
'class_id' => $r['class_id'] ?? null,
|
||||
'class_section_id' => $r['class_section_id'] ?? null,
|
||||
'school_year' => $r['school_year'] ?? null,
|
||||
'semester' => $r['semester'] ?? null,
|
||||
'school_year' => $r['school_year'] ?? null,
|
||||
'semester' => $r['semester'] ?? null,
|
||||
];
|
||||
|
||||
if ($isAbs) {
|
||||
@@ -329,12 +351,16 @@ class AttendanceData extends BaseModel
|
||||
->where('date', '>=', $start)
|
||||
->where('date', '<', $endEx);
|
||||
|
||||
if (!empty($semester)) $q->where('semester', $semester);
|
||||
if (!empty($schoolYear)) $q->where('school_year', $schoolYear);
|
||||
if (! empty($semester)) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
$affected = $q->update([
|
||||
'is_notified' => 'yes',
|
||||
'updated_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return $affected >= 0;
|
||||
@@ -349,14 +375,20 @@ class AttendanceData extends BaseModel
|
||||
return is_string($d) && preg_match('/^\d{4}-\d{2}-\d{2}$/', $d);
|
||||
})));
|
||||
|
||||
if (empty($dates)) return true;
|
||||
if (empty($dates)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$q = static::query()
|
||||
->where('student_id', $studentId)
|
||||
->whereRaw("LOWER(TRIM(status)) IN ('absent','late')");
|
||||
|
||||
if (!empty($semester)) $q->where('semester', $semester);
|
||||
if (!empty($schoolYear)) $q->where('school_year', $schoolYear);
|
||||
if (! empty($semester)) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
// OR day ranges instead of DATE(date)
|
||||
$q->where(function ($w) use ($dates) {
|
||||
@@ -370,13 +402,17 @@ class AttendanceData extends BaseModel
|
||||
});
|
||||
|
||||
$payload = [
|
||||
'updated_at' => now(),
|
||||
'updated_at' => now(),
|
||||
'is_notified' => 'yes',
|
||||
];
|
||||
|
||||
$cols = static::reportedColumns();
|
||||
if (!empty($cols['is_reported'])) $payload['is_reported'] = 'yes';
|
||||
if (!empty($cols['reported'])) $payload['reported'] = 1;
|
||||
if (! empty($cols['is_reported'])) {
|
||||
$payload['is_reported'] = 'yes';
|
||||
}
|
||||
if (! empty($cols['reported'])) {
|
||||
$payload['reported'] = 1;
|
||||
}
|
||||
|
||||
$affected = $q->update($payload);
|
||||
|
||||
@@ -394,7 +430,9 @@ class AttendanceData extends BaseModel
|
||||
?string $semester = null,
|
||||
?string $schoolYear = null
|
||||
): array {
|
||||
if ($studentId <= 0 || empty($statuses)) return [];
|
||||
if ($studentId <= 0 || empty($statuses)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$statuses = array_map('strtolower', $statuses);
|
||||
|
||||
@@ -403,7 +441,7 @@ class AttendanceData extends BaseModel
|
||||
: now()->toDateString();
|
||||
|
||||
$startDay = Carbon::parse($day)->subDays(max(0, $lookbackDays))->toDateString();
|
||||
[$start, ] = static::dayRange($startDay);
|
||||
[$start] = static::dayRange($startDay);
|
||||
[, $endEx] = static::dayRange($day);
|
||||
|
||||
$q = static::query()
|
||||
@@ -411,17 +449,21 @@ class AttendanceData extends BaseModel
|
||||
->where('student_id', $studentId)
|
||||
->where('date', '>=', $start)
|
||||
->where('date', '<', $endEx)
|
||||
->whereIn(DB::raw("LOWER(TRIM(status))"), $statuses);
|
||||
->whereIn(DB::raw('LOWER(TRIM(status))'), $statuses);
|
||||
|
||||
static::applyUnreportedFilter($q);
|
||||
|
||||
if (!empty($semester)) $q->where('semester', $semester);
|
||||
if (!empty($schoolYear)) $q->where('school_year', $schoolYear);
|
||||
if (! empty($semester)) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
$rows = $q->orderByDesc('date')->pluck('date')->all();
|
||||
|
||||
return array_values(array_unique(array_map(static function ($d) {
|
||||
return substr((string)$d, 0, 10); // YYYY-MM-DD
|
||||
return substr((string) $d, 0, 10); // YYYY-MM-DD
|
||||
}, $rows)));
|
||||
}
|
||||
|
||||
@@ -432,13 +474,15 @@ class AttendanceData extends BaseModel
|
||||
private static function reportedColumns(): array
|
||||
{
|
||||
static $cache = null;
|
||||
if ($cache !== null) return $cache;
|
||||
if ($cache !== null) {
|
||||
return $cache;
|
||||
}
|
||||
|
||||
$table = (new static)->getTable();
|
||||
|
||||
$cache = [
|
||||
'is_reported' => static::columnExists($table, 'is_reported'),
|
||||
'reported' => static::columnExists($table, 'reported'),
|
||||
'reported' => static::columnExists($table, 'reported'),
|
||||
];
|
||||
|
||||
return $cache;
|
||||
@@ -464,16 +508,16 @@ class AttendanceData extends BaseModel
|
||||
{
|
||||
$cols = static::reportedColumns();
|
||||
|
||||
if (!empty($cols['is_reported'])) {
|
||||
if (! empty($cols['is_reported'])) {
|
||||
$q->where(function ($w) {
|
||||
$w->whereNull('is_reported')
|
||||
->orWhere('is_reported', 0)
|
||||
->orWhere('is_reported', '0')
|
||||
->orWhereRaw("LOWER(TRIM(COALESCE(is_reported, ''))) = 'no'");
|
||||
->orWhere('is_reported', 0)
|
||||
->orWhere('is_reported', '0')
|
||||
->orWhereRaw("LOWER(TRIM(COALESCE(is_reported, ''))) = 'no'");
|
||||
});
|
||||
}
|
||||
|
||||
if (!empty($cols['reported'])) {
|
||||
if (! empty($cols['reported'])) {
|
||||
$q->whereRaw("(LOWER(TRIM(COALESCE(reported, ''))) NOT IN ('yes','1','true','y','on'))");
|
||||
}
|
||||
}
|
||||
@@ -485,8 +529,8 @@ class AttendanceData extends BaseModel
|
||||
{
|
||||
$q->where(function ($w) {
|
||||
$w->where('is_reported', 1)
|
||||
->orWhere('is_reported', '1')
|
||||
->orWhereRaw("LOWER(TRIM(COALESCE(is_reported, ''))) = 'yes'");
|
||||
->orWhere('is_reported', '1')
|
||||
->orWhereRaw("LOWER(TRIM(COALESCE(is_reported, ''))) = 'yes'");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class AttendanceDay extends BaseModel
|
||||
{
|
||||
@@ -39,20 +38,20 @@ class AttendanceDay extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'class_section_id' => 'integer',
|
||||
'submitted_by' => 'integer',
|
||||
'published_by' => 'integer',
|
||||
'reopened_by' => 'integer',
|
||||
'submitted_by' => 'integer',
|
||||
'published_by' => 'integer',
|
||||
'reopened_by' => 'integer',
|
||||
|
||||
// If these are DATETIME columns:
|
||||
'submitted_at' => 'datetime',
|
||||
'published_at' => 'datetime',
|
||||
'auto_publish_at' => 'datetime',
|
||||
'reopened_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'submitted_at' => 'datetime',
|
||||
'published_at' => 'datetime',
|
||||
'auto_publish_at' => 'datetime',
|
||||
'reopened_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
|
||||
// If date is stored as DATE string; if it's DATETIME, change to 'datetime'
|
||||
'date' => 'date',
|
||||
'date' => 'date',
|
||||
];
|
||||
|
||||
/* =========================
|
||||
@@ -75,11 +74,15 @@ class AttendanceDay extends BaseModel
|
||||
->whereDate('date', $date)
|
||||
->where(function ($w) {
|
||||
$w->where('status', 'published')
|
||||
->orWhere('status', 'finalized'); // legacy
|
||||
->orWhere('status', 'finalized'); // legacy
|
||||
});
|
||||
|
||||
if ($semester !== null) $q->where('semester', $semester);
|
||||
if ($schoolYear !== null) $q->where('school_year', $schoolYear);
|
||||
if ($semester !== null) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
if ($schoolYear !== null) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
return $q->exists();
|
||||
}
|
||||
@@ -113,7 +116,9 @@ class AttendanceDay extends BaseModel
|
||||
int $userId = 0
|
||||
): self {
|
||||
$row = static::findBySectionDate($classSectionId, $date, $semester, $schoolYear);
|
||||
if ($row) return $row;
|
||||
if ($row) {
|
||||
return $row;
|
||||
}
|
||||
|
||||
$now = now();
|
||||
$normalizedDate = Carbon::parse($date)->toDateString();
|
||||
@@ -121,25 +126,27 @@ class AttendanceDay extends BaseModel
|
||||
try {
|
||||
return static::create([
|
||||
'class_section_id' => $classSectionId,
|
||||
'date' => $normalizedDate,
|
||||
'status' => 'draft',
|
||||
'submitted_by' => null,
|
||||
'submitted_at' => null,
|
||||
'published_by' => null,
|
||||
'published_at' => null,
|
||||
'auto_publish_at' => null,
|
||||
'reopened_by' => null,
|
||||
'reopened_at' => null,
|
||||
'reopen_reason' => null,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
'date' => $normalizedDate,
|
||||
'status' => 'draft',
|
||||
'submitted_by' => null,
|
||||
'submitted_at' => null,
|
||||
'published_by' => null,
|
||||
'published_at' => null,
|
||||
'auto_publish_at' => null,
|
||||
'reopened_by' => null,
|
||||
'reopened_at' => null,
|
||||
'reopen_reason' => null,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
} catch (QueryException $e) {
|
||||
// Race: someone inserted same unique key.
|
||||
$row = static::findBySectionDate($classSectionId, $date, $semester, $schoolYear);
|
||||
if ($row) return $row;
|
||||
if ($row) {
|
||||
return $row;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
@@ -160,10 +167,10 @@ class AttendanceDay extends BaseModel
|
||||
$now = now();
|
||||
|
||||
$payload = [
|
||||
'status' => 'submitted',
|
||||
'status' => 'submitted',
|
||||
'submitted_by' => $userId,
|
||||
'submitted_at' => $now,
|
||||
'updated_at' => $now,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
|
||||
if ($autoPublishAt !== null) {
|
||||
@@ -181,10 +188,10 @@ class AttendanceDay extends BaseModel
|
||||
$now = now();
|
||||
|
||||
return static::query()->whereKey($this->id)->update([
|
||||
'status' => 'published',
|
||||
'status' => 'published',
|
||||
'published_by' => $userId,
|
||||
'published_at' => $now,
|
||||
'updated_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]) >= 0;
|
||||
}
|
||||
|
||||
@@ -193,18 +200,18 @@ class AttendanceDay extends BaseModel
|
||||
*/
|
||||
public function reopen(int $userId, string $toStatus = 'draft', ?string $reason = null): bool
|
||||
{
|
||||
if (!in_array($toStatus, ['draft', 'submitted'], true)) {
|
||||
if (! in_array($toStatus, ['draft', 'submitted'], true)) {
|
||||
throw new \InvalidArgumentException('toStatus must be "draft" or "submitted".');
|
||||
}
|
||||
|
||||
$now = now();
|
||||
|
||||
return static::query()->whereKey($this->id)->update([
|
||||
'status' => $toStatus,
|
||||
'reopened_by' => $userId,
|
||||
'reopened_at' => $now,
|
||||
'status' => $toStatus,
|
||||
'reopened_by' => $userId,
|
||||
'reopened_at' => $now,
|
||||
'reopen_reason' => $reason,
|
||||
'updated_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class AttendanceEmailTemplate extends BaseModel
|
||||
{
|
||||
protected $table = 'email_templates';
|
||||
@@ -22,7 +20,7 @@ class AttendanceEmailTemplate extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'is_active' => 'boolean',
|
||||
'is_active' => 'boolean',
|
||||
'updated_by' => 'integer',
|
||||
];
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AttendanceRecord extends BaseModel
|
||||
@@ -28,14 +27,14 @@ class AttendanceRecord extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'class_section_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'total_absence' => 'integer',
|
||||
'total_late' => 'integer',
|
||||
'total_presence' => 'integer',
|
||||
'total_attendance' => 'integer',
|
||||
'modified_by' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'total_absence' => 'integer',
|
||||
'total_late' => 'integer',
|
||||
'total_presence' => 'integer',
|
||||
'total_attendance' => 'integer',
|
||||
'modified_by' => 'integer',
|
||||
];
|
||||
|
||||
/* =========================
|
||||
@@ -86,6 +85,7 @@ class AttendanceRecord extends BaseModel
|
||||
public static function updateAttendanceRecord(int $attendanceId, array $data): bool
|
||||
{
|
||||
$affected = static::query()->whereKey($attendanceId)->update($data);
|
||||
|
||||
return $affected >= 0;
|
||||
}
|
||||
|
||||
@@ -101,20 +101,26 @@ class AttendanceRecord extends BaseModel
|
||||
string $schoolYear,
|
||||
array $increments
|
||||
): bool {
|
||||
$allowed = ['total_absence','total_late','total_presence','total_attendance'];
|
||||
$allowed = ['total_absence', 'total_late', 'total_presence', 'total_attendance'];
|
||||
$inc = array_intersect_key($increments, array_flip($allowed));
|
||||
|
||||
if (empty($inc)) return true;
|
||||
if (empty($inc)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Build atomic update: field = field + X
|
||||
$update = [];
|
||||
foreach ($inc as $field => $value) {
|
||||
$value = (int) $value;
|
||||
if ($value === 0) continue;
|
||||
if ($value === 0) {
|
||||
continue;
|
||||
}
|
||||
$update[$field] = DB::raw("COALESCE($field,0) + {$value}");
|
||||
}
|
||||
|
||||
if (empty($update)) return true;
|
||||
if (empty($update)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$affected = static::query()
|
||||
->where('student_id', $studentId)
|
||||
@@ -139,4 +145,4 @@ class AttendanceRecord extends BaseModel
|
||||
->where('school_year', $schoolYear)
|
||||
->sum('total_absence');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
@@ -26,11 +25,11 @@ class AttendanceTracking extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'date' => 'datetime', // legacy dateFormat = datetime
|
||||
'is_reported' => 'integer',
|
||||
'is_notified' => 'integer',
|
||||
'notif_counter' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'date' => 'datetime', // legacy dateFormat = datetime
|
||||
'is_reported' => 'integer',
|
||||
'is_notified' => 'integer',
|
||||
'notif_counter' => 'integer',
|
||||
];
|
||||
|
||||
/* ----------------------- Helpers ----------------------- */
|
||||
@@ -42,7 +41,7 @@ class AttendanceTracking extends BaseModel
|
||||
return $date;
|
||||
}
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
|
||||
return $date . ' 00:00:00';
|
||||
return $date.' 00:00:00';
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -61,6 +60,7 @@ class AttendanceTracking extends BaseModel
|
||||
if ($schoolYear !== null && $schoolYear !== '') {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
return $q;
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ class AttendanceTracking extends BaseModel
|
||||
$y = (int) $d->format('Y');
|
||||
|
||||
$semester = ($m >= 8 && $m <= 12) ? 'Fall' : 'Spring';
|
||||
$startY = ($m >= 8) ? $y : $y - 1;
|
||||
$endY = $startY + 1;
|
||||
$startY = ($m >= 8) ? $y : $y - 1;
|
||||
$endY = $startY + 1;
|
||||
|
||||
return [$semester, sprintf('%d-%d', $startY, $endY)];
|
||||
}
|
||||
@@ -89,6 +89,7 @@ class AttendanceTracking extends BaseModel
|
||||
$day = substr($ymd, 0, 10);
|
||||
$start = Carbon::parse($day, 'UTC')->startOfDay();
|
||||
$endEx = Carbon::parse($day, 'UTC')->addDay()->startOfDay(); // exclusive
|
||||
|
||||
return [$start, $endEx];
|
||||
}
|
||||
|
||||
@@ -111,19 +112,19 @@ class AttendanceTracking extends BaseModel
|
||||
|
||||
if ($semester === null || $schoolYear === null) {
|
||||
[$sem, $yr] = static::deriveTermFromDate($dt);
|
||||
$semester = $semester ?? $sem;
|
||||
$semester = $semester ?? $sem;
|
||||
$schoolYear = $schoolYear ?? $yr;
|
||||
}
|
||||
|
||||
$row = static::create([
|
||||
'student_id' => $studentId,
|
||||
'date' => $dt,
|
||||
'is_reported' => $isExcused ? 1 : 0,
|
||||
'reason' => $reason,
|
||||
'is_notified' => 0,
|
||||
'notif_counter' => 0,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'student_id' => $studentId,
|
||||
'date' => $dt,
|
||||
'is_reported' => $isExcused ? 1 : 0,
|
||||
'reason' => $reason,
|
||||
'is_notified' => 0,
|
||||
'notif_counter' => 0,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
]);
|
||||
|
||||
return (int) $row->id;
|
||||
@@ -144,7 +145,7 @@ class AttendanceTracking extends BaseModel
|
||||
|
||||
if ($startDate) {
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $startDate)) {
|
||||
[$start, ] = static::dayRange($startDate);
|
||||
[$start] = static::dayRange($startDate);
|
||||
$q->where('date', '>=', $start);
|
||||
} else {
|
||||
$q->where('date', '>=', static::normalizeDateTime($startDate));
|
||||
@@ -201,7 +202,7 @@ class AttendanceTracking extends BaseModel
|
||||
?string $schoolYear = null
|
||||
): bool {
|
||||
$startDay = Carbon::now('UTC')->subDays($days)->toDateString();
|
||||
[$start, ] = static::dayRange($startDay);
|
||||
[$start] = static::dayRange($startDay);
|
||||
|
||||
$q = static::query()
|
||||
->where('student_id', $studentId)
|
||||
@@ -231,13 +232,17 @@ class AttendanceTracking extends BaseModel
|
||||
|
||||
$absences = $q->orderByDesc('date')->limit($threshold)->get()->toArray();
|
||||
|
||||
if (count($absences) < $threshold) return false;
|
||||
if (count($absences) < $threshold) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $threshold - 1; $i++) {
|
||||
$d1 = new \DateTime($absences[$i]['date']);
|
||||
$d2 = new \DateTime($absences[$i + 1]['date']);
|
||||
$diffDays = (int) $d2->diff($d1)->format('%a');
|
||||
if ($diffDays !== 7) return false;
|
||||
if ($diffDays !== 7) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -264,11 +269,13 @@ class AttendanceTracking extends BaseModel
|
||||
|
||||
$records = $q->orderByDesc('date')->limit($weeksStreak)->get()->toArray();
|
||||
|
||||
if (count($records) < $weeksStreak) return false;
|
||||
if (count($records) < $weeksStreak) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
foreach ($records as $r) {
|
||||
if ((int)($r['is_reported'] ?? 0) === 0 && (int)($r['is_notified'] ?? 0) === 0) {
|
||||
if ((int) ($r['is_reported'] ?? 0) === 0 && (int) ($r['is_notified'] ?? 0) === 0) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
@@ -297,9 +304,9 @@ class AttendanceTracking extends BaseModel
|
||||
$last = $q3->orderByDesc('date')->first();
|
||||
|
||||
return [
|
||||
'total_absences' => $total,
|
||||
'total_absences' => $total,
|
||||
'unexcused_absences' => $unexcused,
|
||||
'last_absence' => $last ? $last->toArray() : null,
|
||||
'last_absence' => $last ? $last->toArray() : null,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -313,7 +320,10 @@ class AttendanceTracking extends BaseModel
|
||||
) {
|
||||
$q = static::query();
|
||||
static::applyTermFilters($q, $semester, $schoolYear);
|
||||
if ($limit > 0) $q->limit($limit);
|
||||
if ($limit > 0) {
|
||||
$q->limit($limit);
|
||||
}
|
||||
|
||||
return $q->orderByDesc('date')->get();
|
||||
}
|
||||
|
||||
@@ -335,8 +345,8 @@ class AttendanceTracking extends BaseModel
|
||||
$students = (int) $q3->distinct('student_id')->count('student_id');
|
||||
|
||||
return [
|
||||
'total_absences' => $total,
|
||||
'unexcused_absences' => $unexcused,
|
||||
'total_absences' => $total,
|
||||
'unexcused_absences' => $unexcused,
|
||||
'students_with_absences' => $students,
|
||||
];
|
||||
}
|
||||
@@ -352,26 +362,28 @@ class AttendanceTracking extends BaseModel
|
||||
foreach ($studentsWithViolations as $student) {
|
||||
if (empty($student['absences'])) {
|
||||
$results['skipped']++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($student['absences'] as $absence) {
|
||||
$ymd = substr((string)($absence['date'] ?? now()->toDateString()), 0, 10);
|
||||
$ymd = substr((string) ($absence['date'] ?? now()->toDateString()), 0, 10);
|
||||
[$start, $endEx] = static::dayRange($ymd);
|
||||
|
||||
$data = [
|
||||
'student_id' => (int)($student['id'] ?? 0),
|
||||
'date' => static::normalizeDateTime($ymd),
|
||||
'is_reported' => 0,
|
||||
'reason' => (string)($student['violation'] ?? ''),
|
||||
'is_notified' => 0,
|
||||
'notif_counter' => 0,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'student_id' => (int) ($student['id'] ?? 0),
|
||||
'date' => static::normalizeDateTime($ymd),
|
||||
'is_reported' => 0,
|
||||
'reason' => (string) ($student['violation'] ?? ''),
|
||||
'is_notified' => 0,
|
||||
'notif_counter' => 0,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
];
|
||||
|
||||
if ($data['student_id'] <= 0) {
|
||||
$results['skipped']++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -391,8 +403,8 @@ class AttendanceTracking extends BaseModel
|
||||
$existing->fill($data)->save();
|
||||
$results['updated']++;
|
||||
|
||||
if (!empty($existing->is_notified)) {
|
||||
static::resetNotification((int)$existing->id);
|
||||
if (! empty($existing->is_notified)) {
|
||||
static::resetNotification((int) $existing->id);
|
||||
$results['notified']++;
|
||||
}
|
||||
} else {
|
||||
@@ -404,7 +416,7 @@ class AttendanceTracking extends BaseModel
|
||||
|
||||
// Only match standalone "4"
|
||||
if (preg_match('/\b4\b/', $data['reason'])) {
|
||||
static::markAsNotified((int)$new->id);
|
||||
static::markAsNotified((int) $new->id);
|
||||
$results['notified']++;
|
||||
}
|
||||
}
|
||||
@@ -427,8 +439,8 @@ class AttendanceTracking extends BaseModel
|
||||
->whereKey($id)
|
||||
->update([
|
||||
'notif_counter' => DB::raw('COALESCE(notif_counter,0)+1'),
|
||||
'is_notified' => 1,
|
||||
'updated_at' => now(),
|
||||
'is_notified' => 1,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return $affected > 0;
|
||||
@@ -439,9 +451,9 @@ class AttendanceTracking extends BaseModel
|
||||
$affected = static::query()
|
||||
->whereKey($id)
|
||||
->update([
|
||||
'is_notified' => 0,
|
||||
'is_notified' => 0,
|
||||
'notif_counter' => 0,
|
||||
'updated_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return $affected >= 0;
|
||||
@@ -463,7 +475,7 @@ class AttendanceTracking extends BaseModel
|
||||
// Here we require term to be passed or derived from date.
|
||||
if ($semester === null || $schoolYear === null) {
|
||||
[$sem, $yr] = static::deriveTermFromDate($ymd);
|
||||
$semester = $semester ?? $sem;
|
||||
$semester = $semester ?? $sem;
|
||||
$schoolYear = $schoolYear ?? $yr;
|
||||
}
|
||||
|
||||
@@ -475,33 +487,33 @@ class AttendanceTracking extends BaseModel
|
||||
->where('semester', $semester)
|
||||
->where('school_year', $schoolYear)
|
||||
->where('date', '>=', $start)
|
||||
->where('date', '<', $endEx)
|
||||
->where('date', '<', $endEx)
|
||||
->where('reason', 'like', "%{$code}%")
|
||||
->orderByDesc('date')
|
||||
->first();
|
||||
|
||||
// 2) Fallback: match by day only
|
||||
if (!$row) {
|
||||
if (! $row) {
|
||||
$row = static::query()
|
||||
->where('student_id', $studentId)
|
||||
->where('semester', $semester)
|
||||
->where('school_year', $schoolYear)
|
||||
->where('date', '>=', $start)
|
||||
->where('date', '<', $endEx)
|
||||
->where('date', '<', $endEx)
|
||||
->orderByDesc('date')
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($row) {
|
||||
$counter = ((int)($row->notif_counter ?? 0)) + 1;
|
||||
$counter = ((int) ($row->notif_counter ?? 0)) + 1;
|
||||
|
||||
$affected = static::query()
|
||||
->whereKey((int)$row->id)
|
||||
->whereKey((int) $row->id)
|
||||
->update([
|
||||
'is_notified' => 1,
|
||||
'is_notified' => 1,
|
||||
'notif_counter' => $counter,
|
||||
'is_reported' => 0,
|
||||
'updated_at' => now(),
|
||||
'is_reported' => 0,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return $affected > 0;
|
||||
@@ -509,18 +521,18 @@ class AttendanceTracking extends BaseModel
|
||||
|
||||
// Insert a row so future runs see it as notified
|
||||
$created = static::create([
|
||||
'student_id' => $studentId,
|
||||
'date' => static::normalizeDateTime($ymd),
|
||||
'is_reported' => 0,
|
||||
'reason' => $code,
|
||||
'is_notified' => 1,
|
||||
'notif_counter' => 1,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'note' => null,
|
||||
'student_id' => $studentId,
|
||||
'date' => static::normalizeDateTime($ymd),
|
||||
'is_reported' => 0,
|
||||
'reason' => $code,
|
||||
'is_notified' => 1,
|
||||
'notif_counter' => 1,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'note' => null,
|
||||
]);
|
||||
|
||||
return !empty($created->id);
|
||||
return ! empty($created->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -538,11 +550,11 @@ class AttendanceTracking extends BaseModel
|
||||
->where('student_id', $studentId)
|
||||
->where('school_year', $schoolYear);
|
||||
|
||||
if (!empty($semester)) {
|
||||
if (! empty($semester)) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
|
||||
if (!empty($lastDate)) {
|
||||
if (! empty($lastDate)) {
|
||||
$q->where('date', '<=', static::normalizeDateTime($lastDate));
|
||||
}
|
||||
|
||||
@@ -550,18 +562,20 @@ class AttendanceTracking extends BaseModel
|
||||
->orderByDesc('date')
|
||||
->first();
|
||||
|
||||
if (!$row) return 0;
|
||||
if (! $row) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$counter = ((int)($row->notif_counter ?? 0)) + 1;
|
||||
$counter = ((int) ($row->notif_counter ?? 0)) + 1;
|
||||
|
||||
$affected = static::query()
|
||||
->whereKey((int)$row->id)
|
||||
->whereKey((int) $row->id)
|
||||
->update([
|
||||
'is_notified' => 1,
|
||||
'is_notified' => 1,
|
||||
'notif_counter' => $counter,
|
||||
'updated_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
return $affected > 0 ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class AuthorizedUser extends BaseModel
|
||||
{
|
||||
protected $table = 'authorized_users';
|
||||
@@ -27,7 +25,7 @@ class AuthorizedUser extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'user_id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'authorized_user_id' => 'integer',
|
||||
];
|
||||
|
||||
@@ -44,4 +42,4 @@ class AuthorizedUser extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'authorized_user_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -25,21 +24,19 @@ class BadgePrintLog extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'user_id' => 'integer',
|
||||
'printed_by' => 'integer',
|
||||
'printed_at' => 'datetime',
|
||||
'copies' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'printed_by' => 'integer',
|
||||
'printed_at' => 'datetime',
|
||||
'copies' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
* Insert a batch of print logs. Swallows errors if table is missing.
|
||||
*
|
||||
* @param int[] $userIds
|
||||
* @param int|null $printedBy
|
||||
* @param string|null $schoolYear
|
||||
* @param array $roleMap userId => role label
|
||||
* @param array $classMap userId => class name
|
||||
* @param int $copies copies per user (defaults to 1)
|
||||
* @param int[] $userIds
|
||||
* @param array $roleMap userId => role label
|
||||
* @param array $classMap userId => class name
|
||||
* @param int $copies copies per user (defaults to 1)
|
||||
* @return int rows inserted (best-effort)
|
||||
*/
|
||||
public static function logPrints(
|
||||
@@ -55,31 +52,38 @@ class BadgePrintLog extends BaseModel
|
||||
|
||||
foreach ($userIds as $uid) {
|
||||
$uid = (int) $uid;
|
||||
if ($uid <= 0) continue;
|
||||
if ($uid <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rows[] = [
|
||||
'user_id' => $uid,
|
||||
'printed_by' => $printedBy,
|
||||
'school_year' => $schoolYear,
|
||||
'printed_at' => $now,
|
||||
'role' => (string)($roleMap[$uid] ?? ''),
|
||||
'class_section_name' => (string)($classMap[$uid] ?? ''),
|
||||
'copies' => max(1, (int) $copies),
|
||||
'user_id' => $uid,
|
||||
'printed_by' => $printedBy,
|
||||
'school_year' => $schoolYear,
|
||||
'printed_at' => $now,
|
||||
'role' => (string) ($roleMap[$uid] ?? ''),
|
||||
'class_section_name' => (string) ($classMap[$uid] ?? ''),
|
||||
'copies' => max(1, (int) $copies),
|
||||
];
|
||||
}
|
||||
|
||||
if (empty($rows)) return 0;
|
||||
if (empty($rows)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
// insert returns bool; we return count best-effort like legacy
|
||||
DB::table((new static)->getTable())->insert($rows);
|
||||
|
||||
return count($rows);
|
||||
} catch (QueryException $e) {
|
||||
// Avoid breaking badge/PDF generation if the table is missing or other DB error
|
||||
Log::error('BadgePrintLog::logPrints failed: ' . $e->getMessage());
|
||||
Log::error('BadgePrintLog::logPrints failed: '.$e->getMessage());
|
||||
|
||||
return 0;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('BadgePrintLog::logPrints failed: ' . $e->getMessage());
|
||||
Log::error('BadgePrintLog::logPrints failed: '.$e->getMessage());
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -87,31 +91,35 @@ class BadgePrintLog extends BaseModel
|
||||
/**
|
||||
* Return counts and last printed info for given user IDs.
|
||||
*
|
||||
* @param int[] $userIds
|
||||
* @param string|null $schoolYear Optional filter by school year
|
||||
* @param int[] $userIds
|
||||
* @param string|null $schoolYear Optional filter by school year
|
||||
* @return array userId => [count, last_printed_at, last_printed_by]
|
||||
*/
|
||||
public static function getStatus(array $userIds, ?string $schoolYear = null): array
|
||||
{
|
||||
$userIds = array_values(array_unique(array_map('intval', array_filter($userIds))));
|
||||
if (empty($userIds)) return [];
|
||||
if (empty($userIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
$q = DB::table((new static)->getTable() . ' as l')
|
||||
$q = DB::table((new static)->getTable().' as l')
|
||||
->selectRaw('l.user_id, COUNT(*) AS prints, MAX(l.printed_at) AS last_printed_at, MAX(l.printed_by) AS last_printed_by')
|
||||
->whereIn('l.user_id', $userIds)
|
||||
->groupBy('l.user_id');
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('l.school_year', $schoolYear);
|
||||
}
|
||||
|
||||
$rows = $q->get();
|
||||
} catch (QueryException $e) {
|
||||
Log::error('BadgePrintLog::getStatus failed: ' . $e->getMessage());
|
||||
Log::error('BadgePrintLog::getStatus failed: '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('BadgePrintLog::getStatus failed: ' . $e->getMessage());
|
||||
Log::error('BadgePrintLog::getStatus failed: '.$e->getMessage());
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
@@ -119,7 +127,7 @@ class BadgePrintLog extends BaseModel
|
||||
foreach ($rows as $r) {
|
||||
$uid = (int) ($r->user_id ?? 0);
|
||||
$out[$uid] = [
|
||||
'count' => (int) ($r->prints ?? 0),
|
||||
'count' => (int) ($r->prints ?? 0),
|
||||
'last_printed_at' => (string) ($r->last_printed_at ?? ''),
|
||||
'last_printed_by' => isset($r->last_printed_by) ? (int) $r->last_printed_by : null,
|
||||
];
|
||||
@@ -138,4 +146,4 @@ class BadgePrintLog extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'printed_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Foundation\Application;
|
||||
|
||||
class BaseModel extends Model
|
||||
{
|
||||
@@ -12,8 +13,9 @@ class BaseModel extends Model
|
||||
{
|
||||
if ($this->isTestingEnv()) {
|
||||
$columns = $this->tableColumns();
|
||||
if (!empty($columns)) {
|
||||
if (! empty($columns)) {
|
||||
$key = $this->getKeyName();
|
||||
|
||||
return array_values(array_filter($columns, static function ($col) use ($key) {
|
||||
return $col !== $key;
|
||||
}));
|
||||
@@ -22,10 +24,10 @@ class BaseModel extends Model
|
||||
|
||||
$fillable = parent::getFillable();
|
||||
if ($this->timestamps) {
|
||||
if (!in_array('created_at', $fillable, true)) {
|
||||
if (! in_array('created_at', $fillable, true)) {
|
||||
$fillable[] = 'created_at';
|
||||
}
|
||||
if (!in_array('updated_at', $fillable, true)) {
|
||||
if (! in_array('updated_at', $fillable, true)) {
|
||||
$fillable[] = 'updated_at';
|
||||
}
|
||||
}
|
||||
@@ -49,7 +51,7 @@ class BaseModel extends Model
|
||||
if (function_exists('app')) {
|
||||
try {
|
||||
$app = app();
|
||||
if ($app instanceof \Illuminate\Foundation\Application && $app->runningUnitTests()) {
|
||||
if ($app instanceof Application && $app->runningUnitTests()) {
|
||||
return true;
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
@@ -82,7 +84,7 @@ class BaseModel extends Model
|
||||
}
|
||||
|
||||
if ($pattern === null) {
|
||||
$pattern = __DIR__ . '/../../database/migrations/*.php';
|
||||
$pattern = __DIR__.'/../../database/migrations/*.php';
|
||||
}
|
||||
|
||||
$files = glob($pattern) ?: [];
|
||||
@@ -98,7 +100,7 @@ class BaseModel extends Model
|
||||
}
|
||||
|
||||
foreach ($this->parseSchemaCreateTables($contents) as $table => $columns) {
|
||||
if (!isset($map[$table]) || empty($map[$table])) {
|
||||
if (! isset($map[$table]) || empty($map[$table])) {
|
||||
$map[$table] = $columns;
|
||||
}
|
||||
}
|
||||
@@ -116,7 +118,7 @@ class BaseModel extends Model
|
||||
$colsBlock = $match[2];
|
||||
preg_match_all('/`([^`]+)`\\s+[^,]+/m', $colsBlock, $colsMatch);
|
||||
$columns = $colsMatch[1] ?? [];
|
||||
if (!empty($columns)) {
|
||||
if (! empty($columns)) {
|
||||
$map[$table] = $columns;
|
||||
}
|
||||
}
|
||||
@@ -128,7 +130,7 @@ class BaseModel extends Model
|
||||
private function parseSchemaCreateTables(string $contents): array
|
||||
{
|
||||
$map = [];
|
||||
if (!preg_match_all('/Schema::create\\(\\s*[\'"]([^\'"]+)[\'"]\\s*,\\s*function\\s*\\([^)]*\\)\\s*\\{(.*?)\\n\\s*\\}\\);/is', $contents, $matches, PREG_SET_ORDER)) {
|
||||
if (! preg_match_all('/Schema::create\\(\\s*[\'"]([^\'"]+)[\'"]\\s*,\\s*function\\s*\\([^)]*\\)\\s*\\{(.*?)\\n\\s*\\}\\);/is', $contents, $matches, PREG_SET_ORDER)) {
|
||||
return $map;
|
||||
}
|
||||
|
||||
@@ -150,7 +152,7 @@ class BaseModel extends Model
|
||||
$columns[] = 'deleted_at';
|
||||
}
|
||||
|
||||
if (!empty($columns)) {
|
||||
if (! empty($columns)) {
|
||||
$map[$table] = $columns;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,4 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
class Calendar extends CalendarEvent
|
||||
{
|
||||
}
|
||||
class Calendar extends CalendarEvent {}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
@@ -31,12 +30,12 @@ class CalendarEvent extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
// If your column is DATE use 'date', if it's DATETIME use 'datetime'
|
||||
'date' => 'date',
|
||||
'notify_parent' => 'boolean',
|
||||
'notify_admin' => 'boolean',
|
||||
'date' => 'date',
|
||||
'notify_parent' => 'boolean',
|
||||
'notify_admin' => 'boolean',
|
||||
'notify_teacher' => 'boolean',
|
||||
'no_school' => 'integer',
|
||||
'event_type' => 'string',
|
||||
'no_school' => 'integer',
|
||||
'event_type' => 'string',
|
||||
];
|
||||
|
||||
private static ?bool $hasEventTypeColumn = null;
|
||||
@@ -48,18 +47,21 @@ class CalendarEvent extends BaseModel
|
||||
public static function getEvents()
|
||||
{
|
||||
$events = static::query()->get()->toArray();
|
||||
|
||||
return static::withNoSchoolFlag($events);
|
||||
}
|
||||
|
||||
public static function getEventByDate(string $date): array
|
||||
{
|
||||
$events = static::query()->where('date', $date)->get()->toArray();
|
||||
|
||||
return static::withNoSchoolFlag($events);
|
||||
}
|
||||
|
||||
public static function addEvent(array $data): int
|
||||
{
|
||||
$row = static::create($data);
|
||||
|
||||
return (int) $row->id;
|
||||
}
|
||||
|
||||
@@ -92,6 +94,7 @@ class CalendarEvent extends BaseModel
|
||||
if (static::$hasEventTypeColumn === null) {
|
||||
static::$hasEventTypeColumn = static::columnExists((new static)->getTable(), 'event_type');
|
||||
}
|
||||
|
||||
return (bool) static::$hasEventTypeColumn;
|
||||
}
|
||||
|
||||
@@ -123,9 +126,9 @@ class CalendarEvent extends BaseModel
|
||||
*/
|
||||
protected static function isNoSchoolEvent(array $event): bool
|
||||
{
|
||||
$title = strtolower((string)($event['title'] ?? ''));
|
||||
$desc = strtolower((string)($event['description'] ?? ''));
|
||||
$text = $title . ' ' . $desc;
|
||||
$title = strtolower((string) ($event['title'] ?? ''));
|
||||
$desc = strtolower((string) ($event['description'] ?? ''));
|
||||
$text = $title.' '.$desc;
|
||||
|
||||
$keywords = ['no school', 'no-school', 'cancel', 'vacation', 'holiday', 'break'];
|
||||
|
||||
|
||||
@@ -2,6 +2,4 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
class ClassModel extends SchoolClass
|
||||
{
|
||||
}
|
||||
class ClassModel extends SchoolClass {}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class ClassPrepAdjustment extends BaseModel
|
||||
{
|
||||
protected $table = 'class_prep_adjustments';
|
||||
@@ -21,7 +19,7 @@ class ClassPrepAdjustment extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'class_section_id' => 'integer',
|
||||
'adjustment' => 'integer', // change to 'decimal:2' if it's not an int
|
||||
'adjustment' => 'integer', // change to 'decimal:2' if it's not an int
|
||||
];
|
||||
|
||||
// Optional relationship
|
||||
@@ -29,4 +27,4 @@ class ClassPrepAdjustment extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(ClassSection::class, 'class_section_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class ClassPreparationLog extends BaseModel
|
||||
{
|
||||
protected $table = 'class_preparation_log';
|
||||
@@ -22,7 +20,7 @@ class ClassPreparationLog extends BaseModel
|
||||
protected $casts = [
|
||||
'class_section_id' => 'integer',
|
||||
// If prep_data is JSON in DB, use 'array' (or 'json') cast:
|
||||
'prep_data' => 'array',
|
||||
'prep_data' => 'array',
|
||||
];
|
||||
|
||||
// Optional relationship
|
||||
@@ -30,4 +28,4 @@ class ClassPreparationLog extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(ClassSection::class, 'class_section_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class ClassProgressAttachment extends BaseModel
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'class_progress_attachments';
|
||||
|
||||
// legacy: useTimestamps = false
|
||||
@@ -23,8 +23,8 @@ class ClassProgressAttachment extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'report_id' => 'integer',
|
||||
'file_size' => 'integer',
|
||||
'report_id' => 'integer',
|
||||
'file_size' => 'integer',
|
||||
];
|
||||
|
||||
// Optional relationship
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
class ClassProgressReport extends BaseModel
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $table = 'class_progress_reports';
|
||||
|
||||
// ✅ legacy: useTimestamps = true (created_at/updated_at)
|
||||
@@ -36,14 +36,14 @@ class ClassProgressReport extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'class_section_id' => 'integer',
|
||||
'teacher_id' => 'integer',
|
||||
'teacher_id' => 'integer',
|
||||
|
||||
// change to 'datetime' if your columns are DATETIME
|
||||
'week_start' => 'date',
|
||||
'week_end' => 'date',
|
||||
'week_start' => 'date',
|
||||
'week_end' => 'date',
|
||||
|
||||
// If flags_json is JSON in DB, this makes it an array automatically
|
||||
'flags_json' => 'array',
|
||||
'flags_json' => 'array',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ClassSection extends BaseModel
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
// legacy table name is "classSection"
|
||||
protected $table = 'classSection';
|
||||
|
||||
@@ -24,7 +24,7 @@ class ClassSection extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'class_id' => 'integer',
|
||||
'class_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
];
|
||||
|
||||
|
||||
@@ -2,6 +2,4 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
class Communication extends CommunicationLog
|
||||
{
|
||||
}
|
||||
class Communication extends CommunicationLog {}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class CommunicationLog extends BaseModel
|
||||
{
|
||||
protected $table = 'communication_logs';
|
||||
@@ -34,16 +32,16 @@ class CommunicationLog extends BaseModel
|
||||
}
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'family_id' => 'integer',
|
||||
'sent_by' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'family_id' => 'integer',
|
||||
'sent_by' => 'integer',
|
||||
|
||||
// If these columns are JSON in DB, this will auto convert to arrays
|
||||
'recipients' => 'array',
|
||||
'cc' => 'array',
|
||||
'bcc' => 'array',
|
||||
'attachments' => 'array',
|
||||
'metadata' => 'array',
|
||||
'recipients' => 'array',
|
||||
'cc' => 'array',
|
||||
'bcc' => 'array',
|
||||
'attachments' => 'array',
|
||||
'metadata' => 'array',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
|
||||
+11
-12
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Competition extends BaseModel
|
||||
@@ -34,20 +33,20 @@ class Competition extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'class_section_id' => 'integer',
|
||||
'winners_count' => 'integer',
|
||||
'prize_per_point' => 'decimal:2', // adjust precision if needed
|
||||
'winners_count' => 'integer',
|
||||
'prize_per_point' => 'decimal:2', // adjust precision if needed
|
||||
|
||||
'is_published' => 'boolean',
|
||||
'is_locked' => 'boolean',
|
||||
'is_published' => 'boolean',
|
||||
'is_locked' => 'boolean',
|
||||
|
||||
// change to 'date' if your columns are DATE (not DATETIME)
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
'published_at' => 'datetime',
|
||||
'locked_at' => 'datetime',
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
'published_at' => 'datetime',
|
||||
'locked_at' => 'datetime',
|
||||
|
||||
'locked_by' => 'integer',
|
||||
'created_by' => 'integer',
|
||||
'locked_by' => 'integer',
|
||||
'created_by' => 'integer',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -70,4 +69,4 @@ class Competition extends BaseModel
|
||||
{
|
||||
return $this->hasMany(CompetitionClassWinner::class, 'competition_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class CompetitionClassWinner extends BaseModel
|
||||
{
|
||||
protected $table = 'competition_class_winners';
|
||||
@@ -25,10 +23,10 @@ class CompetitionClassWinner extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'competition_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'question_count' => 'integer',
|
||||
'winners_override' => 'integer',
|
||||
'competition_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'question_count' => 'integer',
|
||||
'winners_override' => 'integer',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -41,4 +39,4 @@ class CompetitionClassWinner extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(ClassSection::class, 'class_section_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class CompetitionScore extends BaseModel
|
||||
{
|
||||
protected $table = 'competition_scores';
|
||||
@@ -20,10 +18,10 @@ class CompetitionScore extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'competition_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'competition_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'score' => 'integer', // change to 'decimal:2' if score is not int
|
||||
'score' => 'integer', // change to 'decimal:2' if score is not int
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -41,4 +39,4 @@ class CompetitionScore extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(ClassSection::class, 'class_section_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class CompetitionWinner extends BaseModel
|
||||
{
|
||||
protected $table = 'competition_winners';
|
||||
@@ -22,13 +20,13 @@ class CompetitionWinner extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'competition_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'competition_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'rank' => 'integer',
|
||||
'score' => 'integer', // change to 'decimal:2' if needed
|
||||
'prize_amount' => 'decimal:2', // adjust precision if needed
|
||||
'created_at' => 'datetime',
|
||||
'rank' => 'integer',
|
||||
'score' => 'integer', // change to 'decimal:2' if needed
|
||||
'prize_amount' => 'decimal:2', // adjust precision if needed
|
||||
'created_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -46,4 +44,4 @@ class CompetitionWinner extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(ClassSection::class, 'class_section_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Services\SemesterRangeService;
|
||||
|
||||
class Configuration extends BaseModel
|
||||
{
|
||||
@@ -58,11 +57,11 @@ class Configuration extends BaseModel
|
||||
}
|
||||
|
||||
$row = static::query()->create([
|
||||
'config_key' => $key,
|
||||
'config_key' => $key,
|
||||
'config_value' => $value,
|
||||
]);
|
||||
|
||||
return !empty($row->id);
|
||||
return ! empty($row->id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,6 +86,7 @@ class Configuration extends BaseModel
|
||||
public static function addConfig(array $data): int
|
||||
{
|
||||
$row = static::query()->create($data);
|
||||
|
||||
return (int) $row->id;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ class Configuration extends BaseModel
|
||||
try {
|
||||
// If you have this service in Laravel, inject/resolve it from container.
|
||||
// This call assumes the service constructor can accept Configuration model (like legacy did).
|
||||
$semester = app(\App\Services\SemesterRangeService::class)->getSemesterForDate();
|
||||
$semester = app(SemesterRangeService::class)->getSemesterForDate();
|
||||
if (is_string($semester) && $semester !== '') {
|
||||
return $semester;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class ContactUs extends BaseModel
|
||||
{
|
||||
protected $table = 'contactus';
|
||||
@@ -23,7 +21,7 @@ class ContactUs extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'sender_id' => 'integer',
|
||||
'sender_id' => 'integer',
|
||||
'reciever_id' => 'integer',
|
||||
];
|
||||
|
||||
@@ -79,4 +77,4 @@ class ContactUs extends BaseModel
|
||||
{
|
||||
return static::query()->whereKey($id)->update($data) >= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class CurrentFlag extends BaseModel
|
||||
{
|
||||
protected $table = 'current_flag';
|
||||
@@ -33,11 +31,11 @@ class CurrentFlag extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'updated_by_open' => 'integer',
|
||||
'updated_by_closed' => 'integer',
|
||||
'updated_by_canceled'=> 'integer',
|
||||
'flag_datetime' => 'datetime',
|
||||
'student_id' => 'integer',
|
||||
'updated_by_open' => 'integer',
|
||||
'updated_by_closed' => 'integer',
|
||||
'updated_by_canceled' => 'integer',
|
||||
'flag_datetime' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -60,4 +58,4 @@ class CurrentFlag extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'updated_by_canceled');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class CurrentIncident extends BaseModel
|
||||
{
|
||||
protected $table = 'current_incident';
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
protected $fillable = [
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DiscountUsage extends BaseModel
|
||||
@@ -24,12 +23,12 @@ class DiscountUsage extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'voucher_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'discount_amount' => 'decimal:2', // adjust precision if needed
|
||||
'updated_by' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'used_at' => 'datetime',
|
||||
'voucher_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'discount_amount' => 'decimal:2', // adjust precision if needed
|
||||
'updated_by' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'used_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -56,4 +55,4 @@ class DiscountUsage extends BaseModel
|
||||
|
||||
return (float) $total;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DiscountVoucher extends BaseModel
|
||||
{
|
||||
@@ -31,11 +29,11 @@ class DiscountVoucher extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'discount_value' => 'decimal:2',
|
||||
'max_uses' => 'integer',
|
||||
'times_used' => 'integer',
|
||||
'is_active' => 'boolean',
|
||||
'valid_from' => 'date',
|
||||
'valid_until' => 'date',
|
||||
'max_uses' => 'integer',
|
||||
'times_used' => 'integer',
|
||||
'is_active' => 'boolean',
|
||||
'valid_from' => 'date',
|
||||
'valid_until' => 'date',
|
||||
];
|
||||
|
||||
/* =========================
|
||||
@@ -90,8 +88,8 @@ class DiscountVoucher extends BaseModel
|
||||
|
||||
private function validateDatesOrder(): void
|
||||
{
|
||||
if (!empty($this->valid_from) && !empty($this->valid_until)) {
|
||||
$from = Carbon::parse($this->valid_from)->toDateString();
|
||||
if (! empty($this->valid_from) && ! empty($this->valid_until)) {
|
||||
$from = Carbon::parse($this->valid_from)->toDateString();
|
||||
$until = Carbon::parse($this->valid_until)->toDateString();
|
||||
if ($from > $until) {
|
||||
// In Laravel, prefer validating in FormRequest.
|
||||
@@ -123,24 +121,24 @@ class DiscountVoucher extends BaseModel
|
||||
// Left join usages for this student only
|
||||
->leftJoin('discount_usages as u', function ($join) use ($studentId) {
|
||||
$join->on('u.voucher_id', '=', 'v.id')
|
||||
->where('u.student_id', '=', (int) $studentId);
|
||||
->where('u.student_id', '=', (int) $studentId);
|
||||
})
|
||||
->where('v.code', $code)
|
||||
->where('v.is_active', 1)
|
||||
// valid_from is null or <= today
|
||||
->where(function ($w) use ($today) {
|
||||
$w->whereNull('v.valid_from')
|
||||
->orWhere('v.valid_from', '<=', $today);
|
||||
->orWhere('v.valid_from', '<=', $today);
|
||||
})
|
||||
// valid_until is null or >= today
|
||||
->where(function ($w) use ($today) {
|
||||
$w->whereNull('v.valid_until')
|
||||
->orWhere('v.valid_until', '>=', $today);
|
||||
->orWhere('v.valid_until', '>=', $today);
|
||||
})
|
||||
// max_uses is null or times_used < max_uses
|
||||
->where(function ($w) {
|
||||
$w->whereNull('v.max_uses')
|
||||
->orWhereColumn('v.times_used', '<', 'v.max_uses');
|
||||
->orWhereColumn('v.times_used', '<', 'v.max_uses');
|
||||
})
|
||||
// Not previously used by this student (no usage row)
|
||||
->whereNull('u.id')
|
||||
@@ -148,4 +146,4 @@ class DiscountVoucher extends BaseModel
|
||||
|
||||
return $q->first();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class EarlyDismissalSignature extends BaseModel
|
||||
{
|
||||
protected $table = 'early_dismissal_signatures';
|
||||
@@ -26,7 +24,7 @@ class EarlyDismissalSignature extends BaseModel
|
||||
// report_date is stored as Y-m-d in legacy validation; keep as date
|
||||
'report_date' => 'date',
|
||||
|
||||
'file_size' => 'integer',
|
||||
'file_size' => 'integer',
|
||||
'uploaded_by' => 'integer',
|
||||
];
|
||||
|
||||
@@ -35,4 +33,4 @@ class EarlyDismissalSignature extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'uploaded_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class EmailTemplate extends BaseModel
|
||||
{
|
||||
protected $table = 'email_templates';
|
||||
@@ -31,9 +29,9 @@ class EmailTemplate extends BaseModel
|
||||
->where('is_active', 1)
|
||||
->where(function ($q) use ($variant) {
|
||||
$q->where('variant', $variant)
|
||||
->orWhere('variant', 'default');
|
||||
->orWhere('variant', 'default');
|
||||
})
|
||||
->orderByRaw("CASE WHEN variant = ? THEN 0 ELSE 1 END", [$variant])
|
||||
->orderByRaw('CASE WHEN variant = ? THEN 0 ELSE 1 END', [$variant])
|
||||
->first();
|
||||
|
||||
return $row;
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class EmergencyContact extends BaseModel
|
||||
{
|
||||
protected $table = 'emergency_contacts';
|
||||
@@ -24,8 +22,8 @@ class EmergencyContact extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'parent_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'authorized_user_id' => 'integer',
|
||||
];
|
||||
|
||||
@@ -72,7 +70,7 @@ class EmergencyContact extends BaseModel
|
||||
return static::query()
|
||||
->where(function ($q) use ($studentId) {
|
||||
$q->where('student_id', $studentId)
|
||||
->orWhere('parent_id', $studentId);
|
||||
->orWhere('parent_id', $studentId);
|
||||
})
|
||||
->get();
|
||||
}
|
||||
|
||||
+10
-11
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Enrollment extends BaseModel
|
||||
@@ -28,14 +27,14 @@ class Enrollment extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'is_withdrawn' => 'boolean',
|
||||
'parent_id' => 'integer',
|
||||
'is_withdrawn' => 'boolean',
|
||||
|
||||
// change to 'datetime' if your columns are DATETIME
|
||||
'enrollment_date' => 'date',
|
||||
'withdrawal_date' => 'date',
|
||||
'enrollment_date' => 'date',
|
||||
'withdrawal_date' => 'date',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -69,11 +68,11 @@ class Enrollment extends BaseModel
|
||||
->select('students.*')
|
||||
->where('enrollments.parent_id', $parentId);
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('enrollments.school_year', $schoolYear);
|
||||
}
|
||||
|
||||
if (!empty($semester)) {
|
||||
if (! empty($semester)) {
|
||||
$q->where('enrollments.semester', $semester);
|
||||
}
|
||||
|
||||
@@ -92,10 +91,10 @@ class Enrollment extends BaseModel
|
||||
->where('enrollments.parent_id', $parentId)
|
||||
->where(function ($w) {
|
||||
$w->where('enrollments.enrollment_status', 'enrolled')
|
||||
->orWhere('enrollments.enrollment_status', 'payment pending');
|
||||
->orWhere('enrollments.enrollment_status', 'payment pending');
|
||||
});
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('enrollments.school_year', $schoolYear);
|
||||
}
|
||||
|
||||
@@ -118,4 +117,4 @@ class Enrollment extends BaseModel
|
||||
|
||||
return $row?->enrollment_status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-15
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class Event extends BaseModel
|
||||
{
|
||||
protected $table = 'events';
|
||||
@@ -26,9 +24,9 @@ class Event extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'expiration_date' => 'date', // change to 'datetime' if stored as DATETIME
|
||||
'created_by' => 'integer',
|
||||
'created_by' => 'integer',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -54,7 +52,7 @@ class Event extends BaseModel
|
||||
$q = static::query()
|
||||
->whereDate('expiration_date', '>=', now()->toDateString());
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
@@ -67,9 +65,9 @@ class Event extends BaseModel
|
||||
public static function getEventsByName(string $name, ?string $schoolYear = null)
|
||||
{
|
||||
$q = static::query()
|
||||
->where('event_name', 'like', '%' . $name . '%');
|
||||
->where('event_name', 'like', '%'.$name.'%');
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
@@ -83,7 +81,7 @@ class Event extends BaseModel
|
||||
{
|
||||
$q = static::query();
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
@@ -96,6 +94,7 @@ class Event extends BaseModel
|
||||
public static function addEvent(array $data): int
|
||||
{
|
||||
$row = static::create($data);
|
||||
|
||||
return (int) $row->id;
|
||||
}
|
||||
|
||||
@@ -106,7 +105,7 @@ class Event extends BaseModel
|
||||
{
|
||||
$q = static::query()->whereDate('expiration_date', $date);
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
@@ -121,11 +120,11 @@ class Event extends BaseModel
|
||||
$q = static::query()
|
||||
->whereDate('expiration_date', '>=', now()->toDateString());
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
if (!empty($semester)) {
|
||||
if (! empty($semester)) {
|
||||
$q->where('semester', $semester);
|
||||
}
|
||||
|
||||
@@ -139,7 +138,7 @@ class Event extends BaseModel
|
||||
{
|
||||
$q = static::query()->whereKey($id);
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
@@ -153,7 +152,7 @@ class Event extends BaseModel
|
||||
{
|
||||
$q = static::query()->whereKey($id);
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
@@ -167,10 +166,10 @@ class Event extends BaseModel
|
||||
{
|
||||
$q = static::query()->whereKey($id);
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
return (bool) $q->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,4 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
class EventCharge extends EventCharges
|
||||
{
|
||||
}
|
||||
class EventCharge extends EventCharges {}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class EventCharges extends BaseModel
|
||||
@@ -41,12 +40,12 @@ class EventCharges extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'event_id' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'participation' => 'boolean', // change if stored as string/enum
|
||||
'charged' => 'boolean', // change if stored as string/enum
|
||||
'updated_by' => 'integer',
|
||||
'event_id' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'participation' => 'boolean', // change if stored as string/enum
|
||||
'charged' => 'boolean', // change if stored as string/enum
|
||||
'updated_by' => 'integer',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -75,15 +74,15 @@ class EventCharges extends BaseModel
|
||||
->leftJoin('events', 'events.id', '=', 'event_charges.event_id')
|
||||
->select('event_charges.*', 'events.event_name', 'events.amount');
|
||||
|
||||
if (!empty($parentId)) {
|
||||
if (! empty($parentId)) {
|
||||
$q->where('event_charges.parent_id', $parentId);
|
||||
}
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('event_charges.school_year', $schoolYear);
|
||||
}
|
||||
|
||||
if (!empty($semester)) {
|
||||
if (! empty($semester)) {
|
||||
$q->where('event_charges.semester', $semester);
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class Exam extends BaseModel
|
||||
{
|
||||
protected $table = 'exams';
|
||||
@@ -16,6 +14,7 @@ class Exam extends BaseModel
|
||||
* We'll keep auto created_at, no updated_at:
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
const UPDATED_AT = null; // ✅ no updated_at column
|
||||
|
||||
protected $fillable = [
|
||||
@@ -27,8 +26,8 @@ class Exam extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
];
|
||||
|
||||
@@ -42,4 +41,4 @@ class Exam extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(ClassSection::class, 'class_section_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class ExamDraft extends BaseModel
|
||||
{
|
||||
protected $table = 'exam_drafts';
|
||||
@@ -43,15 +41,15 @@ class ExamDraft extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'teacher_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'admin_id' => 'integer',
|
||||
'is_legacy' => 'boolean',
|
||||
'teacher_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'admin_id' => 'integer',
|
||||
'is_legacy' => 'boolean',
|
||||
|
||||
'version' => 'integer',
|
||||
'version' => 'integer',
|
||||
'previous_draft_id' => 'integer',
|
||||
|
||||
'reviewed_at' => 'datetime',
|
||||
'reviewed_at' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -65,7 +63,7 @@ class ExamDraft extends BaseModel
|
||||
*/
|
||||
public function forceSave(array $attributes = []): bool
|
||||
{
|
||||
if (!empty($attributes)) {
|
||||
if (! empty($attributes)) {
|
||||
$this->fill($attributes);
|
||||
}
|
||||
|
||||
|
||||
+14
-15
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Expense extends BaseModel
|
||||
@@ -31,14 +30,14 @@ class Expense extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'date_of_purchase'=> 'date', // change to 'datetime' if stored as DATETIME
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'date_of_purchase' => 'date', // change to 'datetime' if stored as DATETIME
|
||||
|
||||
'purchased_by' => 'integer',
|
||||
'added_by' => 'integer',
|
||||
'reimbursement_id'=> 'integer',
|
||||
'approved_by' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'purchased_by' => 'integer',
|
||||
'added_by' => 'integer',
|
||||
'reimbursement_id' => 'integer',
|
||||
'approved_by' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -71,7 +70,7 @@ class Expense extends BaseModel
|
||||
public static function getReimbursedExpensesWithDetails(array $filters = [])
|
||||
{
|
||||
$q = DB::table('expenses')
|
||||
->selectRaw("
|
||||
->selectRaw('
|
||||
expenses.*,
|
||||
r.id AS reimb_id,
|
||||
r.amount AS reimb_amount, r.reimbursement_method, r.check_number,
|
||||
@@ -80,24 +79,24 @@ class Expense extends BaseModel
|
||||
r.reimbursed_to AS reimb_recipient_id,
|
||||
reimb.firstname AS reimb_firstname, reimb.lastname AS reimb_lastname,
|
||||
approver.firstname AS approver_firstname, approver.lastname AS approver_lastname
|
||||
")
|
||||
')
|
||||
->join('reimbursements as r', 'r.expense_id', '=', 'expenses.id')
|
||||
->leftJoin('users as reimb', 'reimb.id', '=', 'r.reimbursed_to')
|
||||
->leftJoin('users as approver', 'approver.id', '=', 'r.approved_by');
|
||||
|
||||
if (!empty($filters['school_year'])) {
|
||||
if (! empty($filters['school_year'])) {
|
||||
$q->where('r.school_year', $filters['school_year']);
|
||||
}
|
||||
if (!empty($filters['semester'])) {
|
||||
if (! empty($filters['semester'])) {
|
||||
$q->where('r.semester', $filters['semester']);
|
||||
}
|
||||
if (!empty($filters['status'])) {
|
||||
if (! empty($filters['status'])) {
|
||||
$q->where('r.status', $filters['status']);
|
||||
}
|
||||
if (!empty($filters['user_id'])) {
|
||||
if (! empty($filters['user_id'])) {
|
||||
$q->where('r.reimbursed_to', $filters['user_id']);
|
||||
}
|
||||
|
||||
return $q->orderByDesc('r.created_at');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class Family extends BaseModel
|
||||
{
|
||||
protected $table = 'families';
|
||||
@@ -40,4 +38,4 @@ class Family extends BaseModel
|
||||
{
|
||||
return $this->hasMany(FamilyCommPref::class, 'family_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class FamilyCommPref extends BaseModel
|
||||
{
|
||||
protected $table = 'family_comm_prefs';
|
||||
@@ -20,10 +18,10 @@ class FamilyCommPref extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'family_id' => 'integer',
|
||||
'via_email' => 'boolean',
|
||||
'via_sms' => 'boolean',
|
||||
'cc_all_guardians' => 'boolean',
|
||||
'family_id' => 'integer',
|
||||
'via_email' => 'boolean',
|
||||
'via_sms' => 'boolean',
|
||||
'cc_all_guardians' => 'boolean',
|
||||
];
|
||||
|
||||
// Optional relationship
|
||||
@@ -31,4 +29,4 @@ class FamilyCommPref extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(Family::class, 'family_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class FamilyGuardian extends BaseModel
|
||||
{
|
||||
protected $table = 'family_guardians';
|
||||
@@ -22,11 +20,11 @@ class FamilyGuardian extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'family_id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'is_primary' => 'boolean',
|
||||
'receive_emails' => 'boolean',
|
||||
'receive_sms' => 'boolean',
|
||||
'family_id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
'is_primary' => 'boolean',
|
||||
'receive_emails' => 'boolean',
|
||||
'receive_sms' => 'boolean',
|
||||
];
|
||||
|
||||
// Optional relationships
|
||||
@@ -39,4 +37,4 @@ class FamilyGuardian extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class FamilyStudent extends BaseModel
|
||||
@@ -20,9 +19,9 @@ class FamilyStudent extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'family_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'is_primary_home' => 'boolean',
|
||||
'family_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'is_primary_home' => 'boolean',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -53,4 +52,4 @@ class FamilyStudent extends BaseModel
|
||||
->map(fn ($r) => (array) $r)
|
||||
->all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-12
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class FinalExam extends BaseModel
|
||||
{
|
||||
protected $table = 'final_exam';
|
||||
@@ -33,19 +31,19 @@ class FinalExam extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
|
||||
// score is often numeric; adjust if yours is integer
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -82,4 +80,4 @@ class FinalExam extends BaseModel
|
||||
|
||||
return $row?->score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class FinalScore extends BaseModel
|
||||
{
|
||||
protected $table = 'final_score';
|
||||
@@ -27,11 +25,11 @@ class FinalScore extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'teacher_id' => 'integer',
|
||||
'score' => 'decimal:2', // change to 'integer' if score is whole number
|
||||
'teacher_id' => 'integer',
|
||||
'score' => 'decimal:2', // change to 'integer' if score is whole number
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -64,4 +62,4 @@ class FinalScore extends BaseModel
|
||||
|
||||
return $row?->score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace App\Models;
|
||||
class FinanceBalanceCarryforward extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'finance_balance_carryforwards';
|
||||
|
||||
protected $casts = ['source_invoice_ids_json' => 'array', 'metadata_json' => 'array'];
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace App\Models;
|
||||
class FinanceFollowUpNote extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'finance_follow_up_notes';
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace App\Models;
|
||||
class FinanceNotificationLog extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'finance_notification_logs';
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace App\Models;
|
||||
class FinanceNotificationPreference extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'finance_notification_preferences';
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace App\Models;
|
||||
class FinanceReceiptSequence extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'finance_receipt_sequences';
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class GradingLock extends BaseModel
|
||||
{
|
||||
protected $table = 'grading_locks';
|
||||
@@ -24,9 +22,9 @@ class GradingLock extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'class_section_id' => 'integer',
|
||||
'is_locked' => 'boolean',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
'is_locked' => 'boolean',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -63,6 +61,7 @@ class GradingLock extends BaseModel
|
||||
public static function isLocked(int $classSectionId, string $semester, string $schoolYear): bool
|
||||
{
|
||||
$row = static::getLock($classSectionId, $semester, $schoolYear);
|
||||
|
||||
return (bool) ($row?->is_locked ?? false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-16
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Homework extends BaseModel
|
||||
@@ -35,20 +34,20 @@ class Homework extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'homework_index' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'homework_index' => 'integer',
|
||||
|
||||
// keep numeric; change to 'integer' if your scores are whole numbers
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -93,10 +92,18 @@ class Homework extends BaseModel
|
||||
foreach ($rows as $r) {
|
||||
$score = $r->score ?? null;
|
||||
|
||||
if ($score === null) continue;
|
||||
if (is_string($score) && trim($score) === '') continue;
|
||||
if ($score === '') continue;
|
||||
if (!is_numeric($score)) continue;
|
||||
if ($score === null) {
|
||||
continue;
|
||||
}
|
||||
if (is_string($score) && trim($score) === '') {
|
||||
continue;
|
||||
}
|
||||
if ($score === '') {
|
||||
continue;
|
||||
}
|
||||
if (! is_numeric($score)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$total += (float) $score;
|
||||
$count++;
|
||||
@@ -108,4 +115,4 @@ class Homework extends BaseModel
|
||||
|
||||
return round($total / $count, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class Incident extends BaseModel
|
||||
{
|
||||
protected $table = 'incident';
|
||||
@@ -32,11 +30,11 @@ class Incident extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'updated_by_open' => 'integer',
|
||||
'updated_by_closed' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'updated_by_open' => 'integer',
|
||||
'updated_by_closed' => 'integer',
|
||||
'updated_by_canceled' => 'integer',
|
||||
'incident_datetime' => 'datetime',
|
||||
'incident_datetime' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class InventoryCategory extends BaseModel
|
||||
{
|
||||
protected $table = 'inventory_categories';
|
||||
@@ -39,4 +37,4 @@ class InventoryCategory extends BaseModel
|
||||
->get()
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class InventoryItem extends BaseModel
|
||||
{
|
||||
protected $table = 'inventory_items';
|
||||
@@ -33,14 +31,14 @@ class InventoryItem extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'category_id' => 'integer',
|
||||
'quantity' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'category_id' => 'integer',
|
||||
'quantity' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
|
||||
'good_qty' => 'integer',
|
||||
'needs_repair_qty' => 'integer',
|
||||
'need_replace_qty' => 'integer',
|
||||
'cannot_find_qty' => 'integer',
|
||||
'good_qty' => 'integer',
|
||||
'needs_repair_qty' => 'integer',
|
||||
'need_replace_qty' => 'integer',
|
||||
'cannot_find_qty' => 'integer',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -48,4 +46,4 @@ class InventoryItem extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(InventoryCategory::class, 'category_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class InventoryMovement extends BaseModel
|
||||
{
|
||||
protected $table = 'inventory_movements';
|
||||
@@ -26,12 +24,12 @@ class InventoryMovement extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'item_id' => 'integer',
|
||||
'qty_change' => 'integer',
|
||||
'performed_by' => 'integer',
|
||||
'teacher_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'class_section_id'=> 'integer',
|
||||
'item_id' => 'integer',
|
||||
'qty_change' => 'integer',
|
||||
'performed_by' => 'integer',
|
||||
'teacher_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -59,4 +57,4 @@ class InventoryMovement extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(ClassSection::class, 'class_section_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-20
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
@@ -35,19 +34,19 @@ class Invoice extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'parent_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'has_discount' => 'boolean',
|
||||
|
||||
'total_amount' => 'decimal:2',
|
||||
'balance' => 'decimal:2',
|
||||
'paid_amount' => 'decimal:2',
|
||||
'balance' => 'decimal:2',
|
||||
'paid_amount' => 'decimal:2',
|
||||
|
||||
'issue_date' => 'datetime',
|
||||
'due_date' => 'datetime',
|
||||
'issue_date' => 'datetime',
|
||||
'due_date' => 'datetime',
|
||||
// created_at/updated_at exist but are DB-managed; you can still cast if you like:
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -84,13 +83,18 @@ class Invoice extends BaseModel
|
||||
private function normalizeDateTimes(): void
|
||||
{
|
||||
foreach (['issue_date', 'due_date', 'created_at', 'updated_at'] as $field) {
|
||||
if (!$this->isDirty($field)) continue;
|
||||
if (! $this->isDirty($field)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$val = $this->{$field};
|
||||
|
||||
if ($val === null || $val === '' || $val === '0000-00-00' || $val === '0000-00-00 00:00:00') {
|
||||
// keep NULL for due_date; keep other values as-is (DB defaults/triggers)
|
||||
if ($field === 'due_date') $this->{$field} = null;
|
||||
if ($field === 'due_date') {
|
||||
$this->{$field} = null;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -108,11 +112,14 @@ class Invoice extends BaseModel
|
||||
}
|
||||
|
||||
$s = trim((string) $raw);
|
||||
if ($s === '') return null;
|
||||
if ($s === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// strict datetime
|
||||
try {
|
||||
$dt = Carbon::createFromFormat('Y-m-d H:i:s', $s, 'UTC');
|
||||
|
||||
return $dt->utc()->format('Y-m-d H:i:s');
|
||||
} catch (\Throwable $e) {
|
||||
// ignore
|
||||
@@ -121,6 +128,7 @@ class Invoice extends BaseModel
|
||||
// date-only sneaks in => store at 12:00:00
|
||||
try {
|
||||
$d = Carbon::createFromFormat('Y-m-d', $s, 'UTC')->setTime(12, 0, 0);
|
||||
|
||||
return $d->utc()->format('Y-m-d H:i:s');
|
||||
} catch (\Throwable $e) {
|
||||
// ignore
|
||||
@@ -207,7 +215,7 @@ class Invoice extends BaseModel
|
||||
->selectRaw('(SELECT COALESCE(SUM(du.discount_amount),0) FROM discount_usages du WHERE du.invoice_id = i.id) AS discount')
|
||||
->where('i.parent_id', $parentId);
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('i.school_year', $schoolYear);
|
||||
}
|
||||
|
||||
@@ -242,10 +250,12 @@ class Invoice extends BaseModel
|
||||
public static function getInvoicesByUserIds(array $parentIds, string $schoolYear): array
|
||||
{
|
||||
$parentIds = array_values(array_unique(array_map('intval', array_filter($parentIds))));
|
||||
if (empty($parentIds)) return [];
|
||||
if (empty($parentIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return DB::table('invoices as i')
|
||||
->select(['i.id','i.parent_id','i.invoice_number','i.status','i.balance','i.total_amount','i.issue_date','i.due_date'])
|
||||
->select(['i.id', 'i.parent_id', 'i.invoice_number', 'i.status', 'i.balance', 'i.total_amount', 'i.issue_date', 'i.due_date'])
|
||||
->selectRaw('(SELECT COALESCE(SUM(du.discount_amount),0) FROM discount_usages du WHERE du.invoice_id = i.id) AS discount')
|
||||
->whereIn('i.parent_id', $parentIds)
|
||||
->where('i.school_year', $schoolYear)
|
||||
@@ -259,10 +269,12 @@ class Invoice extends BaseModel
|
||||
public static function getAllInvoicesByUserIds(array $parentIds, string $schoolYear): array
|
||||
{
|
||||
$parentIds = array_values(array_unique(array_map('intval', array_filter($parentIds))));
|
||||
if (empty($parentIds)) return [];
|
||||
if (empty($parentIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return DB::table('invoices as i')
|
||||
->select(['i.id','i.parent_id','i.invoice_number','i.status','i.balance','i.issue_date'])
|
||||
->select(['i.id', 'i.parent_id', 'i.invoice_number', 'i.status', 'i.balance', 'i.issue_date'])
|
||||
->selectRaw('(SELECT COALESCE(SUM(du.discount_amount),0) FROM discount_usages du WHERE du.invoice_id = i.id) AS discount')
|
||||
->whereIn('i.parent_id', $parentIds)
|
||||
->where('i.school_year', $schoolYear)
|
||||
@@ -314,10 +326,10 @@ class Invoice extends BaseModel
|
||||
$affected = DB::table('invoices')
|
||||
->where('id', $invoiceId)
|
||||
->update([
|
||||
'total_amount' => DB::raw('GREATEST(total_amount - ' . $amount . ', 0)'),
|
||||
'balance' => DB::raw('GREATEST(balance - ' . $amount . ', 0)'),
|
||||
'total_amount' => DB::raw('GREATEST(total_amount - '.$amount.', 0)'),
|
||||
'balance' => DB::raw('GREATEST(balance - '.$amount.', 0)'),
|
||||
]);
|
||||
|
||||
return $affected >= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class InvoiceEvent extends BaseModel
|
||||
{
|
||||
protected $table = 'invoice_event';
|
||||
@@ -24,9 +22,9 @@ class InvoiceEvent extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'invoice_id' => 'integer',
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'updated_by' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'updated_by' => 'integer',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -39,4 +37,4 @@ class InvoiceEvent extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'updated_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace App\Models;
|
||||
class InvoiceInstallment extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'invoice_installments';
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace App\Models;
|
||||
class InvoiceInstallmentPlan extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'invoice_installment_plans';
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class InvoiceStudentList extends BaseModel
|
||||
{
|
||||
protected $table = 'invoice_students_list';
|
||||
@@ -27,8 +25,8 @@ class InvoiceStudentList extends BaseModel
|
||||
protected $casts = [
|
||||
'invoice_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'enrolled' => 'boolean',
|
||||
'school_id' => 'integer',
|
||||
'enrolled' => 'boolean',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -41,4 +39,4 @@ class InvoiceStudentList extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(Student::class, 'student_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class IpAttempt extends BaseModel
|
||||
{
|
||||
protected $table = 'ip_attempts';
|
||||
@@ -21,9 +19,9 @@ class IpAttempt extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'attempts' => 'integer',
|
||||
'attempts' => 'integer',
|
||||
'last_attempt_at' => 'datetime',
|
||||
'blocked_until' => 'datetime',
|
||||
'blocked_until' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -53,6 +51,7 @@ class IpAttempt extends BaseModel
|
||||
public static function insertIpAttempt(array $data): int
|
||||
{
|
||||
$row = static::query()->create($data);
|
||||
|
||||
return (int) $row->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-17
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -28,10 +27,10 @@ class LateSlipLog extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'printed_by' => 'integer',
|
||||
'slip_date' => 'date', // slip_date is Y-m-d
|
||||
'slip_date' => 'date', // slip_date is Y-m-d
|
||||
'printed_at' => 'datetime',
|
||||
// time_in is often stored as TIME or string; keep as string unless you store as DATETIME
|
||||
'time_in' => 'string',
|
||||
'time_in' => 'string',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -41,27 +40,30 @@ class LateSlipLog extends BaseModel
|
||||
public static function logSlip(array $data, ?int $printedBy): bool
|
||||
{
|
||||
$row = [
|
||||
'school_year' => (string)($data['school_year'] ?? ''),
|
||||
'semester' => (string)($data['semester'] ?? ''),
|
||||
'student_name' => (string)($data['student_name'] ?? ''),
|
||||
'slip_date' => $data['slip_date'] ?? null, // Y-m-d
|
||||
'time_in' => $data['time_in'] ?? null, // H:i:s
|
||||
'grade' => (string)($data['grade'] ?? ''),
|
||||
'reason' => (string)($data['reason'] ?? ''),
|
||||
'admin_name' => (string)($data['admin_name'] ?? ''),
|
||||
'printed_by' => $printedBy,
|
||||
'printed_at' => now(), // use UTC if your app timezone is UTC
|
||||
'school_year' => (string) ($data['school_year'] ?? ''),
|
||||
'semester' => (string) ($data['semester'] ?? ''),
|
||||
'student_name' => (string) ($data['student_name'] ?? ''),
|
||||
'slip_date' => $data['slip_date'] ?? null, // Y-m-d
|
||||
'time_in' => $data['time_in'] ?? null, // H:i:s
|
||||
'grade' => (string) ($data['grade'] ?? ''),
|
||||
'reason' => (string) ($data['reason'] ?? ''),
|
||||
'admin_name' => (string) ($data['admin_name'] ?? ''),
|
||||
'printed_by' => $printedBy,
|
||||
'printed_at' => now(), // use UTC if your app timezone is UTC
|
||||
];
|
||||
|
||||
try {
|
||||
// create() returns model; treat as success if created
|
||||
$created = static::query()->create($row);
|
||||
return !empty($created->id);
|
||||
|
||||
return ! empty($created->id);
|
||||
} catch (QueryException $e) {
|
||||
Log::error('LateSlipLog::logSlip failed: ' . $e->getMessage());
|
||||
Log::error('LateSlipLog::logSlip failed: '.$e->getMessage());
|
||||
|
||||
return false;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('LateSlipLog::logSlip failed: ' . $e->getMessage());
|
||||
Log::error('LateSlipLog::logSlip failed: '.$e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -71,4 +73,4 @@ class LateSlipLog extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'printed_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class LoginActivity extends BaseModel
|
||||
{
|
||||
protected $table = 'login_activity';
|
||||
@@ -25,8 +23,8 @@ class LoginActivity extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'user_id' => 'integer',
|
||||
'login_time' => 'datetime',
|
||||
'user_id' => 'integer',
|
||||
'login_time' => 'datetime',
|
||||
'logout_time' => 'datetime',
|
||||
];
|
||||
|
||||
@@ -46,4 +44,4 @@ class LoginActivity extends BaseModel
|
||||
->limit(max(1, $limit))
|
||||
->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class ManualPayment extends BaseModel
|
||||
{
|
||||
protected $table = 'manual_payments';
|
||||
@@ -23,7 +21,7 @@ class ManualPayment extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'created_at' => 'datetime',
|
||||
];
|
||||
|
||||
@@ -32,4 +30,4 @@ class ManualPayment extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(Invoice::class, 'invoice_number', 'invoice_number');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-11
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class Message extends BaseModel
|
||||
{
|
||||
protected $table = 'messages';
|
||||
@@ -28,13 +26,13 @@ class Message extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'sender_id' => 'integer',
|
||||
'recipient_id' => 'integer',
|
||||
'read_status' => 'boolean',
|
||||
'sender_id' => 'integer',
|
||||
'recipient_id' => 'integer',
|
||||
'read_status' => 'boolean',
|
||||
'message_number' => 'integer',
|
||||
|
||||
'sent_datetime' => 'datetime',
|
||||
'read_datetime' => 'datetime',
|
||||
'sent_datetime' => 'datetime',
|
||||
'read_datetime' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -66,7 +64,7 @@ class Message extends BaseModel
|
||||
$affected = static::query()
|
||||
->whereKey($messageId)
|
||||
->update([
|
||||
'read_status' => 1,
|
||||
'read_status' => 1,
|
||||
'read_datetime' => now(), // set app timezone (configure to UTC if desired)
|
||||
]);
|
||||
|
||||
@@ -121,7 +119,7 @@ class Message extends BaseModel
|
||||
return static::query()
|
||||
->where(function ($q) use ($userId) {
|
||||
$q->where('sender_id', $userId)
|
||||
->orWhere('recipient_id', $userId);
|
||||
->orWhere('recipient_id', $userId);
|
||||
})
|
||||
->where('status', 'trashed')
|
||||
->orderByDesc('sent_datetime')
|
||||
@@ -132,10 +130,10 @@ class Message extends BaseModel
|
||||
{
|
||||
$q = static::query()->where('semester', $semester);
|
||||
|
||||
if (!empty($schoolYear)) {
|
||||
if (! empty($schoolYear)) {
|
||||
$q->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
return $q->orderByDesc('sent_datetime')->get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-12
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class MidtermExam extends BaseModel
|
||||
{
|
||||
protected $table = 'midterm_exam';
|
||||
@@ -33,19 +31,19 @@ class MidtermExam extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
|
||||
// score can be decimal; change to 'integer' if it's whole number
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -85,4 +83,4 @@ class MidtermExam extends BaseModel
|
||||
|
||||
return $row?->score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class MissingScoreOverride extends BaseModel
|
||||
@@ -26,11 +25,11 @@ class MissingScoreOverride extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'item_index' => 'integer',
|
||||
'is_allowed' => 'boolean',
|
||||
'updated_by' => 'integer',
|
||||
'item_index' => 'integer',
|
||||
'is_allowed' => 'boolean',
|
||||
'updated_by' => 'integer',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -101,12 +100,12 @@ class MissingScoreOverride extends BaseModel
|
||||
->where('school_year', $schoolYear)
|
||||
->where('item_type', $itemType);
|
||||
|
||||
if (!empty($studentIds)) {
|
||||
if (! empty($studentIds)) {
|
||||
$q->whereIn('student_id', array_map('intval', $studentIds));
|
||||
}
|
||||
|
||||
if ($itemIndexes !== null) {
|
||||
if (!empty($itemIndexes)) {
|
||||
if (! empty($itemIndexes)) {
|
||||
$q->whereIn('item_index', array_map('intval', $itemIndexes));
|
||||
} else {
|
||||
// legacy behavior: if itemIndexes is provided but empty, do nothing.
|
||||
@@ -128,25 +127,27 @@ class MissingScoreOverride extends BaseModel
|
||||
|
||||
foreach ($checkedItems as $item) {
|
||||
$sid = (int) ($item['student_id'] ?? 0);
|
||||
if ($sid <= 0) continue;
|
||||
if ($sid <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$rows[] = [
|
||||
'student_id' => $sid,
|
||||
'student_id' => $sid,
|
||||
'class_section_id' => $classSectionId,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'item_type' => $itemType,
|
||||
'item_index' => array_key_exists('item_index', $item) ? $item['item_index'] : null,
|
||||
'is_allowed' => 1,
|
||||
'updated_by' => $updatedBy,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'item_type' => $itemType,
|
||||
'item_index' => array_key_exists('item_index', $item) ? $item['item_index'] : null,
|
||||
'is_allowed' => 1,
|
||||
'updated_by' => $updatedBy,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($rows)) {
|
||||
if (! empty($rows)) {
|
||||
DB::table((new static)->getTable())->insert($rows);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class NavItem extends BaseModel
|
||||
@@ -11,6 +10,7 @@ class NavItem extends BaseModel
|
||||
|
||||
// ✅ legacy: timestamps + soft deletes
|
||||
use SoftDeletes;
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
protected $fillable = [
|
||||
@@ -25,8 +25,8 @@ class NavItem extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'menu_parent_id' => 'integer',
|
||||
'sort_order' => 'integer',
|
||||
'is_enabled' => 'boolean',
|
||||
'sort_order' => 'integer',
|
||||
'is_enabled' => 'boolean',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -55,4 +55,4 @@ class NavItem extends BaseModel
|
||||
->get()
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
@@ -12,6 +11,7 @@ class Notification extends BaseModel
|
||||
|
||||
// ✅ legacy: soft deletes + timestamps
|
||||
use SoftDeletes;
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
protected $fillable = [
|
||||
@@ -73,10 +73,10 @@ class Notification extends BaseModel
|
||||
->where('scheduled_at', '<=', now())
|
||||
->where(function ($w) {
|
||||
$w->whereNull('expires_at')
|
||||
->orWhere('expires_at', '>', now());
|
||||
->orWhere('expires_at', '>', now());
|
||||
});
|
||||
|
||||
if (!empty($targetGroup)) {
|
||||
if (! empty($targetGroup)) {
|
||||
$q->where('target_group', $targetGroup);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,10 @@ class Notification extends BaseModel
|
||||
public static function restoreNotification(int $id): bool
|
||||
{
|
||||
$row = static::withTrashed()->find($id);
|
||||
if (!$row) return false;
|
||||
if (! $row) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $row->restore();
|
||||
}
|
||||
|
||||
@@ -129,4 +132,4 @@ class Notification extends BaseModel
|
||||
->where('expires_at', '<', now())
|
||||
->delete(); // soft delete
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ParentAttendanceReport extends BaseModel
|
||||
@@ -27,10 +26,10 @@ class ParentAttendanceReport extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'parent_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'class_section_id'=> 'integer',
|
||||
'report_date' => 'date',
|
||||
'parent_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'report_date' => 'date',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -68,10 +67,10 @@ class ParentAttendanceReport extends BaseModel
|
||||
$q->where('par.parent_id', $parentId);
|
||||
}
|
||||
|
||||
if (!empty($startDate)) {
|
||||
if (! empty($startDate)) {
|
||||
$q->where('par.report_date', '>=', $startDate);
|
||||
}
|
||||
if (!empty($endDate)) {
|
||||
if (! empty($endDate)) {
|
||||
$q->where('par.report_date', '<=', $endDate);
|
||||
}
|
||||
if (is_string($schoolYear) && $schoolYear !== '') {
|
||||
@@ -82,12 +81,12 @@ class ParentAttendanceReport extends BaseModel
|
||||
}
|
||||
|
||||
$q->leftJoin('students as s', 's.id', '=', 'par.student_id')
|
||||
->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'par.class_section_id')
|
||||
->select('par.*', 's.firstname', 's.lastname', 'cs.class_section_name')
|
||||
->orderBy('par.report_date', 'asc')
|
||||
->orderBy('par.class_section_id', 'asc')
|
||||
->orderBy('par.student_id', 'asc');
|
||||
->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'par.class_section_id')
|
||||
->select('par.*', 's.firstname', 's.lastname', 'cs.class_section_name')
|
||||
->orderBy('par.report_date', 'asc')
|
||||
->orderBy('par.class_section_id', 'asc')
|
||||
->orderBy('par.student_id', 'asc');
|
||||
|
||||
return $q->get()->map(fn ($r) => (array) $r)->all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class ParentMeetingSchedule extends BaseModel
|
||||
{
|
||||
protected $table = 'parent_meeting_schedules';
|
||||
@@ -27,14 +25,14 @@ class ParentMeetingSchedule extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'parent_user_id' => 'integer',
|
||||
'created_by' => 'integer',
|
||||
'created_by' => 'integer',
|
||||
|
||||
// if these are DATE/TIME columns:
|
||||
'date' => 'date',
|
||||
'date' => 'date',
|
||||
// time is typically stored as TIME or string; keep as string unless DATETIME
|
||||
'time' => 'string',
|
||||
'time' => 'string',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -52,4 +50,4 @@ class ParentMeetingSchedule extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'created_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class ParentModel extends BaseModel
|
||||
{
|
||||
protected $table = 'parents';
|
||||
@@ -31,4 +29,4 @@ class ParentModel extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'firstparent_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class ParentNotification extends BaseModel
|
||||
{
|
||||
protected $table = 'parent_notifications';
|
||||
@@ -25,7 +23,7 @@ class ParentNotification extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
// incident_date is stored as Y-m-d in legacy usage
|
||||
'incident_date' => 'date',
|
||||
];
|
||||
@@ -52,7 +50,7 @@ class ParentNotification extends BaseModel
|
||||
->whereDate('incident_date', $incidentYmd)
|
||||
->where('channel', $channel);
|
||||
|
||||
if (!empty($to)) {
|
||||
if (! empty($to)) {
|
||||
$q->where('to_address', $to);
|
||||
}
|
||||
|
||||
@@ -60,4 +58,4 @@ class ParentNotification extends BaseModel
|
||||
|
||||
return $row && (($row->status ?? '') === 'sent');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class Participation extends BaseModel
|
||||
{
|
||||
protected $table = 'participation';
|
||||
@@ -33,19 +31,19 @@ class Participation extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
|
||||
// score is numeric; change to 'integer' if it is whole number
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -80,15 +78,25 @@ class Participation extends BaseModel
|
||||
}
|
||||
|
||||
$row = $q->first();
|
||||
if (!$row) return null;
|
||||
if (! $row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$score = $row->score;
|
||||
|
||||
if ($score === null) return null;
|
||||
if (is_string($score) && trim($score) === '') return null;
|
||||
if ($score === '') return null;
|
||||
if (!is_numeric($score)) return null;
|
||||
if ($score === null) {
|
||||
return null;
|
||||
}
|
||||
if (is_string($score) && trim($score) === '') {
|
||||
return null;
|
||||
}
|
||||
if ($score === '') {
|
||||
return null;
|
||||
}
|
||||
if (! is_numeric($score)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (float) $score;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PasswordReset extends BaseModel
|
||||
{
|
||||
protected $table = 'password_resets';
|
||||
@@ -23,6 +21,7 @@ class PasswordReset extends BaseModel
|
||||
public $timestamps = true;
|
||||
|
||||
const CREATED_AT = 'created_at';
|
||||
|
||||
const UPDATED_AT = 'expires_at';
|
||||
|
||||
protected $fillable = [
|
||||
@@ -45,4 +44,4 @@ class PasswordReset extends BaseModel
|
||||
// protected $primaryKey = 'id';
|
||||
// public $incrementing = true;
|
||||
// protected $keyType = 'int';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PasswordResetRequest extends BaseModel
|
||||
{
|
||||
protected $table = 'password_reset_requests';
|
||||
@@ -19,4 +17,4 @@ class PasswordResetRequest extends BaseModel
|
||||
protected $casts = [
|
||||
'requested_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PayPalPayment extends BaseModel
|
||||
{
|
||||
protected $table = 'paypal_payments';
|
||||
@@ -13,6 +11,7 @@ class PayPalPayment extends BaseModel
|
||||
* In Laravel: enable timestamps but disable UPDATED_AT.
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
const UPDATED_AT = null;
|
||||
|
||||
protected $fillable = [
|
||||
@@ -38,10 +37,10 @@ class PayPalPayment extends BaseModel
|
||||
|
||||
protected $casts = [
|
||||
'parent_school_id' => 'integer',
|
||||
'amount' => 'decimal:2',
|
||||
'paypal_fee' => 'decimal:2',
|
||||
'net_amount' => 'decimal:2',
|
||||
'synced' => 'boolean',
|
||||
'sync_attempts' => 'integer',
|
||||
'amount' => 'decimal:2',
|
||||
'paypal_fee' => 'decimal:2',
|
||||
'net_amount' => 'decimal:2',
|
||||
'synced' => 'boolean',
|
||||
'sync_attempts' => 'integer',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+25
-22
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class Payment extends BaseModel
|
||||
@@ -34,16 +33,16 @@ class Payment extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'parent_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'number_of_installments' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'number_of_installments' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
|
||||
'total_amount' => 'decimal:2',
|
||||
'paid_amount' => 'decimal:2',
|
||||
'balance' => 'decimal:2',
|
||||
'total_amount' => 'decimal:2',
|
||||
'paid_amount' => 'decimal:2',
|
||||
'balance' => 'decimal:2',
|
||||
|
||||
'payment_date' => 'datetime',
|
||||
'payment_date' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -84,18 +83,20 @@ class Payment extends BaseModel
|
||||
{
|
||||
/** @var self|null $payment */
|
||||
$payment = static::query()->find($paymentId);
|
||||
if (!$payment) return false;
|
||||
if (! $payment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$newBalance = (float)$payment->balance - (float)$amountPaid;
|
||||
$newBalance = (float) $payment->balance - (float) $amountPaid;
|
||||
|
||||
// keep precision stable
|
||||
$paidAmount = (float)$payment->paid_amount + (float)$amountPaid;
|
||||
$paidAmount = (float) $payment->paid_amount + (float) $amountPaid;
|
||||
|
||||
$affected = static::query()
|
||||
->whereKey($paymentId)
|
||||
->update([
|
||||
'paid_amount' => $paidAmount,
|
||||
'balance' => $newBalance,
|
||||
'balance' => $newBalance,
|
||||
]);
|
||||
|
||||
return $affected > 0;
|
||||
@@ -116,21 +117,21 @@ class Payment extends BaseModel
|
||||
public static function generateNewTransactionId(): string
|
||||
{
|
||||
$currentYear = date('Y');
|
||||
$prefix = $currentYear . '-';
|
||||
$prefix = $currentYear.'-';
|
||||
|
||||
$latest = static::query()
|
||||
->where('transaction_id', 'like', $prefix . '%')
|
||||
->where('transaction_id', 'like', $prefix.'%')
|
||||
->orderByDesc('transaction_id')
|
||||
->first();
|
||||
|
||||
if ($latest && !empty($latest->transaction_id)) {
|
||||
$lastNumber = (int) str_replace($prefix, '', (string)$latest->transaction_id);
|
||||
if ($latest && ! empty($latest->transaction_id)) {
|
||||
$lastNumber = (int) str_replace($prefix, '', (string) $latest->transaction_id);
|
||||
$newNumber = $lastNumber + 1;
|
||||
} else {
|
||||
$newNumber = 1;
|
||||
}
|
||||
|
||||
return $prefix . str_pad((string)$newNumber, 6, '0', STR_PAD_LEFT);
|
||||
return $prefix.str_pad((string) $newNumber, 6, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,11 +140,13 @@ class Payment extends BaseModel
|
||||
*/
|
||||
public static function getPaymentsByInvoice($invoiceIds): array
|
||||
{
|
||||
if (!is_array($invoiceIds)) {
|
||||
if (! is_array($invoiceIds)) {
|
||||
$invoiceIds = [$invoiceIds];
|
||||
}
|
||||
$invoiceIds = array_values(array_unique(array_map('intval', array_filter($invoiceIds))));
|
||||
if (empty($invoiceIds)) return [];
|
||||
if (empty($invoiceIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Subquery: latest payment_date per invoice (Full/Partial only)
|
||||
$latestSub = DB::table('payments')
|
||||
@@ -155,7 +158,7 @@ class Payment extends BaseModel
|
||||
$rows = DB::table('payments as p')
|
||||
->joinSub($latestSub, 'latest', function ($join) {
|
||||
$join->on('latest.invoice_id', '=', 'p.invoice_id')
|
||||
->on('latest.max_date', '=', 'p.payment_date');
|
||||
->on('latest.max_date', '=', 'p.payment_date');
|
||||
})
|
||||
->whereIn('p.invoice_id', $invoiceIds)
|
||||
->whereIn('p.status', ['Full', 'Paid', 'Partially Paid'])
|
||||
@@ -169,4 +172,4 @@ class Payment extends BaseModel
|
||||
|
||||
return $rows->map(fn ($r) => (array) $r)->all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace App\Models;
|
||||
class PaymentCarryforwardAllocation extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'payment_carryforward_allocations';
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PaymentError extends BaseModel
|
||||
{
|
||||
protected $table = 'payment_error';
|
||||
@@ -26,12 +24,12 @@ class PaymentError extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'payment_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'wrong_paid_amount' => 'decimal:2', // adjust precision if needed
|
||||
'logged_by' => 'integer',
|
||||
'logged_at' => 'datetime',
|
||||
'payment_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'parent_id' => 'integer',
|
||||
'wrong_paid_amount' => 'decimal:2', // adjust precision if needed
|
||||
'logged_by' => 'integer',
|
||||
'logged_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -49,4 +47,4 @@ class PaymentError extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'logged_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace App\Models;
|
||||
class PaymentInstallmentAllocation extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $table = 'payment_installment_allocations';
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PaymentNotificationLog extends BaseModel
|
||||
{
|
||||
protected $table = 'payment_notification_logs';
|
||||
@@ -31,14 +29,14 @@ class PaymentNotificationLog extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'parent_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'period_year' => 'integer',
|
||||
'period_month' => 'integer',
|
||||
'head_fa_notified' => 'boolean',
|
||||
'balance_snapshot' => 'decimal:2', // adjust precision if needed
|
||||
'created_at' => 'datetime',
|
||||
'sent_at' => 'datetime',
|
||||
'parent_id' => 'integer',
|
||||
'invoice_id' => 'integer',
|
||||
'period_year' => 'integer',
|
||||
'period_month' => 'integer',
|
||||
'head_fa_notified' => 'boolean',
|
||||
'balance_snapshot' => 'decimal:2', // adjust precision if needed
|
||||
'created_at' => 'datetime',
|
||||
'sent_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -73,16 +71,16 @@ class PaymentNotificationLog extends BaseModel
|
||||
{
|
||||
$q = static::query()->orderByDesc('sent_at');
|
||||
|
||||
if (!empty($from)) {
|
||||
if (! empty($from)) {
|
||||
$q->where('sent_at', '>=', $from);
|
||||
}
|
||||
if (!empty($to)) {
|
||||
if (! empty($to)) {
|
||||
$q->where('sent_at', '<=', $to);
|
||||
}
|
||||
if (!empty($type)) {
|
||||
if (! empty($type)) {
|
||||
$q->where('type', $type);
|
||||
}
|
||||
|
||||
return $q->get()->toArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class PaymentTransaction extends BaseModel
|
||||
{
|
||||
protected $table = 'payment_transactions';
|
||||
@@ -29,11 +26,11 @@ class PaymentTransaction extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'payment_id' => 'integer',
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'transaction_fee' => 'decimal:2', // adjust precision if needed
|
||||
'transaction_date' => 'datetime',
|
||||
'is_full_payment' => 'boolean',
|
||||
'payment_id' => 'integer',
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'transaction_fee' => 'decimal:2', // adjust precision if needed
|
||||
'transaction_date' => 'datetime',
|
||||
'is_full_payment' => 'boolean',
|
||||
];
|
||||
|
||||
/* Optional relationship */
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PaypalTransaction extends BaseModel
|
||||
{
|
||||
protected $table = 'paypal_transactions';
|
||||
@@ -29,11 +27,11 @@ class PaypalTransaction extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'payment_id' => 'integer',
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'transaction_fee' => 'decimal:2', // adjust precision if needed
|
||||
'payment_id' => 'integer',
|
||||
'amount' => 'decimal:2', // adjust precision if needed
|
||||
'transaction_fee' => 'decimal:2', // adjust precision if needed
|
||||
// raw_data is often JSON; if it's JSON in DB, cast to array
|
||||
'raw_data' => 'array',
|
||||
'raw_data' => 'array',
|
||||
];
|
||||
|
||||
/* Optional relationship */
|
||||
@@ -41,4 +39,4 @@ class PaypalTransaction extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(Payment::class, 'payment_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -32,7 +31,7 @@ class Permission extends BaseModel
|
||||
try {
|
||||
return static::query()->get();
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('Error fetching permissions: ' . $e->getMessage());
|
||||
Log::error('Error fetching permissions: '.$e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
@@ -53,12 +52,12 @@ class Permission extends BaseModel
|
||||
->map(fn ($r) => (array) $r)
|
||||
->all();
|
||||
|
||||
Log::info('Role permissions fetched: ' . print_r($rows, true));
|
||||
Log::info('Role permissions fetched: '.print_r($rows, true));
|
||||
|
||||
return $rows;
|
||||
} catch (\Throwable $e) {
|
||||
Log::error("Error fetching role permissions for role ID {$roleId}: " . $e->getMessage());
|
||||
Log::error("Error fetching role permissions for role ID {$roleId}: ".$e->getMessage());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PlacementBatch extends BaseModel
|
||||
{
|
||||
protected $table = 'placement_batches';
|
||||
@@ -35,4 +33,4 @@ class PlacementBatch extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'updated_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PlacementLevel extends BaseModel
|
||||
{
|
||||
protected $table = 'placement_levels';
|
||||
@@ -42,4 +40,4 @@ class PlacementLevel extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'updated_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PlacementScore extends BaseModel
|
||||
{
|
||||
protected $table = 'placement_scores';
|
||||
@@ -22,9 +20,9 @@ class PlacementScore extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'batch_id' => 'integer',
|
||||
'batch_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'score' => 'decimal:2', // change to 'integer' if score is whole number
|
||||
'score' => 'decimal:2', // change to 'integer' if score is whole number
|
||||
'created_by' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
];
|
||||
@@ -49,4 +47,4 @@ class PlacementScore extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(User::class, 'updated_by');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class Preferences extends BaseModel
|
||||
{
|
||||
protected $table = 'user_preferences';
|
||||
@@ -34,15 +32,15 @@ class Preferences extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'user_id' => 'integer',
|
||||
'user_id' => 'integer',
|
||||
|
||||
'receive_email_notifications' => 'boolean',
|
||||
'receive_sms_notifications' => 'boolean',
|
||||
'receive_push_notifications' => 'boolean',
|
||||
'daily_summary_email' => 'boolean',
|
||||
'privacy_mode' => 'boolean',
|
||||
'marketing_emails' => 'boolean',
|
||||
'account_activity_alerts' => 'boolean',
|
||||
'receive_sms_notifications' => 'boolean',
|
||||
'receive_push_notifications' => 'boolean',
|
||||
'daily_summary_email' => 'boolean',
|
||||
'privacy_mode' => 'boolean',
|
||||
'marketing_emails' => 'boolean',
|
||||
'account_activity_alerts' => 'boolean',
|
||||
];
|
||||
|
||||
/* Optional relationship */
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
|
||||
class PrintRequest extends BaseModel
|
||||
{
|
||||
protected $table = 'print_requests';
|
||||
@@ -24,11 +22,11 @@ class PrintRequest extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'teacher_id' => 'integer',
|
||||
'admin_id' => 'integer',
|
||||
'class_id' => 'integer',
|
||||
'num_copies' => 'integer',
|
||||
'required_by' => 'datetime', // if stored as DATETIME
|
||||
'teacher_id' => 'integer',
|
||||
'admin_id' => 'integer',
|
||||
'class_id' => 'integer',
|
||||
'num_copies' => 'integer',
|
||||
'required_by' => 'datetime', // if stored as DATETIME
|
||||
];
|
||||
|
||||
/* Optional relationships */
|
||||
@@ -46,4 +44,4 @@ class PrintRequest extends BaseModel
|
||||
{
|
||||
return $this->belongsTo(SchoolClass::class, 'class_id');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-14
@@ -3,7 +3,6 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Project extends BaseModel
|
||||
@@ -45,17 +44,17 @@ class Project extends BaseModel
|
||||
* Helpful casts (adjust types if your DB columns differ).
|
||||
*/
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'project_index' => 'integer',
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime', // or 'float' if you prefer
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'project_index' => 'integer',
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime', // or 'float' if you prefer
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* ============================================================
|
||||
@@ -91,7 +90,7 @@ class Project extends BaseModel
|
||||
public function scopeForTerm(Builder $q, string $semester, string $schoolYear): Builder
|
||||
{
|
||||
return $q->where('semester', $semester)
|
||||
->where('school_year', $schoolYear);
|
||||
->where('school_year', $schoolYear);
|
||||
}
|
||||
|
||||
public function scopeForClassSection(Builder $q, ?int $classSectionId): Builder
|
||||
@@ -161,4 +160,4 @@ class Project extends BaseModel
|
||||
// Safe default if you're unsure. Set to false if score is numeric.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,16 +16,27 @@ class PromotionAuditLog extends BaseModel
|
||||
public $timestamps = true;
|
||||
|
||||
public const ACTION_RECORD_CREATED = 'record_created';
|
||||
|
||||
public const ACTION_STATUS_CHANGED = 'status_changed';
|
||||
|
||||
public const ACTION_ELIGIBILITY_EVALUATED = 'eligibility_evaluated';
|
||||
|
||||
public const ACTION_PARENT_NOTIFIED = 'parent_notified';
|
||||
|
||||
public const ACTION_ENROLLMENT_STARTED = 'enrollment_started';
|
||||
|
||||
public const ACTION_ENROLLMENT_STEP_COMPLETED = 'enrollment_step_completed';
|
||||
|
||||
public const ACTION_ENROLLMENT_COMPLETED = 'enrollment_completed';
|
||||
|
||||
public const ACTION_PROMOTION_FINALIZED = 'promotion_finalized';
|
||||
|
||||
public const ACTION_DEADLINE_SET = 'deadline_set';
|
||||
|
||||
public const ACTION_REMINDER_SENT = 'reminder_sent';
|
||||
|
||||
public const ACTION_DEADLINE_EXPIRED = 'deadline_expired';
|
||||
|
||||
public const ACTION_MANUAL_OVERRIDE = 'manual_override';
|
||||
|
||||
protected $fillable = [
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class PromotionQueue extends BaseModel
|
||||
@@ -22,16 +21,17 @@ class PromotionQueue extends BaseModel
|
||||
'updated_at',
|
||||
'updated_by',
|
||||
];
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'from_class_section_id' => 'integer',
|
||||
'to_class_id' => 'integer',
|
||||
'to_class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'student_id' => 'integer',
|
||||
'from_class_section_id' => 'integer',
|
||||
'to_class_id' => 'integer',
|
||||
'to_class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* ============================================================
|
||||
@@ -92,9 +92,9 @@ class PromotionQueue extends BaseModel
|
||||
public static function upsertQueue(array $data): ?self
|
||||
{
|
||||
$studentId = isset($data['student_id']) ? (int) $data['student_id'] : null;
|
||||
$yearTo = isset($data['school_year_to']) ? (string) $data['school_year_to'] : null;
|
||||
$yearTo = isset($data['school_year_to']) ? (string) $data['school_year_to'] : null;
|
||||
|
||||
if (!$studentId || !$yearTo) {
|
||||
if (! $studentId || ! $yearTo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -114,4 +114,4 @@ class PromotionQueue extends BaseModel
|
||||
{
|
||||
return (bool) static::upsertQueue($data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,13 @@ class PromotionReminderLog extends BaseModel
|
||||
public $timestamps = true;
|
||||
|
||||
public const TYPE_FIRST = 'first';
|
||||
|
||||
public const TYPE_HALFWAY = 'halfway';
|
||||
|
||||
public const TYPE_FINAL = 'final';
|
||||
|
||||
public const TYPE_EXPIRATION = 'expiration';
|
||||
|
||||
public const TYPE_MANUAL = 'manual';
|
||||
|
||||
public const ALLOWED_TYPES = [
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class PurchaseOrder extends BaseModel
|
||||
{
|
||||
@@ -25,18 +24,19 @@ class PurchaseOrder extends BaseModel
|
||||
'total',
|
||||
'notes',
|
||||
];
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
protected $casts = [
|
||||
'supplier_id' => 'integer',
|
||||
'order_date' => 'date', // or 'datetime' if your DB stores time too
|
||||
'expected_date' => 'date',
|
||||
'subtotal' => 'decimal:2',
|
||||
'tax' => 'decimal:2',
|
||||
'total' => 'decimal:2',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
'supplier_id' => 'integer',
|
||||
'order_date' => 'date', // or 'datetime' if your DB stores time too
|
||||
'expected_date' => 'date',
|
||||
'subtotal' => 'decimal:2',
|
||||
'tax' => 'decimal:2',
|
||||
'total' => 'decimal:2',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'deleted_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function getFillable(): array
|
||||
@@ -49,9 +49,12 @@ class PurchaseOrder extends BaseModel
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
public const STATUS_DRAFT = 'draft';
|
||||
public const STATUS_ORDERED = 'ordered';
|
||||
public const STATUS_DRAFT = 'draft';
|
||||
|
||||
public const STATUS_ORDERED = 'ordered';
|
||||
|
||||
public const STATUS_RECEIVED = 'received';
|
||||
|
||||
public const STATUS_CANCELED = 'canceled';
|
||||
|
||||
public static function allowedStatuses(): array
|
||||
@@ -116,8 +119,8 @@ class PurchaseOrder extends BaseModel
|
||||
$total = $subtotal + $tax;
|
||||
|
||||
$this->subtotal = $subtotal;
|
||||
$this->tax = $tax;
|
||||
$this->total = $total;
|
||||
$this->tax = $tax;
|
||||
$this->total = $total;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -125,18 +128,21 @@ class PurchaseOrder extends BaseModel
|
||||
public function markOrdered(): self
|
||||
{
|
||||
$this->status = self::STATUS_ORDERED;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function markReceived(): self
|
||||
{
|
||||
$this->status = self::STATUS_RECEIVED;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function markCanceled(): self
|
||||
{
|
||||
$this->status = self::STATUS_CANCELED;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -149,16 +155,16 @@ class PurchaseOrder extends BaseModel
|
||||
{
|
||||
// Mirrors legacy: unique purchase_orders.po_number except current id.
|
||||
return [
|
||||
'po_number' => ['required', 'string', 'max:60', 'unique:purchase_orders,po_number,' . ($id ?? 'NULL') . ',id'],
|
||||
'po_number' => ['required', 'string', 'max:60', 'unique:purchase_orders,po_number,'.($id ?? 'NULL').',id'],
|
||||
'supplier_id' => ['required', 'integer', 'min:1', 'exists:suppliers,id'],
|
||||
'status' => ['nullable', 'string', 'in:' . implode(',', self::allowedStatuses())],
|
||||
'status' => ['nullable', 'string', 'in:'.implode(',', self::allowedStatuses())],
|
||||
|
||||
'order_date' => ['nullable', 'date'],
|
||||
'expected_date' => ['nullable', 'date', 'after_or_equal:order_date'],
|
||||
'subtotal' => ['nullable', 'numeric', 'min:0'],
|
||||
'tax' => ['nullable', 'numeric', 'min:0'],
|
||||
'total' => ['nullable', 'numeric', 'min:0'],
|
||||
'notes' => ['nullable', 'string', 'max:5000'],
|
||||
'order_date' => ['nullable', 'date'],
|
||||
'expected_date' => ['nullable', 'date', 'after_or_equal:order_date'],
|
||||
'subtotal' => ['nullable', 'numeric', 'min:0'],
|
||||
'tax' => ['nullable', 'numeric', 'min:0'],
|
||||
'total' => ['nullable', 'numeric', 'min:0'],
|
||||
'notes' => ['nullable', 'string', 'max:5000'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class PurchaseOrderItem extends BaseModel
|
||||
@@ -17,16 +16,17 @@ class PurchaseOrderItem extends BaseModel
|
||||
'received_qty',
|
||||
'unit_cost',
|
||||
];
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
protected $casts = [
|
||||
'purchase_order_id' => 'integer',
|
||||
'supply_id' => 'integer',
|
||||
'quantity' => 'integer',
|
||||
'received_qty' => 'integer',
|
||||
'unit_cost' => 'decimal:2', // adjust scale to match DB (e.g., decimal:4)
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'supply_id' => 'integer',
|
||||
'quantity' => 'integer',
|
||||
'received_qty' => 'integer',
|
||||
'unit_cost' => 'decimal:2', // adjust scale to match DB (e.g., decimal:4)
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function getFillable(): array
|
||||
@@ -57,16 +57,18 @@ class PurchaseOrderItem extends BaseModel
|
||||
// total ordered cost
|
||||
public function getLineTotalAttribute(): float
|
||||
{
|
||||
$qty = (int) ($this->quantity ?? 0);
|
||||
$qty = (int) ($this->quantity ?? 0);
|
||||
$cost = (float) ($this->unit_cost ?? 0);
|
||||
|
||||
return $qty * $cost;
|
||||
}
|
||||
|
||||
// total received cost
|
||||
public function getReceivedLineTotalAttribute(): float
|
||||
{
|
||||
$qty = (int) ($this->received_qty ?? 0);
|
||||
$qty = (int) ($this->received_qty ?? 0);
|
||||
$cost = (float) ($this->unit_cost ?? 0);
|
||||
|
||||
return $qty * $cost;
|
||||
}
|
||||
|
||||
@@ -81,11 +83,11 @@ class PurchaseOrderItem extends BaseModel
|
||||
// keep strict by default to match legacy behavior
|
||||
return [
|
||||
'purchase_order_id' => [$updating ? 'sometimes' : 'required', 'integer', 'min:1', 'exists:purchase_orders,id'],
|
||||
'supply_id' => [$updating ? 'sometimes' : 'required', 'integer', 'min:1', 'exists:supplies,id'],
|
||||
'description' => ['nullable', 'string', 'max:1000'],
|
||||
'quantity' => [$updating ? 'sometimes' : 'required', 'integer', 'min:1'],
|
||||
'received_qty' => ['nullable', 'integer', 'min:0', 'lte:quantity'],
|
||||
'unit_cost' => [$updating ? 'sometimes' : 'required', 'numeric', 'min:0'],
|
||||
'supply_id' => [$updating ? 'sometimes' : 'required', 'integer', 'min:1', 'exists:supplies,id'],
|
||||
'description' => ['nullable', 'string', 'max:1000'],
|
||||
'quantity' => [$updating ? 'sometimes' : 'required', 'integer', 'min:1'],
|
||||
'received_qty' => ['nullable', 'integer', 'min:0', 'lte:quantity'],
|
||||
'unit_cost' => [$updating ? 'sometimes' : 'required', 'numeric', 'min:0'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -2,12 +2,12 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Quiz extends BaseModel
|
||||
{
|
||||
protected $table = 'quiz';
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = [
|
||||
@@ -30,17 +30,17 @@ class Quiz extends BaseModel
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'student_id' => 'integer',
|
||||
'school_id' => 'integer',
|
||||
'class_section_id' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'quiz_index' => 'integer',
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'updated_by' => 'integer',
|
||||
'quiz_index' => 'integer',
|
||||
'score' => 'decimal:2',
|
||||
'max_points' => 'decimal:2',
|
||||
'locked_by' => 'integer',
|
||||
'locked_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function student(): BelongsTo
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user