Files
alrahma_sunday_school_api/app/Models/AttendanceDay.php
T
2026-06-09 00:03:03 -04:00

218 lines
6.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Models;
use Illuminate\Database\QueryException;
use Illuminate\Support\Carbon;
class AttendanceDay extends BaseModel
{
protected $table = 'attendance_day';
// ✅ You are storing created_at / updated_at manually in legacy (timestamps off there)
// User didn't explicitly ask to auto-manage here, so we keep it OFF to match legacy.
// If you want auto-manage, tell me and Ill flip it.
public $timestamps = false;
protected $fillable = [
'class_section_id',
'date',
'status',
'draft',
'submitted',
'published',
'finalized',
'submitted_by',
'submitted_at',
'published_by',
'published_at',
'auto_publish_at',
'reopened_by',
'reopened_at',
'reopen_reason',
'semester',
'school_year',
'created_at',
'updated_at',
];
protected $casts = [
'class_section_id' => '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',
// If date is stored as DATE string; if it's DATETIME, change to 'datetime'
'date' => 'date',
];
/* =========================
* legacy method equivalents
* ========================= */
/**
* Legacy helper: True iff (section, date, term) is hard-locked for everyone.
* Treats 'published' and legacy 'finalized' as finalized.
*/
public static function isFinalized(
int $classSectionId,
string $date,
?string $semester = null,
?string $schoolYear = null
): bool {
$q = static::query()
->select('id')
->where('class_section_id', $classSectionId)
->whereDate('date', $date)
->where(function ($w) {
$w->where('status', 'published')
->orWhere('status', 'finalized'); // legacy
});
if ($semester !== null) {
$q->where('semester', $semester);
}
if ($schoolYear !== null) {
$q->where('school_year', $schoolYear);
}
return $q->exists();
}
/**
* Find day row by (section, date, term).
*/
public static function findBySectionDate(
int $classSectionId,
string $date,
?string $semester,
?string $schoolYear
): ?self {
return static::query()
->where('class_section_id', $classSectionId)
->whereDate('date', $date)
->where('semester', $semester)
->where('school_year', $schoolYear)
->first();
}
/**
* Get draft row for (section,date,term), create it if missing.
* Requires unique index: (class_section_id, date, semester, school_year)
*/
public static function getOrCreateDraft(
int $classSectionId,
string $date,
?string $semester,
?string $schoolYear,
int $userId = 0
): self {
$row = static::findBySectionDate($classSectionId, $date, $semester, $schoolYear);
if ($row) {
return $row;
}
$now = now();
$normalizedDate = Carbon::parse($date)->toDateString();
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,
]);
} catch (QueryException $e) {
// Race: someone inserted same unique key.
$row = static::findBySectionDate($classSectionId, $date, $semester, $schoolYear);
if ($row) {
return $row;
}
throw $e;
}
}
/**
* DEPRECATED legacy finalize => submit (teacher submit).
*/
public function finalize(int $userId): bool
{
return $this->submit($userId, null);
}
/**
* Teacher submit: status => submitted (teacher locked, admin editable).
*/
public function submit(int $userId, ?string $autoPublishAt = null): bool
{
$now = now();
$payload = [
'status' => 'submitted',
'submitted_by' => $userId,
'submitted_at' => $now,
'updated_at' => $now,
];
if ($autoPublishAt !== null) {
$payload['auto_publish_at'] = $autoPublishAt;
}
return static::query()->whereKey($this->id)->update($payload) >= 0;
}
/**
* Admin publish (hard lock): status => published.
*/
public function publish(int $userId): bool
{
$now = now();
return static::query()->whereKey($this->id)->update([
'status' => 'published',
'published_by' => $userId,
'published_at' => $now,
'updated_at' => $now,
]) >= 0;
}
/**
* Admin reopen a day back to 'draft' (default) or 'submitted'.
*/
public function reopen(int $userId, string $toStatus = 'draft', ?string $reason = null): bool
{
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,
'reopen_reason' => $reason,
'updated_at' => $now,
]) >= 0;
}
}