This commit is contained in:
Dr Masroor Ehsan 2024-12-28 17:59:13 +06:00
parent e98a88e27d
commit 588982ebff
16 changed files with 196 additions and 51 deletions

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class InstituteRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => ['required'],
'is_active' => ['boolean'],
];
}
public function authorize(): bool
{
return true;
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Resources;
use App\Models\Institute;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
/** @mixin Institute */
class InstituteResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'is_active' => $this->is_active,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Models\Enums;
enum NameMatchModes: int
{
case Exact = 0;
case Contains = 1;
case StartsWith = 2;
case EndsWith = 3;
case Regex = 4;
}

View File

@ -0,0 +1,11 @@
<?php
namespace App\Models\Enums;
enum StudyLevelStatus: int
{
case None = 0;
case StudyArrived = 1 << 1;
case StudyLocked = 1 << 2;
case StudyUnlocked = 1 << 3;
}

View File

@ -2,10 +2,13 @@
namespace App\Models; namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Site extends Model class Institute extends Model
{ {
use HasFactory;
protected function casts(): array protected function casts(): array
{ {
return [ return [

View File

@ -0,0 +1,22 @@
<?php
namespace Database\Factories;
use App\Models\Institute;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Carbon;
class InstituteFactory extends Factory
{
protected $model = Institute::class;
public function definition(): array
{
return [
'name' => $this->faker->name(),
'is_active' => $this->faker->boolean(),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
];
}
}

View File

@ -42,7 +42,7 @@ public function definition(): array
'remember_token' => Str::random(10), 'remember_token' => Str::random(10),
'profile_photo_path' => null, 'profile_photo_path' => null,
'current_team_id' => null, 'current_team_id' => null,
'site_id' => null, 'institute_id' => null,
]; ];
} }

View File

@ -8,16 +8,16 @@
{ {
public function up(): void public function up(): void
{ {
Schema::create('sites', function (Blueprint $table) { Schema::create('institutes', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name'); $table->string('name')->unique();
$table->boolean('is_active')->default(true); $table->boolean('is_active')->default(false);
$table->timestamps(); $table->timestamps();
}); });
} }
public function down(): void public function down(): void
{ {
Schema::dropIfExists('sites'); Schema::dropIfExists('institutes');
} }
}; };

View File

@ -1,7 +1,7 @@
<?php <?php
use App\Models\Enums\UserRole; use App\Models\Enums\UserRole;
use App\Models\Site; use App\Models\Institute;
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;
@ -25,7 +25,7 @@ public function up(): void
$table->unsignedTinyInteger('role')->default(UserRole::Guest->value); $table->unsignedTinyInteger('role')->default(UserRole::Guest->value);
$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(Site::class)->nullable()->index(); $table->foreignIdFor(Institute::class)->nullable()->index();
$table->timestamps(); $table->timestamps();
}); });

View File

@ -1,7 +1,7 @@
<?php <?php
use App\Models\Enums\StudyAccessFlags; use App\Models\Enums\StudyAccessFlags;
use App\Models\Site; use App\Models\Institute;
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;
@ -15,7 +15,8 @@ public function up(): void
$table->id(); $table->id();
$table->string('orthanc_uid')->unique(); $table->string('orthanc_uid')->unique();
$table->boolean('is_active')->default(true); $table->boolean('is_active')->default(true);
$table->unsignedTinyInteger('priority')->default(0); $table->boolean('is_locked')->default(true);
$table->unsignedTinyInteger('study_priority')->default(0);
$table->string('patient_id')->nullable(); $table->string('patient_id')->nullable();
$table->string('patient_name'); $table->string('patient_name');
$table->string('patient_sex'); $table->string('patient_sex');
@ -24,24 +25,28 @@ public function up(): void
$table->string('institution_name'); $table->string('institution_name');
$table->string('accession_number')->nullable(); $table->string('accession_number')->nullable();
$table->string('study_description')->nullable(); $table->string('study_description')->nullable();
$table->dateTime('study_date')->index(); $table->string('study_modality', 4)->nullable();
$table->dateTime('receive_date')->index(); $table->dateTime('study_date');
$table->dateTime('receive_date');
$table->dateTime('report_date')->nullable(); $table->dateTime('report_date')->nullable();
$table->foreignIdFor(Site::class)->constrained()->onDelete('cascade'); $table->foreignIdFor(Institute::class)->constrained()->onDelete('cascade');
$table->unsignedTinyInteger('report_status')->default(0); $table->unsignedTinyInteger('report_status')->default(0);
$table->string('study_modality', 4); $table->unsignedSmallInteger('image_count')->default(0);
$table->unsignedSmallInteger('series_count')->default(0);
$table->foreignIdFor(User::class, 'assigned_physician_id')->nullable()->constrained()->onDelete('set null'); $table->foreignIdFor(User::class, 'assigned_physician_id')->nullable()->constrained()->onDelete('set null');
$table->foreignIdFor(User::class, 'interpreting_physician_id')->nullable()->constrained()->onDelete('set null'); $table->foreignIdFor(User::class, 'interpreting_physician_id')->nullable()->constrained()->onDelete('set null');
$table->foreignIdFor(User::class, 'referring_physician_id')->nullable()->constrained()->onDelete('set null'); $table->foreignIdFor(User::class, 'referring_physician_id')->nullable()->constrained()->onDelete('set null');
$table->foreignIdFor(User::class, 'reading_physician_id')->nullable()->constrained()->onDelete('set null');
$table->unsignedTinyInteger('access_flags')->default(StudyAccessFlags::None->value); $table->unsignedTinyInteger('access_flags')->default(StudyAccessFlags::None->value);
$table->string('access_password')->nullable(); $table->string('access_password')->nullable();
$table->timestamps(); $table->timestamps();
$table->index(['referring_physician_id', 'receive_date']); $table->index(['referring_physician_id', 'receive_date']);
$table->index(['site_id', 'receive_date']); $table->index(['institute_id', 'receive_date']);
$table->index(['site_id', 'accession_number']); $table->index(['institute_id', 'report_status', 'study_priority', 'receive_date']);
$table->index(['site_id', 'report_status', 'priority', 'receive_date']); $table->index(['assigned_physician_id', 'report_status', 'study_priority', 'receive_date']);
$table->index(['assigned_physician_id', 'report_status', 'priority', 'receive_date']);
}); });
} }

