massive reorganization Institute, Facility => Organization, Department

This commit is contained in:
Masroor Ehsan 2025-01-22 17:33:34 +06:00
parent a75833f77a
commit 03bd94eb37
22 changed files with 81 additions and 102 deletions

View File

@ -9,12 +9,12 @@ final class TechnicianWorklist extends WorklistBase
protected function buildQuery(?int $user_id = null): Builder protected function buildQuery(?int $user_id = null): Builder
{ {
$query = $this->getStudiesQuery(); $query = $this->getStudiesQuery();
$facility_id = auth()->user()->facility_id; $department_id = auth()->user()->department_id;
if ($facility_id) { if ($department_id) {
$query = $query->where('facility_id', $facility_id); $query = $query->where('department_id', $department_id);
} else { } else {
$institute_id = auth()->user()->institute_id; $organization_id = auth()->user()->organization_id;
$query = $query->where('institute_id', $institute_id); $query = $query->where('organization_id', $organization_id);
} }
return $query; return $query;

View File

@ -3,7 +3,7 @@
namespace App\Filament\Resources; namespace App\Filament\Resources;
use App\Filament\Resources\FacilityResource\Pages; use App\Filament\Resources\FacilityResource\Pages;
use App\Models\Facility; use App\Models\Department;
use Filament\Forms\Form; use Filament\Forms\Form;
use Filament\Resources\Resource; use Filament\Resources\Resource;
use Filament\Tables; use Filament\Tables;
@ -11,7 +11,7 @@
class FacilityResource extends Resource class FacilityResource extends Resource
{ {
protected static ?string $model = Facility::class; protected static ?string $model = Department::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';

View File

@ -3,7 +3,7 @@
namespace App\Filament\Resources; namespace App\Filament\Resources;
use App\Filament\Resources\InstituteResource\Pages; use App\Filament\Resources\InstituteResource\Pages;
use App\Models\Institute; use App\Models\Organization;
use Filament\Forms\Form; use Filament\Forms\Form;
use Filament\Resources\Resource; use Filament\Resources\Resource;
use Filament\Tables; use Filament\Tables;
@ -11,7 +11,7 @@
class InstituteResource extends Resource class InstituteResource extends Resource
{ {
protected static ?string $model = Institute::class; protected static ?string $model = Organization::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';

View File

@ -2,11 +2,11 @@
namespace App\Http\Resources; namespace App\Http\Resources;
use App\Models\Institute; use App\Models\Organization;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource; use Illuminate\Http\Resources\Json\JsonResource;
/** @mixin Institute */ /** @mixin Organization */
class InstituteResource extends JsonResource class InstituteResource extends JsonResource
{ {
public function toArray(Request $request): array public function toArray(Request $request): array

View File

@ -6,13 +6,13 @@
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Facility extends Model class Department extends Model
{ {
use Active; use Active;
public function institute(): BelongsTo public function organization(): BelongsTo
{ {
return $this->belongsTo(Institute::class); return $this->belongsTo(Organization::class);
} }
protected function casts(): array protected function casts(): array

View File

@ -17,14 +17,14 @@ public function conditions(): HasMany
return $this->hasMany(DicomRuleCondition::class); return $this->hasMany(DicomRuleCondition::class);
} }
public function institute(): BelongsTo public function organization(): BelongsTo
{ {
return $this->belongsTo(Institute::class); return $this->belongsTo(Organization::class);
} }
public function facility(): BelongsTo public function department(): BelongsTo
{ {
return $this->belongsTo(Facility::class); return $this->belongsTo(Department::class);
} }
public function panel(): HasOne public function panel(): HasOne
@ -34,7 +34,7 @@ public function panel(): HasOne
public function radiologist(): HasOne public function radiologist(): HasOne
{ {
return $this->hasOne(User::class, 'radiologist_id'); return $this->hasOne(User::class);
} }
protected function casts(): array protected function casts(): array

View File

@ -12,12 +12,12 @@ class DicomServer extends BaseModel
public function institute(): BelongsTo public function institute(): BelongsTo
{ {
return $this->belongsTo(Institute::class); return $this->belongsTo(Organization::class);
} }
public function facility(): BelongsTo public function facility(): BelongsTo
{ {
return $this->belongsTo(Facility::class); return $this->belongsTo(Department::class);
} }
public function stoneViewerUrl(): Uri public function stoneViewerUrl(): Uri

View File

@ -2,9 +2,4 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; class Modality extends BaseModel {}
class Modality extends BaseModel
{
use HasFactory;
}

View File

@ -6,14 +6,14 @@
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
class Institute extends BaseModel class Organization extends BaseModel
{ {
use Active; use Active;
use HasFactory; use HasFactory;
public function facilities(): HasMany public function departments(): HasMany
{ {
return $this->hasMany(Facility::class); return $this->hasMany(Department::class);
} }
protected function casts(): array protected function casts(): array

View File

@ -2,10 +2,4 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; class Procedure extends BaseModel {}
class Procedure extends BaseModel
{
use HasFactory;
}

View File

@ -161,12 +161,12 @@ public function radiologistProfile(): HasOne
public function institute(): BelongsTo public function institute(): BelongsTo
{ {
return $this->belongsTo(Institute::class); return $this->belongsTo(Organization::class);
} }
public function facility(): BelongsTo public function facility(): BelongsTo
{ {
return $this->belongsTo(Facility::class); return $this->belongsTo(Department::class);
} }
public function canAccessPanel(Panel $panel): bool public function canAccessPanel(Panel $panel): bool

View File

@ -8,7 +8,7 @@
use App\Models\AssignmentPanel; use App\Models\AssignmentPanel;
use App\Models\DicomRoutingRule; use App\Models\DicomRoutingRule;
use App\Models\DicomRuleCondition; use App\Models\DicomRuleCondition;
use App\Models\Institute; use App\Models\Organization;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
@ -80,7 +80,7 @@ private static function initialize(): void
} }
if (self::$catchAll < 0) { if (self::$catchAll < 0) {
self::$catchAll = Institute::where('name', 'CATCH-ALL') self::$catchAll = Organization::where('name', 'CATCH-ALL')
->first('id') ->first('id')
->id; ->id;
} }

View File

@ -2,13 +2,13 @@
namespace Database\Factories; namespace Database\Factories;
use App\Models\Institute; use App\Models\Organization;
use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon; use Illuminate\Support\Carbon;
class InstituteFactory extends Factory class InstituteFactory extends Factory
{ {
protected $model = Institute::class; protected $model = Organization::class;
public function definition(): array public function definition(): array
{ {

View File

@ -1,7 +1,7 @@
<?php <?php
use App\Models\Facility; use App\Models\Department;
use App\Models\Institute; use App\Models\Organization;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
@ -24,8 +24,8 @@ public function up(): void
$table->string('stone_viewer_path')->nullable(); $table->string('stone_viewer_path')->nullable();
$table->string('ohif_viewer_path')->nullable(); $table->string('ohif_viewer_path')->nullable();
$table->string('meddream_viewer_path')->nullable(); $table->string('meddream_viewer_path')->nullable();
$table->foreignIdFor(Institute::class)->nullable()->index(); $table->foreignIdFor(Organization::class)->nullable()->index();
$table->foreignIdFor(Facility::class)->nullable()->index(); $table->foreignIdFor(Department::class)->nullable()->index();
$table->timestamps(); $table->timestamps();
}); });
} }

View File

@ -1,7 +1,7 @@
<?php <?php
use App\Models\Facility; use App\Models\Department;
use App\Models\Institute; use App\Models\Organization;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
@ -13,20 +13,22 @@ public function up(): void
Schema::create('users', static function (Blueprint $table) { Schema::create('users', static function (Blueprint $table) {
$table->id(); $table->id();
$table->string('guid', 40)->unique()->index()->default(DB::raw("concat('USR-', gen_random_uuid())")); $table->string('guid', 40)->unique()->index()->default(DB::raw("concat('USR-', gen_random_uuid())"));
$table->boolean('is_active')->default(true); $table->boolean('is_active')->default(true)->index();
$table->string('prefix')->nullable(); $table->string('prefix')->nullable();
$table->string('first_name'); $table->string('first_name');
$table->string('last_name')->nullable(); $table->string('last_name')->nullable();
$table->string('display_name'); $table->string('display_name');
$table->string('username')->unique(); $table->string('username')->unique();
$table->string('password');
$table->string('phone')->nullable()->index(); $table->string('phone')->nullable()->index();
$table->string('email')->nullable()->index(); $table->string('email')->nullable()->index();
$table->timestamp('email_verified_at')->nullable(); $table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->foreignId('current_team_id')->nullable(); $table->foreignId('current_team_id')->nullable();
$table->string('profile_photo_path')->nullable(); $table->string('profile_photo_path')->nullable();
$table->foreignIdFor(Institute::class)->nullable()->index(); $table->string('signature_image_path')->nullable();
$table->foreignIdFor(Facility::class)->nullable()->index(); $table->text('signature_text')->nullable();
$table->foreignIdFor(Organization::class)->nullable()->index();
$table->foreignIdFor(Department::class)->nullable()->index();
$table->string('timezone')->default('Asia/Dhaka'); $table->string('timezone')->default('Asia/Dhaka');
$table->rememberToken(); $table->rememberToken();
$table->timestamps(); $table->timestamps();

View File

@ -3,6 +3,9 @@
use App\Domain\Report\ReportStatus; use App\Domain\Report\ReportStatus;
use App\Domain\Study\Priority; use App\Domain\Study\Priority;
use App\Domain\Study\StudyLevelStatus; use App\Domain\Study\StudyLevelStatus;
use App\Models\Department;
use App\Models\DicomServer;
use App\Models\Organization;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
@ -13,11 +16,11 @@ public function up(): void
{ {
Schema::create('studies', function (Blueprint $table) { Schema::create('studies', function (Blueprint $table) {
$table->id(); $table->id();
$table->unsignedBigInteger('dicom_server_id')->index(); $table->foreignIdFor(DicomServer::class)->index();
$table->unsignedBigInteger('institute_id')->index(); $table->foreignIdFor(Organization::class)->index();
$table->unsignedBigInteger('facility_id')->nullable(); $table->foreignIdFor(Department::class)->nullable()->index();
$table->unsignedTinyInteger('priority')->default(Priority::Routine); $table->unsignedTinyInteger('priority')->default(Priority::Routine->value);
$table->unsignedTinyInteger('study_status')->default(StudyLevelStatus::Pending->value); $table->unsignedTinyInteger('study_status')->default(StudyLevelStatus::Pending->value);
$table->unsignedTinyInteger('report_status')->default(ReportStatus::Unread->value); $table->unsignedTinyInteger('report_status')->default(ReportStatus::Unread->value);
@ -59,6 +62,16 @@ public function up(): void
$table->timestamps(); $table->timestamps();
$table->unique(['dicom_server_id', 'orthanc_uuid']); $table->unique(['dicom_server_id', 'orthanc_uuid']);
$table->index(['organization_id', 'priority', 'study_date']);
$table->index(['organization_id', 'received_at']);
$table->index(['organization_id', 'assigned_at']);
$table->index(['organization_id', 'locked_at']);
$table->index(['department_id', 'priority', 'study_date']);
$table->index(['department_id', 'received_at']);
$table->index(['department_id', 'assigned_at']);
$table->index(['department_id', 'locked_at']);
}); });
} }

View File

@ -1,8 +1,8 @@
<?php <?php
use App\Domain\Report\ReportStatus; use App\Domain\Report\ReportStatus;
use App\Models\Facility; use App\Models\Department;
use App\Models\Institute; use App\Models\Organization;
use App\Models\Study; use App\Models\Study;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
@ -18,8 +18,8 @@ public function up(): void
$table->unsignedTinyInteger('report_status')->default(ReportStatus::Unread->value); $table->unsignedTinyInteger('report_status')->default(ReportStatus::Unread->value);
$table->string('accession_number', 64)->unique()->index()->default(DB::raw("concat('REP-', gen_random_uuid())")); $table->string('accession_number', 64)->unique()->index()->default(DB::raw("concat('REP-', gen_random_uuid())"));
$table->foreignIdFor(Institute::class)->index()->nullable()->constrained()->nullOnDelete(); $table->foreignIdFor(Organization::class)->index()->nullable()->constrained()->nullOnDelete();
$table->foreignIdFor(Facility::class)->index()->nullable()->constrained()->nullOnDelete(); $table->foreignIdFor(Department::class)->index()->nullable()->constrained()->nullOnDelete();
$table->foreignIdFor(Study::class)->index()->constrained()->cascadeOnDelete(); $table->foreignIdFor(Study::class)->index()->constrained()->cascadeOnDelete();
$table->foreignIdFor(User::class, 'read_by_id')->index()->constrained()->cascadeOnDelete(); $table->foreignIdFor(User::class, 'read_by_id')->index()->constrained()->cascadeOnDelete();
$table->foreignIdFor(User::class, 'dictated_by_id')->index()->nullable()->constrained()->nullOnDelete(); $table->foreignIdFor(User::class, 'dictated_by_id')->index()->nullable()->constrained()->nullOnDelete();

View File

@ -2,8 +2,8 @@
use App\Domain\Rule\MatchCondition; use App\Domain\Rule\MatchCondition;
use App\Models\AssignmentPanel; use App\Models\AssignmentPanel;
use App\Models\Facility; use App\Models\Department;
use App\Models\Institute; use App\Models\Organization;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@ -16,9 +16,9 @@ public function up(): void
Schema::create('dicom_routing_rules', static function (Blueprint $table) { Schema::create('dicom_routing_rules', static function (Blueprint $table) {
$table->id(); $table->id();
$table->boolean('is_active')->default(true); $table->boolean('is_active')->default(true);
$table->foreignIdFor(Institute::class)->constrained()->cascadeOnDelete(); $table->foreignIdFor(Organization::class)->constrained()->cascadeOnDelete();
$table->foreignIdFor(Facility::class)->nullable()->constrained()->cascadeOnDelete(); $table->foreignIdFor(Department::class)->nullable()->constrained()->cascadeOnDelete();
$table->foreignIdFor(User::class, 'radiologist_id')->nullable()->constrained()->nullOnDelete(); $table->foreignIdFor(User::class)->nullable()->constrained()->nullOnDelete();
$table->foreignIdFor(AssignmentPanel::class)->nullable()->constrained()->nullOnDelete(); $table->foreignIdFor(AssignmentPanel::class)->nullable()->constrained()->nullOnDelete();
$table->string('description')->nullable(); $table->string('description')->nullable();
$table->string('match_condition')->default(MatchCondition::ANY->value); $table->string('match_condition')->default(MatchCondition::ANY->value);

View File

@ -1,25 +0,0 @@
<?php
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('radiologist_profiles', static function (Blueprint $table) {
$table->id();
$table->foreignIdFor(User::class)->unique()->constrained()->cascadeOnDelete();
$table->string('signature_image_path')->nullable();
$table->text('signature_text')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('radiologist_profiles');
}
};

View File

@ -3,9 +3,9 @@
namespace Database\Seeders; namespace Database\Seeders;
use App\Domain\Rule\MatchMode; use App\Domain\Rule\MatchMode;
use App\Models\Department;
use App\Models\DicomServer; use App\Models\DicomServer;
use App\Models\Facility; use App\Models\Organization;
use App\Models\Institute;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@ -13,31 +13,31 @@ class InstituteSeeder extends Seeder
{ {
public function run(): void public function run(): void
{ {
Institute::create([ Organization::create([
'name' => 'CATCH-ALL', 'name' => 'CATCH-ALL',
'is_active' => true, 'is_active' => true,
]); ]);
$chev = Institute::create([ $chev = Organization::create([
'name' => 'Chevron', 'name' => 'Chevron',
'is_active' => true, 'is_active' => true,
]); ]);
$cmch = Institute::create([ $cmch = Organization::create([
'name' => 'CMCH', 'name' => 'CMCH',
'is_active' => true, 'is_active' => true,
]); ]);
$dummy = Institute::create([ $dummy = Organization::create([
'name' => 'Dummy Site', 'name' => 'Dummy Site',
'is_active' => false, 'is_active' => false,
]); ]);
$chev_xr = Facility::create( $chev_xr = Department::create(
[ [
'is_active' => true, 'is_active' => true,
'name' => 'Chevron XR', 'name' => 'Chevron XR',
'institute_id' => $chev->id, 'institute_id' => $chev->id,
] ]
); );
$cmch_mr = Facility::create( $cmch_mr = Department::create(
[ [
'is_active' => false, 'is_active' => false,
'name' => 'CMCH MR', 'name' => 'CMCH MR',

View File

@ -3,7 +3,7 @@
namespace Database\Seeders; namespace Database\Seeders;
use App\Domain\ACL\Role; use App\Domain\ACL\Role;
use App\Models\Institute; use App\Models\Organization;
use App\Models\RadiologistProfile; use App\Models\RadiologistProfile;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
@ -33,8 +33,8 @@ public function run(): void
]); ]);
$usr->assignRole(Role::Admin); $usr->assignRole(Role::Admin);
$chevron = Institute::where('name', 'Chevron')->first(); $chevron = Organization::where('name', 'Chevron')->first();
$cmch = Institute::where('name', 'CMCH')->first(); $cmch = Organization::where('name', 'CMCH')->first();
User::factory(4) User::factory(4)
->create([ ->create([