Files
alrahma_sunday_school_api/app/Models/Staff.php
T
2026-06-09 01:25:14 -04:00

210 lines
6.4 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Staff extends BaseModel
{
protected $table = 'staff';
/**
* legacy: timestamps managed manually (created_at/updated_at set by caller/controller)
*/
public $timestamps = false;
protected $fillable = [
'user_id',
'firstname',
'lastname',
'email',
'phone',
'role_name',
'active_role',
'status',
'school_year',
'created_at',
'updated_at',
];
protected $casts = [
'user_id' => 'integer',
'created_at' => 'datetime',
'updated_at' => 'datetime',
];
/* ============================================================
* Relationships (optional)
* ============================================================
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
/* ============================================================
* Scopes (nice for queries)
* ============================================================
*/
public function scopeActive(Builder $q): Builder
{
return $q->where('active_role', '!=', 'inactive');
}
public function scopeInactive(Builder $q): Builder
{
return $q->where('active_role', '=', 'inactive');
}
public function scopeForSchoolYear(Builder $q, string $schoolYear): Builder
{
return $q->where('school_year', $schoolYear);
}
/* ============================================================
* legacy-compatible methods
* ============================================================
*/
public static function getActiveStaff(): array
{
return static::query()
->active()
->orderByDesc('created_at')
->get()
->all();
}
public static function getInactiveStaff(): array
{
return static::query()
->inactive()
->orderByDesc('updated_at')
->get()
->all();
}
/**
* Insert or update a staff row keyed by (user_id, school_year).
* - If school_year missing: reuse latest existing school_year for that user if available.
* - created_at is preserved on update (unless explicitly provided).
* - updated_at can be provided by caller; otherwise we set it.
*
* Returns the saved model or null if invalid.
*/
public static function upsertStaff(array $data): ?self
{
if (empty($data['user_id'])) {
return null;
}
$userId = (int) $data['user_id'];
// Resolve school_year fallback like your legacy logic
$schoolYear = $data['school_year'] ?? null;
if ($schoolYear === null) {
$existingAny = static::query()
->where('user_id', $userId)
->orderByDesc('id')
->first();
if ($existingAny && $existingAny->school_year) {
$schoolYear = (string) $existingAny->school_year;
$data['school_year'] = $schoolYear;
}
}
// Find existing by key
$existing = null;
if ($schoolYear !== null) {
$existing = static::query()
->where('user_id', $userId)
->where('school_year', (string) $schoolYear)
->first();
} else {
// If no school_year, treat (user_id) as key
$existing = static::query()
->where('user_id', $userId)
->first();
}
// The table enforces unique email addresses, so a user cannot safely
// have multiple staff rows across different school years with the same
// generated email. If an exact school-year row is missing but the user
// already has any staff row, update that existing row instead of trying
// to insert a duplicate-email record.
if (! $existing) {
$existing = static::query()
->where('user_id', $userId)
->orderByDesc('id')
->first();
}
$now = now(); // use UTC if app.timezone=UTC (recommended)
// Only allow fillable keys
$payload = array_intersect_key($data, array_flip((new static)->getFillable()));
if ($existing) {
// Preserve original created_at unless explicitly provided
if (! array_key_exists('created_at', $payload) && $existing->created_at) {
$payload['created_at'] = $existing->created_at;
}
// Ensure updated_at exists
if (! array_key_exists('updated_at', $payload)) {
$payload['updated_at'] = $now;
}
$existing->fill($payload);
$existing->save();
return $existing;
}
// Insert new row — set created_at/updated_at if not provided
if (! array_key_exists('created_at', $payload)) {
$payload['created_at'] = $now;
}
if (! array_key_exists('updated_at', $payload)) {
$payload['updated_at'] = $now;
}
return static::query()->create($payload);
}
/**
* legacy-compatible boolean wrapper if you want the same signature.
*/
public static function upsertBool(array $data): bool
{
return (bool) static::upsertStaff($data);
}
/* ============================================================
* Optional validation helper (FormRequest/controller)
* ============================================================
*/
public static function rules(bool $updating = false): array
{
$req = $updating ? 'sometimes' : 'required';
return [
'user_id' => [$req, 'integer', 'min:1', 'exists:users,id'],
'firstname' => ['nullable', 'string', 'max:120'],
'lastname' => ['nullable', 'string', 'max:120'],
'email' => ['nullable', 'email', 'max:255'],
'phone' => ['nullable', 'string', 'max:40'],
'role_name' => ['nullable', 'string', 'max:80'],
'active_role' => ['nullable', 'string', 'max:80'], // includes 'inactive'
'status' => ['nullable', 'string', 'max:40'],
'school_year' => ['nullable', 'string', 'max:20'],
'created_at' => ['nullable', 'date'],
'updated_at' => ['nullable', 'date'],
];
}
}