Initial commit: Aplikasi Ketertiban Siswa
- Fitur: input pelanggaran, sistem poin, surat peringatan otomatis, SP progress - Realtime notifikasi via Laravel Reverb + Echo - Dashboard statistik, manajemen user, manajemen master data - Login 2 kolom premium, user dropdown, pengaturan akun - Tema biru kalem, logo sekolah dinamis, sidebar brand dinamis - Sinkronisasi siswa dari Database Kesiswaan via API
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class AppNotification extends Model
|
||||
{
|
||||
protected $table = 'notifications';
|
||||
|
||||
protected $fillable = [
|
||||
'user_id', 'type', 'title', 'body', 'data',
|
||||
'icon', 'color', 'action_url', 'is_read',
|
||||
'read_at', 'violation_id', 'sp_letter_id',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'data' => 'json',
|
||||
'is_read' => 'boolean',
|
||||
'read_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function violation()
|
||||
{
|
||||
return $this->belongsTo(Violation::class);
|
||||
}
|
||||
|
||||
public function spLetter()
|
||||
{
|
||||
return $this->belongsTo(SpLetter::class, 'sp_letter_id');
|
||||
}
|
||||
|
||||
public function scopeUnread($query)
|
||||
{
|
||||
return $query->where('is_read', false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Classes extends Model
|
||||
{
|
||||
protected $table = 'classes';
|
||||
|
||||
protected $fillable = [
|
||||
'source_id', 'name', 'level', 'department_code',
|
||||
'department_name', 'academic_year_name', 'is_active',
|
||||
'metadata',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_active' => 'boolean',
|
||||
'metadata' => 'json',
|
||||
];
|
||||
}
|
||||
|
||||
public function students()
|
||||
{
|
||||
return $this->hasMany(Student::class, 'class_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Setting extends Model
|
||||
{
|
||||
protected $fillable = ['key', 'value', 'group', 'description'];
|
||||
|
||||
public static function getValue(string $key, mixed $default = null): mixed
|
||||
{
|
||||
$setting = static::where('key', $key)->first();
|
||||
return $setting ? $setting->value : $default;
|
||||
}
|
||||
|
||||
public static function setValue(string $key, mixed $value, string $group = 'general', ?string $description = null): void
|
||||
{
|
||||
static::updateOrCreate(
|
||||
['key' => $key],
|
||||
['value' => $value, 'group' => $group, 'description' => $description]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SpLetter extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'student_id', 'sp_threshold_id', 'generated_by',
|
||||
'letter_number', 'title', 'body', 'total_points_at_time',
|
||||
'violations_included', 'status', 'file_path',
|
||||
'printed_at', 'delivered_at',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'total_points_at_time' => 'integer',
|
||||
'violations_included' => 'json',
|
||||
'printed_at' => 'datetime',
|
||||
'delivered_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function student()
|
||||
{
|
||||
return $this->belongsTo(Student::class);
|
||||
}
|
||||
|
||||
public function spThreshold()
|
||||
{
|
||||
return $this->belongsTo(SpThreshold::class, 'sp_threshold_id');
|
||||
}
|
||||
|
||||
public function generator()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'generated_by');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SpThreshold extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'name', 'slug', 'min_points', 'max_points',
|
||||
'color', 'default_description', 'is_active',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'min_points' => 'integer',
|
||||
'max_points' => 'integer',
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function spLetters()
|
||||
{
|
||||
return $this->hasMany(SpLetter::class, 'sp_threshold_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Student extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'source_id', 'nisn', 'student_number', 'full_name',
|
||||
'gender', 'place_of_birth', 'date_of_birth', 'address',
|
||||
'phone_number', 'email', 'class_name', 'class_level',
|
||||
'department_code', 'department_name', 'academic_year_name',
|
||||
'status', 'photo_path', 'class_id', 'is_active',
|
||||
'metadata', 'synced_at',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'date_of_birth' => 'date',
|
||||
'is_active' => 'boolean',
|
||||
'metadata' => 'json',
|
||||
'synced_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
public function violations(): HasMany
|
||||
{
|
||||
return $this->hasMany(Violation::class);
|
||||
}
|
||||
|
||||
public function spLetters(): HasMany
|
||||
{
|
||||
return $this->hasMany(SpLetter::class);
|
||||
}
|
||||
|
||||
public function class()
|
||||
{
|
||||
return $this->belongsTo(Classes::class, 'class_id');
|
||||
}
|
||||
|
||||
public function getTotalPointsAttribute(): int
|
||||
{
|
||||
return $this->violations()
|
||||
->whereNull('deleted_at')
|
||||
->sum('points');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasFactory, Notifiable;
|
||||
|
||||
protected $fillable = [
|
||||
'name', 'username', 'email', 'password', 'role', 'is_active',
|
||||
];
|
||||
|
||||
protected $hidden = ['password', 'remember_token'];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
'is_active' => 'boolean',
|
||||
];
|
||||
}
|
||||
|
||||
public function isAdmin(): bool { return $this->role === 'admin'; }
|
||||
public function isBK(): bool { return $this->role === 'bk'; }
|
||||
public function isWaliKelas(): bool { return $this->role === 'wali_kelas'; }
|
||||
|
||||
public function recordedViolations()
|
||||
{
|
||||
return $this->hasMany(Violation::class, 'recorded_by');
|
||||
}
|
||||
|
||||
public function appNotifications()
|
||||
{
|
||||
return $this->hasMany(AppNotification::class, 'user_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
class Violation extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = [
|
||||
'student_id', 'violation_type_id', 'recorded_by',
|
||||
'description', 'points', 'sanction', 'location',
|
||||
'violation_date', 'violation_time',
|
||||
'is_verified', 'verified_by', 'verified_at',
|
||||
'notes',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'violation_date' => 'date',
|
||||
'violation_time' => 'datetime:H:i',
|
||||
'is_verified' => 'boolean',
|
||||
'verified_at' => 'datetime',
|
||||
'points' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function student(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Student::class);
|
||||
}
|
||||
|
||||
public function violationType(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ViolationType::class, 'violation_type_id');
|
||||
}
|
||||
|
||||
public function recorder(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'recorded_by');
|
||||
}
|
||||
|
||||
public function verifier(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'verified_by');
|
||||
}
|
||||
|
||||
public function evidences(): HasMany
|
||||
{
|
||||
return $this->hasMany(ViolationEvidence::class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ViolationCategory extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'name', 'slug', 'color', 'description', 'sort_order', 'is_active',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_active' => 'boolean',
|
||||
'sort_order' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function violationTypes()
|
||||
{
|
||||
return $this->hasMany(ViolationType::class, 'category_id');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ViolationEvidence extends Model
|
||||
{
|
||||
protected $table = 'violation_evidences';
|
||||
|
||||
protected $fillable = [
|
||||
'violation_id', 'file_path', 'original_name', 'file_size', 'mime_type',
|
||||
];
|
||||
|
||||
public function violation()
|
||||
{
|
||||
return $this->belongsTo(Violation::class);
|
||||
}
|
||||
|
||||
public function getUrlAttribute(): string
|
||||
{
|
||||
return Storage::url($this->file_path);
|
||||
}
|
||||
|
||||
public function getThumbnailUrlAttribute(): string
|
||||
{
|
||||
return Storage::url($this->file_path);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ViolationType extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'category_id', 'name', 'slug', 'points',
|
||||
'default_sanction', 'description', 'is_active',
|
||||
];
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_active' => 'boolean',
|
||||
'points' => 'integer',
|
||||
];
|
||||
}
|
||||
|
||||
public function category()
|
||||
{
|
||||
return $this->belongsTo(ViolationCategory::class, 'category_id');
|
||||
}
|
||||
|
||||
public function violations()
|
||||
{
|
||||
return $this->hasMany(Violation::class, 'violation_type_id');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user