add projet
This commit is contained in:
Executable
+198
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AttendanceDay extends Model
|
||||
{
|
||||
protected $table = 'attendance_day'; // Because you store created_at/updated_at but CI didn't auto-manage them
|
||||
public $timestamps = true;
|
||||
protected $fillable = [
|
||||
'class_section_id',
|
||||
'date',
|
||||
'status',
|
||||
'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',
|
||||
'date' => 'date:Y-m-d',
|
||||
'submitted_by' => 'integer',
|
||||
'published_by' => 'integer',
|
||||
'reopened_by' => 'integer',
|
||||
'submitted_at' => 'datetime',
|
||||
'published_at' => 'datetime',
|
||||
'auto_publish_at' => 'datetime',
|
||||
'reopened_at' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
/* ============================================================
|
||||
* Helpers
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* Legacy helper kept for compatibility.
|
||||
* True iff this (section, date, term) is hard-locked for everyone.
|
||||
* Treats 'published' (new) and 'finalized' (old) 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 (Builder $w) {
|
||||
$w->where('status', 'published')
|
||||
->orWhere('status', 'finalized'); // tolerate legacy data
|
||||
});
|
||||
|
||||
if ($semester !== null) $q->where('semester', $semester);
|
||||
if ($schoolYear !== null) $q->where('school_year', $schoolYear);
|
||||
|
||||
return $q->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a day row by (section, date, term). Returns model|null.
|
||||
*/
|
||||
public static function findBySectionDate(
|
||||
int $classSectionId,
|
||||
string $date,
|
||||
?string $semester,
|
||||
?string $schoolYear
|
||||
): ?self {
|
||||
return static::query()
|
||||
->where([
|
||||
'class_section_id' => $classSectionId,
|
||||
'date' => $date,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
])->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the draft row for (section,date,term), creating it if missing.
|
||||
* Relies on the unique key (class_section_id, date, semester, school_year) to prevent duplicates.
|
||||
*/
|
||||
public static function getOrCreateDraft(
|
||||
int $classSectionId,
|
||||
string $date,
|
||||
?string $semester,
|
||||
?string $schoolYear,
|
||||
int $userId = 0
|
||||
): self {
|
||||
$now = CarbonImmutable::now('UTC');
|
||||
|
||||
// firstOrCreate is already race-safe with a DB unique index:
|
||||
// if two requests race, one insert wins; the other re-queries.
|
||||
return static::query()->firstOrCreate(
|
||||
[
|
||||
'class_section_id' => $classSectionId,
|
||||
'date' => $date,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
],
|
||||
[
|
||||
'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,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Prior code used "finalize" to lock immediately.
|
||||
* In the new workflow, "finalize" means "teacher submit".
|
||||
*/
|
||||
public function finalize(int $userId): bool
|
||||
{
|
||||
return $this->submit($userId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Teacher submit: status => submitted (teacher locked, admin editable).
|
||||
* Optionally set auto_publish_at.
|
||||
*/
|
||||
public function submit(int $userId, ?string $autoPublishAt = null): bool
|
||||
{
|
||||
$now = CarbonImmutable::now('UTC');
|
||||
|
||||
$this->fill([
|
||||
'status' => 'submitted',
|
||||
'submitted_by' => $userId,
|
||||
'submitted_at' => $now,
|
||||
'auto_publish_at' => $autoPublishAt,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin publish (hard lock): status => published.
|
||||
*/
|
||||
public function publish(int $userId): bool
|
||||
{
|
||||
$now = CarbonImmutable::now('UTC');
|
||||
|
||||
$this->fill([
|
||||
'status' => 'published',
|
||||
'published_by' => $userId,
|
||||
'published_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
return $this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin reopen a submitted/published 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 = CarbonImmutable::now('UTC');
|
||||
|
||||
$this->fill([
|
||||
'status' => $toStatus,
|
||||
'reopened_by' => $userId,
|
||||
'reopened_at' => $now,
|
||||
'reopen_reason' => $reason,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
return $this->save();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user