feat: initialize Dr-Panel project with patient file number support

This commit is contained in:
SajjadMahmoody
2026-05-06 02:18:23 +03:30
parent f8f174690a
commit 8b84d1780f
460 changed files with 113960 additions and 1 deletions
+33
View File
@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use Illuminate\Database\Eloquent\Model;
class Doctor extends Model
{
protected $fillable = [
'first_name',
'last_name',
'speciality',
'license_id',
'is_default',
];
protected function casts(): array
{
return [
'is_default' => 'boolean',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
public function getFullNameAttribute(): string
{
return $this->first_name . ' ' . $this->last_name;
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use Illuminate\Database\Eloquent\Model;
class LabTest extends Model
{
protected $fillable = [
'name',
'notes',
'is_default',
'is_active',
];
protected function casts(): array
{
return [
'is_default' => 'boolean',
'is_active' => 'boolean',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use Illuminate\Database\Eloquent\Model;
class Medication extends Model
{
protected $fillable = [
'name',
'dosage_form',
'strength',
'quantity',
'timing',
'notes',
'is_default',
'is_active',
];
protected function casts(): array
{
return [
'is_default' => 'boolean',
'is_active' => 'boolean',
'quantity' => 'integer',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
}
+35
View File
@@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use Illuminate\Database\Eloquent\Model;
class OsurgInitial extends Model
{
protected $fillable = [
'init_parameter',
'init_value',
'attachment',
];
protected function casts(): array
{
return [
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
public static function val(string $key, mixed $default = null): mixed
{
return cache()->remember(
"osurg_initial.{$key}",
60,
fn () => static::where('init_parameter', $key)->value('init_value') ?? $default
);
}
}
+105
View File
@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use App\Traits\HasUserStamps;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
class Patient extends Model
{
use HasUserStamps;
protected $fillable = [
'icno',
'first_name',
'last_name',
'father_name',
'gender',
'birth_date',
'age',
'marital_status',
'education',
'job',
'hand_phone',
'home_phone',
'work_phone',
'other_phone',
'home_address',
'work_address',
'refered_by',
'referal_reason',
'doc_id',
'insurance',
'insurance_no',
'blood_pressure',
'blood_sugar',
'current_illness_1',
'current_illness_2',
'is_undercare',
'undercare_reason',
'is_usingdrug',
'underdrug_reason',
'has_alergyto',
'alergy_reason',
'description',
'surgery_before',
'sergery_after',
'photos_before',
'photos_after',
'videos',
'audio_files',
];
protected function casts(): array
{
return [
'blood_pressure' => 'integer',
'blood_sugar' => 'integer',
'age' => 'integer',
'current_illness_1' => 'array',
'current_illness_2' => 'array',
'has_alergyto' => 'array',
'photos_before' => 'array',
'photos_after' => 'array',
'videos' => 'array',
'audio_files' => 'array',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
public function getFullNameAttribute(): string
{
return trim($this->first_name . ' ' . $this->last_name);
}
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
public function updator(): BelongsTo
{
return $this->belongsTo(User::class, 'updated_by');
}
public function surgeryAppointment(): HasOne
{
return $this->hasOne(SurgeryAppointment::class);
}
public function prescriptions(): HasMany
{
return $this->hasMany(Prescription::class, 'patient');
}
public function visits(): HasMany
{
return $this->hasMany(Visit::class, 'patient');
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use Illuminate\Database\Eloquent\Model;
class PatientIllness extends Model
{
protected $table = 'patient_illness';
protected $fillable = [
'illness',
'row_no',
'priority',
];
protected function casts(): array
{
return [
'row_no' => 'integer',
'priority' => 'integer',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use Illuminate\Database\Eloquent\Model;
class PaymentType extends Model
{
protected $fillable = [
'payment_type',
'account_no',
'pos_no',
'description',
];
protected function casts(): array
{
return [
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
}
+52
View File
@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use App\Traits\HasUserStamps;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Prescription extends Model
{
use HasUserStamps;
protected $fillable = [
'patient',
'issue_date',
'issue_datetime',
'doctor',
'medication_ids',
'lab_test_ids',
'content',
'lab_content',
];
protected function casts(): array
{
return [
'issue_datetime' => 'datetime',
'medication_ids' => 'array',
'lab_test_ids' => 'array',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
public function patientRecord(): BelongsTo
{
return $this->belongsTo(Patient::class, 'patient');
}
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
public function updator(): BelongsTo
{
return $this->belongsTo(User::class, 'updated_by');
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use App\Traits\HasUserStamps;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class SurgeryAppointment extends Model
{
use HasUserStamps;
protected $fillable = [
'patient_id',
'surgery_date',
'surgery_center_id',
];
protected function casts(): array
{
return [
'surgery_date' => 'datetime',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
public function patient(): BelongsTo
{
return $this->belongsTo(Patient::class);
}
public function surgeryCenter(): BelongsTo
{
return $this->belongsTo(SurgeryCenter::class);
}
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
public function updator(): BelongsTo
{
return $this->belongsTo(User::class, 'updated_by');
}
}
+28
View File
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use Illuminate\Database\Eloquent\Model;
class SurgeryCenter extends Model
{
protected $fillable = [
'name',
'address',
'phone',
'email',
'contact_person',
'description',
];
protected function casts(): array
{
return [
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
}
+63
View File
@@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SyncLog extends Model
{
public $timestamps = false;
protected $table = 'sync_log';
protected $fillable = [
'datetime',
'ip',
'user',
'table_name',
'action',
'record_id',
'changed_data',
];
protected $casts = [
'datetime' => 'datetime',
'changed_data' => 'array',
];
public static function lastSyncId(): int
{
return (int) static::where('action', 'synced')->max('id') ?: 0;
}
public static function changesSince(?string $since): \Illuminate\Database\Eloquent\Collection
{
$query = static::whereIn('action', ['created', 'updated', 'deleted'])
->orderBy('datetime')
->orderBy('id');
if ($since !== null && $since !== '') {
$query->where('datetime', '>', $since);
}
return $query->get();
}
protected function serializeDate(\DateTimeInterface $date): string
{
return $date->format('Y-m-d H:i:s');
}
public static function markSynced(string $ip): static
{
return static::create([
'datetime' => now(),
'ip' => $ip,
'user' => auth()->user()?->name ?? 'system',
'table_name' => '',
'action' => 'synced',
]);
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use Illuminate\Database\Eloquent\Model;
class Treatment extends Model
{
protected $fillable = [
'treatment_type',
'treatment_name',
'descriptions',
'treatment_cost',
];
protected function casts(): array
{
return [
'treatment_cost' => 'integer',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
}
+71
View File
@@ -0,0 +1,71 @@
<?php
namespace App\Models;
use App\Casts\JalaliDatetime;
use BezhanSalleh\FilamentShield\Traits\HasPanelShield;
use Database\Factories\UserFactory;
use Filament\Models\Contracts\HasAvatar;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable implements HasAvatar
{
use HasFactory, Notifiable, HasRoles, HasPanelShield;
protected $fillable = [
'name',
'username',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
public function getFilamentAvatarUrl(): ?string
{
$name = $this->name ?? $this->username ?? '?';
$initials = $this->getAvatarInitials($name);
$color = $this->getAvatarColor($name);
$svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">'
. '<circle cx="50" cy="50" r="50" fill="' . $color . '"/>'
. '<text x="50" y="50" font-size="38" text-anchor="middle" dominant-baseline="central" fill="white" font-family="Vazirmatn,Tahoma,sans-serif">' . $initials . '</text>'
. '</svg>';
return 'data:image/svg+xml;base64,' . base64_encode($svg);
}
private function getAvatarInitials(string $name): string
{
$words = preg_split('/\s+/', trim($name));
if (count($words) >= 2) {
return mb_substr($words[0], 0, 1) . mb_substr($words[1], 0, 1);
}
return mb_substr($name, 0, 2);
}
private function getAvatarColor(string $name): string
{
$colors = ['#4F46E5', '#7C3AED', '#2563EB', '#0891B2', '#059669', '#D97706', '#DC2626', '#0F766E'];
$index = abs(crc32($name) % count($colors));
return $colors[$index];
}
}
+80
View File
@@ -0,0 +1,80 @@
<?php
declare(strict_types=1);
namespace App\Models;
use App\Casts\JalaliDatetime;
use App\Traits\HasUserStamps;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Visit extends Model
{
use HasUserStamps;
protected $fillable = [
'patient',
'visit_date',
'visit_time',
'treatment',
'treatment_cost',
'payment_type',
'paid_amount',
'pos_ul',
'pos_ll',
'pos_ur',
'pos_lr',
'treatment_description',
'doctor',
];
protected function casts(): array
{
return [
'treatment_cost' => 'integer',
'paid_amount' => 'integer',
'pos_ul' => 'integer',
'pos_ll' => 'integer',
'pos_ur' => 'integer',
'pos_lr' => 'integer',
'created_at' => JalaliDatetime::class,
'updated_at' => JalaliDatetime::class,
];
}
public function getRemainedAmountAttribute(): int
{
return (int) ($this->treatment_cost ?? 0) - (int) ($this->paid_amount ?? 0);
}
public function patientRecord(): BelongsTo
{
return $this->belongsTo(Patient::class, 'patient');
}
public function doctorRecord(): BelongsTo
{
return $this->belongsTo(Doctor::class, 'doctor');
}
public function treatmentRecord(): BelongsTo
{
return $this->belongsTo(Treatment::class, 'treatment');
}
public function paymentTypeRecord(): BelongsTo
{
return $this->belongsTo(PaymentType::class, 'payment_type');
}
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
public function updator(): BelongsTo
{
return $this->belongsTo(User::class, 'updated_by');
}
}