View File

@ -1,5 +1,8 @@
<?php <?php
use App\Models\Enums\ReportStatus;
use App\Models\Study;
use App\Models\User;
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;
@ -10,14 +13,12 @@ public function up(): void
{ {
Schema::create('study_reports', function (Blueprint $table) { Schema::create('study_reports', function (Blueprint $table) {
$table->id(); $table->id();
$table->unsignedTinyInteger('report_status')->default(0); $table->unsignedTinyInteger('report_status')->default(ReportStatus::Pending->value);
$table->foreignId('study_id')->constrained('studies'); $table->foreignIdFor(Study::class)->index()->constrained()->onDelete('cascade');
$table->foreignId('radiologist_id')->constrained('users'); $table->foreignIdFor(User::class)->index()->constrained()->onDelete('cascade');
$table->string('file_path'); $table->string('file_path');
$table->string('pdf_path')->nullable(); $table->string('pdf_path')->nullable();
$table->timestamps(); $table->timestamps();
$table->unique(['study_id', 'created_at']);
}); });
} }

View File

@ -0,0 +1,27 @@
<?php
use App\Models\Enums\NameMatchModes;
use App\Models\Institute;
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('institute_names', function (Blueprint $table) {
$table->id();
$table->foreignIdFor(Institute::class)->constrained()->onDelete('CASCADE');
$table->string('name')->unique();
$table->unsignedTinyInteger('match_mode')->default(NameMatchModes::Exact->value);
$table->unsignedTinyInteger('priority')->default(0);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('institute_names');
}
};

View File

@ -13,7 +13,7 @@ class DatabaseSeeder extends Seeder
public function run(): void public function run(): void
{ {
$this->call([ $this->call([
SiteSeeder::class, InstituteSeeder::class,
UserSeeder::class, UserSeeder::class,
]); ]);

View File

@ -0,0 +1,42 @@
<?php
namespace Database\Seeders;
use App\Models\Enums\NameMatchModes;
use App\Models\Institute;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class InstituteSeeder extends Seeder
{
public function run(): void
{
Institute::create([
'name' => 'Catch-all',
'is_active' => true,
]);
$chev = Institute::create([
'name' => 'Chevron',
'is_active' => true,
]);
$srini = Institute::create([
'name' => 'Srinivasa',
'is_active' => true,
]);
Institute::create([
'name' => 'Dummy Site',
'is_active' => false,
]);
DB::table('institute_names')->insert([
'name' => 'CHEVRON CLINICAL LABORATORY , PANCHLAISH,CTG',
'institute_id' => $chev->id,
'match_mode' => NameMatchModes::Exact->value,
]);
DB::table('institute_names')->insert([
'name' => 'CHEVRON CLINICAL',
'institute_id' => $chev->id,
'match_mode' => NameMatchModes::StartsWith->value,
]);
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace Database\Seeders;
use App\Models\Site;
use Illuminate\Database\Seeder;
class SiteSeeder extends Seeder
{
public function run(): void
{
Site::create([
'name' => 'Chevron',
'is_active' => true,
]);
Site::create([
'name' => 'Srinivasa',
'is_active' => true,
]);
Site::create([
'name' => 'Dummy Site',
'is_active' => false,
]);
}
}

View File

@ -3,6 +3,7 @@
namespace Database\Seeders; namespace Database\Seeders;
use App\Models\Enums\UserRole; use App\Models\Enums\UserRole;
use App\Models\Institute;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
@ -19,13 +20,16 @@ public function run(): void
'role' => UserRole::Admin->value, 'role' => UserRole::Admin->value,
]); ]);
$chevron = Institute::where('name', 'Chevron')->first();
$srini = Institute::where('name', 'Srinivasa')->first();
User::factory(2)->create([ User::factory(2)->create([
'site_id' => 1, 'institute_id' => $chevron->id,
'role' => UserRole::Technologist->value, 'role' => UserRole::Technologist->value,
]); ]);
User::factory(2)->create([ User::factory(2)->create([
'site_id' => 2, 'institute_id' => $srini->id,
'role' => UserRole::Technologist->value, 'role' => UserRole::Technologist->value,
]); ]);
} }