reconstruction of the project
This commit is contained in:
+137
-39
@@ -2,14 +2,19 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Models\BaseModel;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class Staff extends BaseModel
|
||||
{
|
||||
protected $table = 'staff';
|
||||
protected $primaryKey = 'id';
|
||||
protected $useAutoIncrement = true;
|
||||
protected $useSoftDeletes = false; // We're handling 'inactive' via active_role column
|
||||
|
||||
/**
|
||||
* CI: timestamps managed manually (created_at/updated_at set by caller/controller)
|
||||
*/
|
||||
public $timestamps = true;
|
||||
|
||||
protected $fillable = [
|
||||
'firstname',
|
||||
'lastname',
|
||||
@@ -23,77 +28,170 @@ class Staff extends BaseModel
|
||||
'user_id',
|
||||
];
|
||||
|
||||
public $timestamps = true; // Managed manually in controller
|
||||
protected $casts = [
|
||||
'user_id' => 'integer',
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function getActiveStaff()
|
||||
/* ============================================================
|
||||
* Relationships (optional)
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->where('active_role !=', 'inactive')
|
||||
->orderBy('created_at', 'DESC')
|
||||
->findAll();
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
public function getInactiveStaff()
|
||||
/* ============================================================
|
||||
* Scopes (nice for queries)
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
public function scopeActive(Builder $q): Builder
|
||||
{
|
||||
return $this->where('active_role', 'inactive')
|
||||
->orderBy('updated_at', 'DESC')
|
||||
->findAll();
|
||||
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);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* CI-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).
|
||||
* Ensures created_at is only set on insert and updated_at can be provided by caller.
|
||||
* - 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 function upsert(array $data): bool
|
||||
public static function upsertStaff(array $data): ?self
|
||||
{
|
||||
if (!isset($data['user_id'])) {
|
||||
return false;
|
||||
if (empty($data['user_id'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If school_year not provided, try to keep existing or fall back to current year string
|
||||
$schoolYear = $data['school_year'] ?? null;
|
||||
$userId = (int) $data['user_id'];
|
||||
|
||||
// Resolve school_year fallback like your CI logic
|
||||
$schoolYear = $data['school_year'] ?? null;
|
||||
if ($schoolYear === null) {
|
||||
// Try to find any existing row by user_id to reuse its school_year
|
||||
$existingAny = $this->where('user_id', $data['user_id'])->orderBy('id', 'DESC')->first();
|
||||
if ($existingAny && isset($existingAny['school_year'])) {
|
||||
$schoolYear = $existingAny['school_year'];
|
||||
$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 = $this->where('user_id', $data['user_id'])
|
||||
->where('school_year', $schoolYear)
|
||||
->first();
|
||||
$existing = static::query()
|
||||
->where('user_id', $userId)
|
||||
->where('school_year', (string) $schoolYear)
|
||||
->first();
|
||||
} else {
|
||||
// If no school_year, treat (user_id) as key
|
||||
$existing = $this->where('user_id', $data['user_id'])->first();
|
||||
$existing = static::query()
|
||||
->where('user_id', $userId)
|
||||
->first();
|
||||
}
|
||||
|
||||
$now = utc_now();
|
||||
$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 (!isset($data['created_at']) && isset($existing['created_at'])) {
|
||||
$data['created_at'] = $existing['created_at'];
|
||||
if (!array_key_exists('created_at', $payload) && $existing->created_at) {
|
||||
$payload['created_at'] = $existing->created_at;
|
||||
}
|
||||
// Ensure updated_at exists
|
||||
if (!isset($data['updated_at'])) {
|
||||
$data['updated_at'] = $now;
|
||||
if (!array_key_exists('updated_at', $payload)) {
|
||||
$payload['updated_at'] = $now;
|
||||
}
|
||||
return $this->update($existing['id'], $data);
|
||||
|
||||
$existing->fill($payload);
|
||||
$existing->save();
|
||||
|
||||
return $existing;
|
||||
}
|
||||
|
||||
// New row — set created_at/updated_at if not provided
|
||||
if (!isset($data['created_at'])) {
|
||||
$data['created_at'] = $now;
|
||||
// Insert new row — set created_at/updated_at if not provided
|
||||
if (!array_key_exists('created_at', $payload)) {
|
||||
$payload['created_at'] = $now;
|
||||
}
|
||||
if (!isset($data['updated_at'])) {
|
||||
$data['updated_at'] = $now;
|
||||
if (!array_key_exists('updated_at', $payload)) {
|
||||
$payload['updated_at'] = $now;
|
||||
}
|
||||
|
||||
return $this->insert($data) !== false;
|
||||
return static::query()->create($payload);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CI-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'],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user