first commit
This commit is contained in:
44
app/Models/AppSetting.php
Normal file
44
app/Models/AppSetting.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class AppSetting extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'key',
|
||||
'value',
|
||||
'type',
|
||||
'group',
|
||||
'label',
|
||||
'description',
|
||||
];
|
||||
|
||||
public static function get(string $key, $default = null)
|
||||
{
|
||||
$setting = Cache::remember("setting.$key", 3600, fn () => static::where('key', $key)->first());
|
||||
|
||||
if (! $setting) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return match ($setting->type) {
|
||||
'integer' => (int) $setting->value,
|
||||
'boolean' => filter_var($setting->value, FILTER_VALIDATE_BOOLEAN),
|
||||
default => $setting->value,
|
||||
};
|
||||
}
|
||||
|
||||
public static function set(string $key, $value): void
|
||||
{
|
||||
static::where('key', $key)->update(['value' => $value]);
|
||||
Cache::forget("setting.$key");
|
||||
}
|
||||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::saved(fn ($m) => Cache::forget("setting.{$m->key}"));
|
||||
}
|
||||
}
|
||||
41
app/Models/ChecklistFormula.php
Normal file
41
app/Models/ChecklistFormula.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class ChecklistFormula extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'checklist_template_id',
|
||||
'checklist_section_id',
|
||||
'result_token',
|
||||
'label',
|
||||
'expression',
|
||||
'unit',
|
||||
'guard_div_zero',
|
||||
'order',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'guard_div_zero' => 'boolean',
|
||||
'order' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function template(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistTemplate::class, 'checklist_template_id');
|
||||
}
|
||||
|
||||
public function section(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistSection::class, 'checklist_section_id');
|
||||
}
|
||||
}
|
||||
69
app/Models/ChecklistItem.php
Normal file
69
app/Models/ChecklistItem.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class ChecklistItem extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public const INPUT_TYPES = [
|
||||
'number' => 'Nombor',
|
||||
'text' => 'Teks',
|
||||
'textarea' => 'Teks Panjang',
|
||||
'select' => 'Senarai Pilihan',
|
||||
'checkbox' => 'Kotak Semak',
|
||||
'file_reference' => 'Rujukan Fail',
|
||||
'calculated' => 'Dikira Automatik',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'checklist_section_id',
|
||||
'checklist_scope_id',
|
||||
'code',
|
||||
'formula_token',
|
||||
'label',
|
||||
'description',
|
||||
'input_type',
|
||||
'options',
|
||||
'unit',
|
||||
'is_required',
|
||||
'is_calculated',
|
||||
'formula',
|
||||
'order',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'options' => 'array',
|
||||
'is_required' => 'boolean',
|
||||
'is_calculated' => 'boolean',
|
||||
'order' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function section(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistSection::class, 'checklist_section_id');
|
||||
}
|
||||
|
||||
public function scope(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistScope::class, 'checklist_scope_id');
|
||||
}
|
||||
|
||||
public function answers(): HasMany
|
||||
{
|
||||
return $this->hasMany(SubmissionAnswer::class);
|
||||
}
|
||||
|
||||
public function isNumeric(): bool
|
||||
{
|
||||
return in_array($this->input_type, ['number', 'calculated'], true);
|
||||
}
|
||||
}
|
||||
38
app/Models/ChecklistScope.php
Normal file
38
app/Models/ChecklistScope.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class ChecklistScope extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'checklist_section_id',
|
||||
'code',
|
||||
'title',
|
||||
'description',
|
||||
'order',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'order' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function section(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistSection::class, 'checklist_section_id');
|
||||
}
|
||||
|
||||
public function items(): HasMany
|
||||
{
|
||||
return $this->hasMany(ChecklistItem::class)->orderBy('order');
|
||||
}
|
||||
}
|
||||
50
app/Models/ChecklistSection.php
Normal file
50
app/Models/ChecklistSection.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class ChecklistSection extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'checklist_template_id',
|
||||
'code',
|
||||
'title',
|
||||
'description',
|
||||
'order',
|
||||
'is_formula_enabled',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_formula_enabled' => 'boolean',
|
||||
'order' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function template(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistTemplate::class, 'checklist_template_id');
|
||||
}
|
||||
|
||||
public function scopes(): HasMany
|
||||
{
|
||||
return $this->hasMany(ChecklistScope::class)->orderBy('order');
|
||||
}
|
||||
|
||||
public function items(): HasMany
|
||||
{
|
||||
return $this->hasMany(ChecklistItem::class)->orderBy('order');
|
||||
}
|
||||
|
||||
public function formula(): HasMany
|
||||
{
|
||||
return $this->hasMany(ChecklistFormula::class);
|
||||
}
|
||||
}
|
||||
47
app/Models/ChecklistTemplate.php
Normal file
47
app/Models/ChecklistTemplate.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class ChecklistTemplate extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'version',
|
||||
'description',
|
||||
'is_active',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function sections(): HasMany
|
||||
{
|
||||
return $this->hasMany(ChecklistSection::class)->orderBy('order');
|
||||
}
|
||||
|
||||
public function formulas(): HasMany
|
||||
{
|
||||
return $this->hasMany(ChecklistFormula::class)->orderBy('order');
|
||||
}
|
||||
|
||||
public function scopeActive($query)
|
||||
{
|
||||
return $query->where('is_active', true);
|
||||
}
|
||||
|
||||
public static function activeTemplate(): ?self
|
||||
{
|
||||
return static::active()->latest('id')->first();
|
||||
}
|
||||
}
|
||||
68
app/Models/Consultant.php
Normal file
68
app/Models/Consultant.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Spatie\Activitylog\Support\LogOptions;
|
||||
use Spatie\Activitylog\Models\Concerns\LogsActivity;
|
||||
|
||||
class Consultant extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes, LogsActivity;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'nama_perunding',
|
||||
'no_pendaftaran_syarikat',
|
||||
'alamat',
|
||||
'emel',
|
||||
'telefon',
|
||||
'aktif',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'aktif' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnly(['nama_perunding', 'no_pendaftaran_syarikat', 'emel', 'telefon', 'aktif', 'user_id'])
|
||||
->logOnlyDirty()
|
||||
->dontLogEmptyChanges()
|
||||
->useLogName('perunding');
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/** Pusat data yang sedang ditugaskan kepada perunding ini. */
|
||||
public function dataCentres(): HasMany
|
||||
{
|
||||
return $this->hasMany(DataCentre::class, 'current_consultant_id');
|
||||
}
|
||||
|
||||
public function assignments(): HasMany
|
||||
{
|
||||
return $this->hasMany(DataCentreConsultantAssignment::class);
|
||||
}
|
||||
|
||||
public function submissions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Submission::class);
|
||||
}
|
||||
|
||||
public function scopeAktif($query)
|
||||
{
|
||||
return $query->where('aktif', true);
|
||||
}
|
||||
}
|
||||
69
app/Models/DataCentre.php
Normal file
69
app/Models/DataCentre.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Spatie\Activitylog\Support\LogOptions;
|
||||
use Spatie\Activitylog\Models\Concerns\LogsActivity;
|
||||
|
||||
class DataCentre extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes, LogsActivity;
|
||||
|
||||
protected $fillable = [
|
||||
'nama_pusat_data',
|
||||
'tajuk_permohonan',
|
||||
'lokasi_pusat_data',
|
||||
'alamat',
|
||||
'keluasan_tapak',
|
||||
'it_load',
|
||||
'status',
|
||||
'current_consultant_id',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'keluasan_tapak' => 'decimal:2',
|
||||
'it_load' => 'decimal:2',
|
||||
];
|
||||
}
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnly(['nama_pusat_data', 'tajuk_permohonan', 'status', 'current_consultant_id', 'it_load', 'keluasan_tapak'])
|
||||
->logOnlyDirty()
|
||||
->dontLogEmptyChanges()
|
||||
->useLogName('pusat_data');
|
||||
}
|
||||
|
||||
public function currentConsultant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Consultant::class, 'current_consultant_id');
|
||||
}
|
||||
|
||||
public function assignments(): HasMany
|
||||
{
|
||||
return $this->hasMany(DataCentreConsultantAssignment::class)->latest('start_date');
|
||||
}
|
||||
|
||||
public function activeAssignment()
|
||||
{
|
||||
return $this->hasOne(DataCentreConsultantAssignment::class)->where('is_active', true);
|
||||
}
|
||||
|
||||
public function submissions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Submission::class);
|
||||
}
|
||||
|
||||
public function scopeAktif($query)
|
||||
{
|
||||
return $query->where('status', 'aktif');
|
||||
}
|
||||
}
|
||||
46
app/Models/DataCentreConsultantAssignment.php
Normal file
46
app/Models/DataCentreConsultantAssignment.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class DataCentreConsultantAssignment extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'data_centre_id',
|
||||
'consultant_id',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'reason',
|
||||
'assigned_by',
|
||||
'is_active',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'start_date' => 'date',
|
||||
'end_date' => 'date',
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function dataCentre(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DataCentre::class);
|
||||
}
|
||||
|
||||
public function consultant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Consultant::class);
|
||||
}
|
||||
|
||||
public function assignedBy(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'assigned_by');
|
||||
}
|
||||
}
|
||||
77
app/Models/ReportingCycle.php
Normal file
77
app/Models/ReportingCycle.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Spatie\Activitylog\Support\LogOptions;
|
||||
use Spatie\Activitylog\Models\Concerns\LogsActivity;
|
||||
|
||||
class ReportingCycle extends Model
|
||||
{
|
||||
use HasFactory, LogsActivity;
|
||||
|
||||
protected $fillable = [
|
||||
'renewal_year',
|
||||
'reporting_year',
|
||||
'period_start',
|
||||
'period_end',
|
||||
'cut_off_date',
|
||||
'licence_period_year',
|
||||
'checklist_template_id',
|
||||
'status',
|
||||
'catatan',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'renewal_year' => 'integer',
|
||||
'reporting_year' => 'integer',
|
||||
'period_start' => 'date',
|
||||
'period_end' => 'date',
|
||||
'cut_off_date' => 'date',
|
||||
'licence_period_year' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Peraturan perniagaan: tahun pelaporan = tahun pembaharuan - 2.
|
||||
* Cth: pembaharuan 2028 => pelaporan 2026.
|
||||
*/
|
||||
public static function reportingYearFor(int $renewalYear): int
|
||||
{
|
||||
return $renewalYear - 2;
|
||||
}
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnly(['renewal_year', 'reporting_year', 'cut_off_date', 'status'])
|
||||
->logOnlyDirty()
|
||||
->dontLogEmptyChanges()
|
||||
->useLogName('kitaran_pelaporan');
|
||||
}
|
||||
|
||||
public function checklistTemplate(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistTemplate::class);
|
||||
}
|
||||
|
||||
public function submissions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Submission::class);
|
||||
}
|
||||
|
||||
public function scopeAktif($query)
|
||||
{
|
||||
return $query->where('status', 'aktif');
|
||||
}
|
||||
|
||||
public function isOverdue(): bool
|
||||
{
|
||||
return $this->cut_off_date && now()->startOfDay()->gt($this->cut_off_date);
|
||||
}
|
||||
}
|
||||
152
app/Models/Submission.php
Normal file
152
app/Models/Submission.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Spatie\Activitylog\Support\LogOptions;
|
||||
use Spatie\Activitylog\Models\Concerns\LogsActivity;
|
||||
|
||||
class Submission extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes, LogsActivity;
|
||||
|
||||
public const STATUSES = [
|
||||
'draf' => 'Draf',
|
||||
'baru' => 'Baru',
|
||||
'dalam_tindakan' => 'Dalam Tindakan',
|
||||
'pembetulan_perunding' => 'Pembetulan Perunding',
|
||||
'selesai' => 'Selesai',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'data_centre_id',
|
||||
'reporting_cycle_id',
|
||||
'consultant_id',
|
||||
'checklist_template_id',
|
||||
'status',
|
||||
'is_locked',
|
||||
'locked_by',
|
||||
'locked_at',
|
||||
'lock_reason',
|
||||
'assigned_officer_id',
|
||||
'hardcopy_received',
|
||||
'hardcopy_received_date',
|
||||
'hardcopy_sent_date',
|
||||
'submitted_at',
|
||||
'submitted_by',
|
||||
'review_notes',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_locked' => 'boolean',
|
||||
'locked_at' => 'datetime',
|
||||
'hardcopy_received' => 'boolean',
|
||||
'hardcopy_received_date' => 'date',
|
||||
'hardcopy_sent_date' => 'date',
|
||||
'submitted_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnly(['status', 'is_locked', 'assigned_officer_id', 'hardcopy_received', 'hardcopy_sent_date'])
|
||||
->logOnlyDirty()
|
||||
->dontLogEmptyChanges()
|
||||
->useLogName('serahan');
|
||||
}
|
||||
|
||||
public function dataCentre(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DataCentre::class);
|
||||
}
|
||||
|
||||
public function reportingCycle(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ReportingCycle::class);
|
||||
}
|
||||
|
||||
public function consultant(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Consultant::class);
|
||||
}
|
||||
|
||||
public function checklistTemplate(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistTemplate::class);
|
||||
}
|
||||
|
||||
public function assignedOfficer(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'assigned_officer_id');
|
||||
}
|
||||
|
||||
public function answers(): HasMany
|
||||
{
|
||||
return $this->hasMany(SubmissionAnswer::class);
|
||||
}
|
||||
|
||||
public function results(): HasMany
|
||||
{
|
||||
return $this->hasMany(SubmissionResult::class);
|
||||
}
|
||||
|
||||
public function documents(): HasMany
|
||||
{
|
||||
return $this->hasMany(SubmissionDocument::class)->orderByDesc('version');
|
||||
}
|
||||
|
||||
public function activeDocument(): HasOne
|
||||
{
|
||||
return $this->hasOne(SubmissionDocument::class)->where('is_active', true);
|
||||
}
|
||||
|
||||
public function statusHistories(): HasMany
|
||||
{
|
||||
return $this->hasMany(SubmissionStatusHistory::class)->latest();
|
||||
}
|
||||
|
||||
public function correctionRequests(): HasMany
|
||||
{
|
||||
return $this->hasMany(SubmissionCorrectionRequest::class)->latest();
|
||||
}
|
||||
|
||||
public function comments(): HasMany
|
||||
{
|
||||
return $this->hasMany(SubmissionComment::class)->oldest();
|
||||
}
|
||||
|
||||
/** Perunding boleh edit selagi belum dikunci dan belum selesai. */
|
||||
public function isEditableByConsultant(): bool
|
||||
{
|
||||
return ! $this->is_locked && $this->status !== 'selesai';
|
||||
}
|
||||
|
||||
public function isSubmitted(): bool
|
||||
{
|
||||
return ! in_array($this->status, ['draf'], true);
|
||||
}
|
||||
|
||||
public function statusLabel(): string
|
||||
{
|
||||
return self::STATUSES[$this->status] ?? $this->status;
|
||||
}
|
||||
|
||||
public function statusBadgeClass(): string
|
||||
{
|
||||
return [
|
||||
'draf' => 'secondary',
|
||||
'baru' => 'info',
|
||||
'dalam_tindakan' => 'primary',
|
||||
'pembetulan_perunding' => 'warning',
|
||||
'selesai' => 'success',
|
||||
][$this->status] ?? 'secondary';
|
||||
}
|
||||
}
|
||||
38
app/Models/SubmissionAnswer.php
Normal file
38
app/Models/SubmissionAnswer.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class SubmissionAnswer extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'submission_id',
|
||||
'checklist_item_id',
|
||||
'value',
|
||||
'unit',
|
||||
'page_reference',
|
||||
'consultant_note',
|
||||
'officer_note',
|
||||
'validation_status',
|
||||
];
|
||||
|
||||
public function submission(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Submission::class);
|
||||
}
|
||||
|
||||
public function item(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistItem::class, 'checklist_item_id');
|
||||
}
|
||||
|
||||
public function numericValue(): ?float
|
||||
{
|
||||
return is_numeric($this->value) ? (float) $this->value : null;
|
||||
}
|
||||
}
|
||||
40
app/Models/SubmissionComment.php
Normal file
40
app/Models/SubmissionComment.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class SubmissionComment extends Model
|
||||
{
|
||||
use HasFactory, SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'submission_id',
|
||||
'user_id',
|
||||
'body',
|
||||
'is_internal',
|
||||
'attachment_path',
|
||||
'attachment_name',
|
||||
'deleted_by',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_internal' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function submission(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Submission::class);
|
||||
}
|
||||
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
61
app/Models/SubmissionCorrectionRequest.php
Normal file
61
app/Models/SubmissionCorrectionRequest.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class SubmissionCorrectionRequest extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public const STATUSES = [
|
||||
'terbuka' => 'Terbuka',
|
||||
'dijawab' => 'Dijawab',
|
||||
'selesai' => 'Selesai',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'submission_id',
|
||||
'checklist_item_id',
|
||||
'page_reference',
|
||||
'location',
|
||||
'description',
|
||||
'status',
|
||||
'consultant_response',
|
||||
'responded_at',
|
||||
'responded_by',
|
||||
'created_by',
|
||||
'resolved_at',
|
||||
'resolved_by',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'responded_at' => 'datetime',
|
||||
'resolved_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function submission(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Submission::class);
|
||||
}
|
||||
|
||||
public function item(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ChecklistItem::class, 'checklist_item_id');
|
||||
}
|
||||
|
||||
public function createdBy(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'created_by');
|
||||
}
|
||||
|
||||
public function respondedBy(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'responded_by');
|
||||
}
|
||||
}
|
||||
56
app/Models/SubmissionDocument.php
Normal file
56
app/Models/SubmissionDocument.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class SubmissionDocument extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'submission_id',
|
||||
'original_filename',
|
||||
'stored_path',
|
||||
'file_hash',
|
||||
'mime_type',
|
||||
'size',
|
||||
'version',
|
||||
'is_active',
|
||||
'uploaded_by',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_active' => 'boolean',
|
||||
'size' => 'integer',
|
||||
'version' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function submission(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Submission::class);
|
||||
}
|
||||
|
||||
public function uploadedBy(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'uploaded_by');
|
||||
}
|
||||
|
||||
public function humanSize(): string
|
||||
{
|
||||
$bytes = (int) $this->size;
|
||||
if ($bytes >= 1048576) {
|
||||
return round($bytes / 1048576, 2).' MB';
|
||||
}
|
||||
if ($bytes >= 1024) {
|
||||
return round($bytes / 1024, 2).' KB';
|
||||
}
|
||||
|
||||
return $bytes.' B';
|
||||
}
|
||||
}
|
||||
32
app/Models/SubmissionResult.php
Normal file
32
app/Models/SubmissionResult.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class SubmissionResult extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'submission_id',
|
||||
'result_token',
|
||||
'label',
|
||||
'value',
|
||||
'unit',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'value' => 'decimal:4',
|
||||
];
|
||||
}
|
||||
|
||||
public function submission(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Submission::class);
|
||||
}
|
||||
}
|
||||
30
app/Models/SubmissionStatusHistory.php
Normal file
30
app/Models/SubmissionStatusHistory.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class SubmissionStatusHistory extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'submission_id',
|
||||
'from_status',
|
||||
'to_status',
|
||||
'changed_by',
|
||||
'notes',
|
||||
];
|
||||
|
||||
public function submission(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Submission::class);
|
||||
}
|
||||
|
||||
public function changedBy(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'changed_by');
|
||||
}
|
||||
}
|
||||
72
app/Models/User.php
Normal file
72
app/Models/User.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Spatie\Activitylog\Support\LogOptions;
|
||||
use Spatie\Activitylog\Models\Concerns\LogsActivity;
|
||||
use Spatie\Permission\Traits\HasRoles;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasFactory, Notifiable, HasRoles, SoftDeletes, LogsActivity;
|
||||
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'email',
|
||||
'password',
|
||||
'phone',
|
||||
'jawatan',
|
||||
'is_active',
|
||||
];
|
||||
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults()
|
||||
->logOnly(['name', 'email', 'phone', 'jawatan', 'is_active'])
|
||||
->logOnlyDirty()
|
||||
->dontLogEmptyChanges()
|
||||
->useLogName('pengguna');
|
||||
}
|
||||
|
||||
public function consultant(): HasOne
|
||||
{
|
||||
return $this->hasOne(Consultant::class);
|
||||
}
|
||||
|
||||
public function assignedSubmissions(): HasMany
|
||||
{
|
||||
return $this->hasMany(Submission::class, 'assigned_officer_id');
|
||||
}
|
||||
|
||||
/** Adakah pengguna ini seorang perunding. */
|
||||
public function isPerunding(): bool
|
||||
{
|
||||
return $this->hasRole('Perunding');
|
||||
}
|
||||
|
||||
/** Adakah pengguna ini kakitangan JPP (bukan perunding). */
|
||||
public function isJpp(): bool
|
||||
{
|
||||
return $this->hasAnyRole(['Super Admin', 'JPP Admin', 'Pegawai JPP', 'Penolong Pegawai', 'Kerani']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user