Compare commits
15 Commits
927c51e16d
...
a7228b8a61
Author | SHA1 | Date | |
---|---|---|---|
a7228b8a61 | |||
fac10cdc25 | |||
d4c6e58e30 | |||
9e969df68b | |||
a02adfc685 | |||
ce28bb1422 | |||
0fce30bd18 | |||
7a28b892f3 | |||
60f32a6468 | |||
4e2c1837ee | |||
ea341ca8f4 | |||
9f60cfb32e | |||
97481e8473 | |||
802f13c702 | |||
3a775c4f21 |
@ -50,4 +50,19 @@ public static function worklist_stats(int $days, int $workflow_level)
|
||||
|
||||
return $rows;
|
||||
}
|
||||
|
||||
public static function activeRads(): array
|
||||
{
|
||||
return cache()
|
||||
->remember('active_rads',
|
||||
now()->addMinutes(5),
|
||||
fn () => DB::table('users')
|
||||
->join('model_has_roles', 'users.id', '=', 'model_has_roles.model_id')
|
||||
->join('roles', 'model_has_roles.role_id', '=', 'roles.id')
|
||||
->where('roles.name', Role::Radiologist->value)
|
||||
->where('users.is_active', true)
|
||||
->orderBy('users.display_name')
|
||||
->pluck('users.display_name', 'users.id')
|
||||
->toArray());
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ interface IUserStudyLister
|
||||
{
|
||||
public function setRadiologist(int $radiologist_id): self;
|
||||
|
||||
public function setWorkflowLevel(WorkflowLevel $status): self;
|
||||
public function setWorkflowLevel(WorkflowLevel $level): self;
|
||||
|
||||
public function setPerPage(int $size): self;
|
||||
|
||||
|
@ -48,9 +48,9 @@ public function setRadiologist(int $radiologist_id): self
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setWorkflowLevel(WorkflowLevel $status): self
|
||||
public function setWorkflowLevel(WorkflowLevel $level): self
|
||||
{
|
||||
$this->workflowLevel = $status;
|
||||
$this->workflowLevel = $level;
|
||||
|
||||
return $this;
|
||||
}
|
||||
@ -71,7 +71,6 @@ public function get(?int $user_id = null): LengthAwarePaginator
|
||||
$query = $this->applySearch($query);
|
||||
$query = $this->applyRadiologist($query);
|
||||
$query = $this->applyWorkflowLevel($query);
|
||||
$query = $this->applyReportStatus($query);
|
||||
$query = $this->applyArchived($query);
|
||||
$query = $this->applyLocked($query);
|
||||
$query = $this->applyDateFilters($query);
|
||||
|
@ -13,22 +13,27 @@
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Support\Str;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class DepartmentResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Department::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
|
||||
protected static ?string $navigationIcon = 'heroicon-o-building-storefront';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
TextInput::make('guid')
|
||||
->label('Unique ID')
|
||||
->default(sprintf('DEP-%s', Str::of(Uuid::uuid4())->lower()))
|
||||
->disabled()
|
||||
->dehydrated()
|
||||
->required()
|
||||
->maxLength(40)
|
||||
->default(sprintf('FAC-%s', Uuid::uuid4())),
|
||||
->unique(ignoreRecord: true),
|
||||
Toggle::make('is_active')
|
||||
->required(),
|
||||
Select::make('organization_id')
|
||||
@ -44,15 +49,10 @@ public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('guid')
|
||||
->searchable(),
|
||||
IconColumn::make('is_active')
|
||||
->boolean(),
|
||||
TextColumn::make('organization.name')
|
||||
->numeric()
|
||||
->sortable(),
|
||||
TextColumn::make('name')
|
||||
->searchable(),
|
||||
IconColumn::make('is_active')->boolean(),
|
||||
TextColumn::make('name')->searchable(),
|
||||
TextColumn::make('organization.name')->sortable(),
|
||||
TextColumn::make('guid')->searchable(),
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
|
126
app/Filament/Resources/DicomRoutingRuleResource.php
Normal file
126
app/Filament/Resources/DicomRoutingRuleResource.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\DAL\Radiologists;
|
||||
use App\Filament\Resources\DicomRoutingRuleResource\Pages;
|
||||
use App\Models\DicomRoutingRule;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class DicomRoutingRuleResource extends Resource
|
||||
{
|
||||
protected static ?string $model = DicomRoutingRule::class;
|
||||
protected static ?string $modelLabel = 'Routing Rules';
|
||||
protected static ?string $navigationIcon = 'heroicon-o-academic-cap';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Toggle::make('is_active')
|
||||
->required(),
|
||||
Select::make('organization_id')
|
||||
->label('Organization')
|
||||
->relationship('organization', 'name')
|
||||
->required(),
|
||||
Select::make('department_id')
|
||||
->label('Department')
|
||||
->relationship('department', 'name'),
|
||||
Select::make('user_id')
|
||||
->label('Radiologist')
|
||||
->relationship('radiologist', 'display_name')
|
||||
->options(Radiologists::activeRads()),
|
||||
Select::make('assignment_panel_id')
|
||||
->label('Panel')
|
||||
->relationship('panel', 'name'),
|
||||
TextInput::make('name')
|
||||
->maxLength(255),
|
||||
Textarea::make('condition')
|
||||
->columnSpanFull()
|
||||
->required(),
|
||||
TextInput::make('priority')
|
||||
->required()
|
||||
->numeric()
|
||||
->default(0),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
IconColumn::make('is_active')
|
||||
->label('')
|
||||
->boolean(),
|
||||
TextColumn::make('name')
|
||||
->searchable(),
|
||||
TextColumn::make('condition')
|
||||
->label('Rule')
|
||||
->limit(20)
|
||||
->searchable(),
|
||||
TextColumn::make('priority')
|
||||
->numeric()
|
||||
->sortable(),
|
||||
TextColumn::make('organization.name')
|
||||
->label('Org')
|
||||
->numeric()
|
||||
->sortable(),
|
||||
TextColumn::make('department.name')
|
||||
->label('Dept')
|
||||
->numeric()
|
||||
->sortable(),
|
||||
TextColumn::make('user_id')
|
||||
->label('Rad')
|
||||
->numeric()
|
||||
->sortable(),
|
||||
TextColumn::make('assignment_panel_id')
|
||||
->label('Panel')
|
||||
->numeric()
|
||||
->sortable(),
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListDicomRoutingRules::route('/'),
|
||||
'create' => Pages\CreateDicomRoutingRule::route('/create'),
|
||||
'edit' => Pages\EditDicomRoutingRule::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\DicomRoutingRuleResource\Pages;
|
||||
|
||||
use App\Filament\Resources\DicomRoutingRuleResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateDicomRoutingRule extends CreateRecord
|
||||
{
|
||||
protected static string $resource = DicomRoutingRuleResource::class;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\DicomRoutingRuleResource\Pages;
|
||||
|
||||
use App\Filament\Resources\DicomRoutingRuleResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditDicomRoutingRule extends EditRecord
|
||||
{
|
||||
protected static string $resource = DicomRoutingRuleResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\DicomRoutingRuleResource\Pages;
|
||||
|
||||
use App\Filament\Resources\DicomRoutingRuleResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListDicomRoutingRules extends ListRecords
|
||||
{
|
||||
protected static string $resource = DicomRoutingRuleResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
@ -3,12 +3,14 @@
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\DicomServerResource\Pages;
|
||||
use App\Models\Department;
|
||||
use App\Models\DicomServer;
|
||||
use App\Services\GeoLocation;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Forms\Get;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
@ -30,6 +32,7 @@ public static function form(Form $form): Form
|
||||
->required(),
|
||||
TextInput::make('server_name')
|
||||
->required()
|
||||
->unique(ignoreRecord: true)
|
||||
->maxLength(255),
|
||||
Select::make('geo_code')
|
||||
->required()
|
||||
@ -48,12 +51,11 @@ public static function form(Form $form): Form
|
||||
->required()
|
||||
->maxLength(255),
|
||||
TextInput::make('ae_title')
|
||||
->maxLength(255),
|
||||
->maxLength(24),
|
||||
TextInput::make('username')
|
||||
->maxLength(255),
|
||||
->maxLength(40),
|
||||
TextInput::make('password')
|
||||
->password()
|
||||
->maxLength(255),
|
||||
->maxLength(40),
|
||||
TextInput::make('wado_path')
|
||||
->maxLength(255),
|
||||
TextInput::make('stone_viewer_path')
|
||||
@ -62,10 +64,21 @@ public static function form(Form $form): Form
|
||||
->maxLength(255),
|
||||
TextInput::make('meddream_viewer_path')
|
||||
->maxLength(255),
|
||||
TextInput::make('organization_id')
|
||||
->numeric(),
|
||||
TextInput::make('department_id')
|
||||
->numeric(),
|
||||
Select::make('organization_id')
|
||||
->label('Organization')
|
||||
->live()
|
||||
->relationship('organization', 'name'),
|
||||
Select::make('department_id')
|
||||
->label('Department')
|
||||
->options(function (Get $get) {
|
||||
$organization_id = $get('organization_id');
|
||||
$result = [];
|
||||
if ($organization_id != null) {
|
||||
$result = Department::active()->organization($organization_id)->pluck('name', 'id')->toArray();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -88,12 +101,13 @@ public static function table(Table $table): Table
|
||||
->label('WADO'),
|
||||
TextColumn::make('dicom_port')
|
||||
->label('DICOM'),
|
||||
TextColumn::make('rest_api_endpoint')
|
||||
->label('REST')
|
||||
->searchable(),
|
||||
TextColumn::make('ae_title')
|
||||
->label('AET')
|
||||
->searchable(),
|
||||
TextColumn::make('rest_api_endpoint')
|
||||
->label('REST')
|
||||
->url(fn (DicomServer $srv) => $srv->rest_api_endpoint, shouldOpenInNewTab: true)
|
||||
->searchable(),
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
use App\Filament\Resources\OrganizationResource\Pages;
|
||||
use App\Models\Organization;
|
||||
use Filament\Forms\Components\Textarea;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Forms\Form;
|
||||
@ -14,28 +15,34 @@
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Support\Str;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
class OrganizationResource extends Resource
|
||||
{
|
||||
protected static ?string $model = Organization::class;
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
|
||||
protected static ?string $navigationIcon = 'heroicon-o-building-office-2';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
TextInput::make('guid')
|
||||
->label('Unique ID')
|
||||
->default(sprintf('ORG-%s', Str::of(Uuid::uuid4())->lower()))
|
||||
->disabled()
|
||||
->dehydrated()
|
||||
->required()
|
||||
->maxLength(40)
|
||||
->default(sprintf('INS-%s', Uuid::uuid4())),
|
||||
TextInput::make('name')
|
||||
->required()
|
||||
->maxLength(255),
|
||||
->unique(ignoreRecord: true),
|
||||
Toggle::make('is_active')
|
||||
->required(),
|
||||
TextInput::make('address')
|
||||
TextInput::make('name')
|
||||
->required()
|
||||
->unique(ignoreRecord: true)
|
||||
->maxLength(255),
|
||||
TextArea::make('address')
|
||||
->maxLength(255),
|
||||
TextInput::make('logo_path')
|
||||
->maxLength(255),
|
||||
@ -46,16 +53,9 @@ public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('guid')
|
||||
->searchable(),
|
||||
TextColumn::make('name')
|
||||
->searchable(),
|
||||
IconColumn::make('is_active')
|
||||
->boolean(),
|
||||
TextColumn::make('address')
|
||||
->searchable(),
|
||||
TextColumn::make('logo_path')
|
||||
->searchable(),
|
||||
IconColumn::make('is_active')->boolean(),
|
||||
TextColumn::make('name')->searchable(),
|
||||
TextColumn::make('guid')->searchable(),
|
||||
TextColumn::make('created_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
|
@ -7,7 +7,6 @@
|
||||
use App\Models\User;
|
||||
use App\Services\ACL\RoleService;
|
||||
use App\Services\TimezoneList;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Select;
|
||||
@ -41,7 +40,7 @@ public static function form(Form $form): Form
|
||||
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('guid')
|
||||
TextInput::make('guid')
|
||||
->label('Unique ID')
|
||||
->default(sprintf('USR-%s', Str::of(Uuid::uuid4())->lower()))
|
||||
->disabled()
|
||||
|
@ -21,7 +21,7 @@ public function rules(): array
|
||||
'referring_physician_name' => ['nullable'],
|
||||
'institution_name' => ['nullable'],
|
||||
'priority' => ['required', 'integer'],
|
||||
'cancel_read' => ['nullable', 'boolean'],
|
||||
'cancel_read' => ['accepted'],
|
||||
|
||||
/*
|
||||
'referring_physician_id' => ['nullable', 'exists:users,id'],
|
||||
|
@ -4,9 +4,8 @@
|
||||
|
||||
use App\Models\Traits\Active;
|
||||
use App\Models\Traits\HasOrganization;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Department extends Model
|
||||
class Department extends BaseModel
|
||||
{
|
||||
use Active;
|
||||
use HasOrganization;
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
use App\Models\Traits\Active;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
|
||||
class DicomRoutingRule extends BaseModel
|
||||
{
|
||||
@ -20,14 +19,14 @@ public function department(): BelongsTo
|
||||
return $this->belongsTo(Department::class);
|
||||
}
|
||||
|
||||
public function panel(): HasOne
|
||||
public function panel(): BelongsTo
|
||||
{
|
||||
return $this->hasOne(AssignmentPanel::class);
|
||||
return $this->belongsTo(AssignmentPanel::class, 'assignment_panel_id');
|
||||
}
|
||||
|
||||
public function radiologist(): HasOne
|
||||
public function radiologist(): BelongsTo
|
||||
{
|
||||
return $this->hasOne(User::class);
|
||||
return $this->belongsTo(User::class, 'user_id');
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
|
@ -10,12 +10,12 @@ class DicomServer extends BaseModel
|
||||
{
|
||||
use Active;
|
||||
|
||||
public function institute(): BelongsTo
|
||||
public function organization(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Organization::class);
|
||||
}
|
||||
|
||||
public function facility(): BelongsTo
|
||||
public function department(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Department::class);
|
||||
}
|
||||
|
@ -17,7 +17,8 @@
|
||||
|
||||
final class StudiesSync
|
||||
{
|
||||
public const string SYNC_AGENT = '$$_pacs_agent_$$';
|
||||
public const SYNC_AGENT = '$$_pacs_agent_$$';
|
||||
|
||||
private Collection $study_ids;
|
||||
|
||||
private Collection $insert_queue;
|
||||
@ -147,6 +148,29 @@ public function transformData(mixed $orthanc_src): array
|
||||
|
||||
$inst_name = data_get($orthanc_src, 'MainDicomTags.InstitutionName');
|
||||
$patient_name = data_get($orthanc_src, 'PatientMainDicomTags.PatientName');
|
||||
$name_parts = tokenizeString($patient_name);
|
||||
$patient_age = data_get($orthanc_src, 'RequestedTags.PatientAge');
|
||||
if (blank($patient_age) && ! empty($name_parts)) {
|
||||
// try to get age from last part of patient name
|
||||
$last = end($name_parts);
|
||||
if (preg_match('/^\d+[YMD]$/i', $last)) {
|
||||
$patient_age = $last;
|
||||
/*
|
||||
// sanitize patient name
|
||||
array_pop($name_parts);
|
||||
$patient_name = implode(' ', $name_parts);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
if ($patient_age !== null) {
|
||||
$age = strtoupper(ltrim($patient_age, '0'));
|
||||
if (strlen($age) > 1) {
|
||||
$patient_age = $age;
|
||||
}
|
||||
}
|
||||
|
||||
// $patient_name = trim($patient_name, '.^ ');
|
||||
|
||||
$descr = $this->getStudyDescription($orthanc_src);
|
||||
$study = [
|
||||
@ -160,7 +184,7 @@ public function transformData(mixed $orthanc_src): array
|
||||
'patient_id' => data_get($orthanc_src, 'PatientMainDicomTags.PatientID'),
|
||||
'patient_name' => $patient_name,
|
||||
'patient_sex' => data_get($orthanc_src, 'PatientMainDicomTags.PatientSex'),
|
||||
'patient_age' => data_get($orthanc_src, 'RequestedTags.PatientAge'),
|
||||
'patient_age' => $patient_age,
|
||||
|
||||
'accession_number' => data_get($orthanc_src, 'MainDicomTags.AccessionNumber'),
|
||||
'referring_physician_name' => data_get($orthanc_src, 'MainDicomTags.ReferringPhysicianName'),
|
||||
@ -182,16 +206,40 @@ public function transformData(mixed $orthanc_src): array
|
||||
$study['workflow_level'] = $stable_study
|
||||
? WorkflowLevel::Unassigned->value
|
||||
: WorkflowLevel::Received->value;
|
||||
$study['patient_birthdate'] = null;
|
||||
|
||||
$patient_birthdate = null;
|
||||
$dob = data_get($orthanc_src, 'PatientMainDicomTags.PatientBirthDate');
|
||||
if (filled($dob)) {
|
||||
try {
|
||||
$study['patient_birthdate'] = Carbon::parse($dob);
|
||||
$patient_birthdate = Carbon::parse($dob);
|
||||
} catch (Exception $e) {
|
||||
Log::error('Failed to parse PatientMainDicomTags.PatientBirthDate: {dob}', ['dob' => $dob, 'exception' => $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($patient_birthdate == null && $patient_age !== null) {
|
||||
try {
|
||||
// $age = (int) preg_replace('/[^0-9]/', '', $patient_age);
|
||||
$age_num = (int) filter_var($patient_age, FILTER_SANITIZE_NUMBER_INT);
|
||||
$now = now();
|
||||
switch (strtoupper(substr($patient_age, -1))) {
|
||||
case 'Y':
|
||||
$patient_birthdate = $now->subYears($age_num);
|
||||
break;
|
||||
case 'M':
|
||||
$patient_birthdate = $now->subMonths($age_num);
|
||||
break;
|
||||
case 'D':
|
||||
$patient_birthdate = $now->subDays($age_num);
|
||||
break;
|
||||
}
|
||||
} catch (Exception) {
|
||||
Log::error('Failed to parse PatientMainDicomTags.PatientBirthDate: {dob}', ['dob' => $dob]);
|
||||
Log::error('Failed to parse patient_age: {age}', ['age' => $patient_age]);
|
||||
}
|
||||
}
|
||||
|
||||
$study['patient_birthdate'] = $patient_birthdate;
|
||||
|
||||
// check for priority in patient name or description
|
||||
if (preg_match('/\b(urgent|stat)\b/i', implode(' ', [$descr, $patient_name]))) {
|
||||
$this->setValue($study, 'priority', Priority::Stat->value);
|
||||
@ -283,7 +331,9 @@ private function getStudyDicomTags(string $study_uuid): array
|
||||
}
|
||||
|
||||
// randomly sample few instances for tags collection
|
||||
$selectedInstances = count($instances) <= $this->maxInstances ? $instances : array_rand(array_flip($instances), $this->maxInstances);
|
||||
$selectedInstances = count($instances) <= $this->maxInstances
|
||||
? $instances
|
||||
: array_intersect_key($instances, array_flip(array_rand($instances, $this->maxInstances)));
|
||||
|
||||
$tags = collect();
|
||||
foreach ($selectedInstances as $instance) {
|
||||
|
@ -123,11 +123,13 @@ function me(User|int|null $user = null): User
|
||||
{
|
||||
if (is_int($user) && $user > 0) {
|
||||
return User::find($user);
|
||||
} elseif ($user instanceof User) {
|
||||
return $user;
|
||||
} else {
|
||||
return auth()->user();
|
||||
}
|
||||
|
||||
if ($user instanceof User) {
|
||||
return $user;
|
||||
}
|
||||
|
||||
return auth()->user();
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,3 +143,10 @@ function formatTitle(string $str): string
|
||||
->toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('tokenizeString')) {
|
||||
function tokenizeString(string $str): array
|
||||
{
|
||||
return preg_split('/\W+/', trim($str), -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ public function up(): void
|
||||
{
|
||||
Schema::create('organizations', static function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('guid', 40)->unique()->index()->default(DB::raw("concat('INS-', gen_random_uuid())"));
|
||||
$table->string('guid', 40)->unique()->index()->default(DB::raw("concat('ORG-', gen_random_uuid())"));
|
||||
$table->string('name')->unique();
|
||||
$table->boolean('is_active')->default(false);
|
||||
$table->string('address')->nullable();
|
||||
|
@ -11,7 +11,7 @@ public function up(): void
|
||||
{
|
||||
Schema::create('departments', static function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('guid', 40)->unique()->index()->default(DB::raw("concat('FAC-', gen_random_uuid())"));
|
||||
$table->string('guid', 40)->unique()->index()->default(DB::raw("concat('DEP-', gen_random_uuid())"));
|
||||
$table->boolean('is_active')->default(false)->index();
|
||||
$table->foreignIdFor(Organization::class)->constrained()->cascadeOnDelete();
|
||||
$table->string('name');
|
||||
|
@ -32,13 +32,25 @@
|
||||
<h5 class="mb-0">Patient Information</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@include('staff.meta.partials._text', ['name' => 'patient_id', 'label' => 'Patient ID', 'value' => $study->patient_id])
|
||||
@include('staff.meta.partials._text', ['name' => 'patient_name', 'label' => 'Patient Name', 'value' => $study->patient_name])
|
||||
@include('staff.meta.partials._text', ['name' => 'patient_sex', 'label' => 'Sex', 'value' => $study->patient_sex])
|
||||
@include('staff.meta.partials._date', ['name' => 'patient_birthdate', 'label' => 'Birth Date', 'value' => $study->patient_birthdate?->toDateString()])
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
@include('staff.meta.partials._text', ['name' => 'patient_id', 'label' => 'Patient ID', 'value' => $study->patient_id])
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@include('staff.meta.partials._text', ['name' => 'accession_number', 'label' => 'Accession number', 'value' => $study->accession_number])
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
@include('staff.meta.partials._text', ['name' => 'patient_sex', 'label' => 'Sex', 'value' => $study->patient_sex])
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@include('staff.meta.partials._date', ['name' => 'patient_birthdate', 'label' => 'Birth Date', 'value' => $study->patient_birthdate?->toDateString()])
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xl">
|
||||
@ -47,10 +59,24 @@
|
||||
<h5 class="mb-0">Study Information</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
@include('staff.meta.partials._text', ['name' => 'study_description', 'label' => 'Study Description', 'value' => $study->study_description])
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@include('staff.meta.partials._text', ['name' => 'body_part_examined', 'label' => 'Body Part Examined', 'value' => $study->body_part_examined])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
@include('staff.meta.partials._text', ['name' => 'institution_name', 'label' => 'Institution', 'value' => $study->institution_name])
|
||||
</div>
|
||||
<div class="col-6">
|
||||
@include('staff.meta.partials._text', ['name' => 'referring_physician_name', 'label' => 'Referring Physician', 'value' => $study->referring_physician_name])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<label class="form-check-label">Priority</label>
|
||||
<div class="col my-2">
|
||||
|
Loading…
Reference in New Issue
Block a user