commit
4a79935e4c
@ -238,11 +238,21 @@ public function getColumns(): array
|
||||
break;
|
||||
|
||||
case WorklistColumn::Organization:
|
||||
$columns[] = Column::make($col->value)
|
||||
->searchable(false)
|
||||
->title('Org');
|
||||
break;
|
||||
|
||||
case WorklistColumn::Department:
|
||||
$columns[] = Column::make($col->value)
|
||||
->searchable(true)
|
||||
->orderable(true)
|
||||
->title(formatTitle($col->value));
|
||||
->searchable(false)
|
||||
->title('Dept');
|
||||
break;
|
||||
|
||||
case WorklistColumn::DicomServer:
|
||||
$columns[] = Column::make($col->value)
|
||||
->searchable(false)
|
||||
->title('Server');
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -445,7 +455,9 @@ private function renderCustomColumns(): array
|
||||
};
|
||||
break;
|
||||
case WorklistColumn::StudyDescription:
|
||||
$columns[$col->value] = static fn (Study $study) => $study->sanitizedStudyDescription();
|
||||
$columns[$col->value] = function (Study $study) {
|
||||
return sprintf('<span data-bs-toggle="tooltip" data-bs-placement="top" title="%s">%s</span>', $study->study_description, str_limit($study->sanitizedStudyDescription(), 20));
|
||||
};
|
||||
break;
|
||||
case WorklistColumn::AssignedPhysician:
|
||||
$columns[$col->value] = static function (Study $study) {
|
||||
@ -500,6 +512,13 @@ private function renderCustomColumns(): array
|
||||
case WorklistColumn::ReportButtons:
|
||||
$columns[$col->value] = fn (Study $study) => $this->generateReportingButtons($study);
|
||||
break;
|
||||
case WorklistColumn::DicomServer:
|
||||
$columns[$col->value] = function (Study $study) {
|
||||
return sprintf('<span class="fi fi-%s msg-icon me-1"></span>%s',
|
||||
strtolower($study->dicomServer->geo_code),
|
||||
$study->dicomServer->server_name);
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,21 +2,14 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Domain\Rule\MatchCondition;
|
||||
use App\Models\Traits\Active;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
|
||||
class DicomRoutingRule extends BaseModel
|
||||
{
|
||||
use Active;
|
||||
|
||||
public function conditions(): HasMany
|
||||
{
|
||||
return $this->hasMany(DicomRuleCondition::class);
|
||||
}
|
||||
|
||||
public function organization(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Organization::class);
|
||||
@ -41,7 +34,6 @@ protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'is_active' => 'boolean',
|
||||
'match_condition' => MatchCondition::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Domain\Rule\MatchMode;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
class DicomRuleCondition extends BaseModel
|
||||
{
|
||||
public function rule(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(DicomRoutingRule::class);
|
||||
}
|
||||
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'case_sensitive' => 'boolean',
|
||||
'match_mode' => MatchMode::class,
|
||||
];
|
||||
}
|
||||
}
|
@ -36,4 +36,5 @@ enum WorklistColumn: string
|
||||
case ReportButtons = 'report_buttons';
|
||||
case Organization = 'organization';
|
||||
case Department = 'department';
|
||||
case DicomServer = 'dicom_server';
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ public static function worklistColumns(User|int|null $usr = null): Collection
|
||||
if ($user->isAdmin()) {
|
||||
$columns->push(WorklistColumn::Organization);
|
||||
$columns->push(WorklistColumn::Department);
|
||||
$columns->push(WorklistColumn::DicomServer);
|
||||
}
|
||||
|
||||
return $columns;
|
||||
|
@ -8,6 +8,7 @@
|
||||
use App\Services\Pacs\DicomUtils;
|
||||
use App\Services\Pacs\OrthancRestClient;
|
||||
use App\Services\StudyRouter\DicomStudyRouter;
|
||||
use App\Services\StudyRouter\RawDicomTags;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Illuminate\Pipeline\Pipeline;
|
||||
@ -283,20 +284,21 @@ 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);
|
||||
|
||||
$tags = [];
|
||||
$tags = collect();
|
||||
foreach ($selectedInstances as $instance) {
|
||||
foreach ($this->fetchInstancesTags($instance) as $key => $value) {
|
||||
if ($key == 'MainDicomTags' || $key == 'RequestedTags') {
|
||||
foreach ($value as $tag => $val) {
|
||||
if (! isset($tags[$tag]) || $tags[$tag] !== $val) {
|
||||
$tags[$tag] = $val;
|
||||
$dcmTag = RawDicomTags::tryFrom($tag);
|
||||
if ($dcmTag != null && (! $tags->has($dcmTag->name) || $tags->get($dcmTag->name) !== $val)) {
|
||||
$tags->put($dcmTag->name, $val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $tags;
|
||||
return $tags->toArray();
|
||||
}
|
||||
|
||||
private function setValue(array &$array, string $key, mixed $value): void
|
||||
|
@ -3,16 +3,15 @@
|
||||
namespace App\Services\StudyRouter;
|
||||
|
||||
use App\Domain\ACL\Role;
|
||||
use App\Domain\Rule\MatchCondition;
|
||||
use App\Domain\Rule\MatchMode;
|
||||
use App\Models\AssignmentPanel;
|
||||
use App\Models\DicomRoutingRule;
|
||||
use App\Models\DicomRuleCondition;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use App\Services\ContentMatcher;
|
||||
use Exception;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
|
||||
|
||||
final class DicomStudyRouter
|
||||
{
|
||||
@ -30,22 +29,27 @@ public static function matchStudy(array $dicomHeaders): array
|
||||
return self::fallbackRouting();
|
||||
}
|
||||
|
||||
$study = json_decode(json_encode($dicomHeaders)); // convert to object
|
||||
$expression = new ExpressionLanguage;
|
||||
foreach (self::$rules as $rule) {
|
||||
$conditions = $rule->conditions()->orderByDesc('priority')->get();
|
||||
$matches = $rule->match_condition === MatchCondition::ALL
|
||||
? $conditions->every(fn ($condition) => self::matchCondition($condition, $dicomHeaders))
|
||||
: $conditions->contains(fn ($condition) => self::matchCondition($condition, $dicomHeaders));
|
||||
try {
|
||||
$matches = (bool) $expression->evaluate($rule->condition, ['study' => $study]);
|
||||
} catch (Exception $exc) {
|
||||
Log::error('Error evaluating rule expression', [
|
||||
'rule_id' => $rule->id,
|
||||
'condition' => $rule->condition,
|
||||
'error' => $exc->getMessage(),
|
||||
]);
|
||||
|
||||
/*
|
||||
if ($dicomHeaders[RawDicomTags::Modality->value] === 'CR') {
|
||||
dd($rule, $conditions->toArray(), $matches, $dicomHeaders[RawDicomTags::Modality->value]);
|
||||
return self::fallbackRouting();
|
||||
}
|
||||
*/
|
||||
|
||||
if ($matches) {
|
||||
return [
|
||||
'organization_id' => $rule->organization_id,
|
||||
'department_id' => $rule->department_id,
|
||||
'rule_id' => $rule->id,
|
||||
'rule_name' => $rule->name,
|
||||
'radiologists' => self::getRadiologists($rule),
|
||||
];
|
||||
}
|
||||
@ -70,7 +74,6 @@ private static function initialize(): void
|
||||
self::$rules = Cache::remember('dicom.rules',
|
||||
now()->addMinutes(self::CACHE_TTL),
|
||||
fn () => DicomRoutingRule::active()
|
||||
->with('conditions')
|
||||
->orderByDesc('priority')
|
||||
->get()
|
||||
);
|
||||
@ -92,22 +95,6 @@ private static function initialize(): void
|
||||
}
|
||||
}
|
||||
|
||||
private static function matchCondition(DicomRuleCondition $condition, array $dicomHeaders): bool
|
||||
{
|
||||
$dicomTag = $condition->dicom_tag;
|
||||
$dicomValue = $dicomHeaders[$dicomTag] ?? '';
|
||||
$searchPattern = $condition->search_pattern;
|
||||
|
||||
if (! $condition->case_sensitive) {
|
||||
$dicomValue = strtolower($dicomValue);
|
||||
if ($condition->match_mode !== MatchMode::Regex) {
|
||||
$searchPattern = strtolower($searchPattern);
|
||||
}
|
||||
}
|
||||
|
||||
return ContentMatcher::match($dicomValue, $searchPattern, $condition->match_mode);
|
||||
}
|
||||
|
||||
private static function getRadiologists(DicomRoutingRule $rule): array
|
||||
{
|
||||
if (! is_null($rule->assignment_panel_id)) {
|
||||
|
@ -4,62 +4,62 @@
|
||||
|
||||
enum RawDicomTags: string
|
||||
{
|
||||
case PatientName = '0010,0010'; // Patient's Name
|
||||
case PatientID = '0010,0020'; // Patient ID
|
||||
case PatientBirthDate = '0010,0030'; // Patient's Birth Date
|
||||
case PatientSex = '0010,0040'; // Patient's Sex
|
||||
case StudyInstanceUID = '0020,000D'; // Study Instance UID
|
||||
case SeriesInstanceUID = '0020,000E'; // Series Instance UID
|
||||
case StudyID = '0020,0010'; // Study ID
|
||||
case SeriesNumber = '0020,0011'; // Series Number
|
||||
case InstanceNumber = '0020,0013'; // Instance Number
|
||||
case SOPClassUID = '0008,0016'; // SOP Class UID
|
||||
case SOPInstanceUID = '0008,0018'; // SOP Instance UID
|
||||
case StudyDate = '0008,0020'; // Study Date
|
||||
case StudyTime = '0008,0030'; // Study Time
|
||||
case AccessionNumber = '0008,0050'; // Accession Number
|
||||
case Modality = '0008,0060'; // Modality
|
||||
case Manufacturer = '0008,0070'; // Manufacturer
|
||||
case InstitutionName = '0008,0080'; // Institution Name
|
||||
case ReferringPhysicianName = '0008,0090'; // Referring Physician's Name
|
||||
case StationName = '0008,1010'; // Station Name
|
||||
case SeriesDescription = '0008,103E'; // Series Description
|
||||
case ManufacturerModelName = '0008,1090'; // Manufacturer's Model Name
|
||||
case PatientAge = '0010,1010'; // Patient's Age
|
||||
case PatientWeight = '0010,1030'; // Patient's Weight
|
||||
case BodyPartExamined = '0018,0015'; // Body Part Examined
|
||||
case ProtocolName = '0018,1030'; // Protocol Name
|
||||
case SoftwareVersions = '0018,1020'; // Software Versions
|
||||
case AcquisitionDate = '0008,0022'; // Acquisition Date
|
||||
case AcquisitionTime = '0008,0032'; // Acquisition Time
|
||||
case ContentDate = '0008,0023'; // Content Date
|
||||
case ContentTime = '0008,0033'; // Content Time
|
||||
case AcquisitionDeviceProcessingDescription = '0018,1400'; // Acquisition Device Processing Description
|
||||
case InstitutionAddress = '0008,0081'; // Institution Address
|
||||
case StudyDescription = '0008,1030'; // Study Description
|
||||
case OperatorsName = '0008,1070'; // Operator's Name
|
||||
case Private10 = '0029,0010'; // Private Tag 10
|
||||
case IW_Private = '0009,0010'; // IW Private Tag
|
||||
case ImageType = '0008,0008'; // Image Type
|
||||
case PatientOrientation = '0020,0020'; // Patient Orientation
|
||||
case ImagePositionPatient = '0020,0032'; // Image Position (Patient)
|
||||
case ImageOrientationPatient = '0020,0037'; // Image Orientation (Patient)
|
||||
case FrameOfReferenceUID = '0020,0052'; // Frame of Reference UID
|
||||
case PositionReferenceIndicator = '0020,1040'; // Position Reference Indicator
|
||||
case SliceLocation = '0020,1041'; // Slice Location
|
||||
case SamplesPerPixel = '0028,0002'; // Samples per Pixel
|
||||
case PhotometricInterpretation = '0028,0004'; // Photometric Interpretation
|
||||
case Rows = '0028,0010'; // Rows
|
||||
case Columns = '0028,0011'; // Columns
|
||||
case PixelSpacing = '0028,0030'; // Pixel Spacing
|
||||
case BitsAllocated = '0028,0100'; // Bits Allocated
|
||||
case BitsStored = '0028,0101'; // Bits Stored
|
||||
case HighBit = '0028,0102'; // High Bit
|
||||
case PixelRepresentation = '0028,0103'; // Pixel Representation
|
||||
case WindowCenter = '0028,1050'; // Window Center
|
||||
case WindowWidth = '0028,1051'; // Window Width
|
||||
case RescaleIntercept = '0028,1052'; // Rescale Intercept
|
||||
case RescaleSlope = '0028,1053'; // Rescale Slope
|
||||
case InoWave_Private = '0011,1060';
|
||||
case RadFusion_SenderId = '1971,1020';
|
||||
case patient_name = '0010,0010'; // Patient's Name
|
||||
case patient_id = '0010,0020'; // Patient ID
|
||||
case patient_birth_date = '0010,0030'; // Patient's Birth Date
|
||||
case patient_sex = '0010,0040'; // Patient's Sex
|
||||
case study_instance_uid = '0020,000D'; // Study Instance UID
|
||||
case series_instance_uid = '0020,000E'; // Series Instance UID
|
||||
case study_id = '0020,0010'; // Study ID
|
||||
case series_number = '0020,0011'; // Series Number
|
||||
case instance_number = '0020,0013'; // Instance Number
|
||||
case sop_class_uid = '0008,0016'; // SOP Class UID
|
||||
case sop_instance_uid = '0008,0018'; // SOP Instance UID
|
||||
case study_date = '0008,0020'; // Study Date
|
||||
case study_time = '0008,0030'; // Study Time
|
||||
case accession_number = '0008,0050'; // Accession Number
|
||||
case modality = '0008,0060'; // Modality
|
||||
case manufacturer = '0008,0070'; // Manufacturer
|
||||
case institution_name = '0008,0080'; // Institution Name
|
||||
case referring_physician_name = '0008,0090'; // Referring Physician's Name
|
||||
case station_name = '0008,1010'; // Station Name
|
||||
case series_description = '0008,103E'; // Series Description
|
||||
case manufacturer_model_name = '0008,1090'; // Manufacturer's Model Name
|
||||
case patient_age = '0010,1010'; // Patient's Age
|
||||
case patient_weight = '0010,1030'; // Patient's Weight
|
||||
case body_part_examined = '0018,0015'; // Body Part Examined
|
||||
case protocol_name = '0018,1030'; // Protocol Name
|
||||
case software_versions = '0018,1020'; // Software Versions
|
||||
case acquisition_date = '0008,0022'; // Acquisition Date
|
||||
case acquisition_time = '0008,0032'; // Acquisition Time
|
||||
case content_date = '0008,0023'; // Content Date
|
||||
case content_time = '0008,0033'; // Content Time
|
||||
case acquisition_device_processing_description = '0018,1400'; // Acquisition Device Processing Description
|
||||
case institution_address = '0008,0081'; // Institution Address
|
||||
case study_description = '0008,1030'; // Study Description
|
||||
case operators_name = '0008,1070'; // Operator's Name
|
||||
case private_10 = '0029,0010'; // Private Tag 10
|
||||
case iw_private = '0009,0010'; // IW Private Tag
|
||||
case image_type = '0008,0008'; // Image Type
|
||||
case patient_orientation = '0020,0020'; // Patient Orientation
|
||||
case image_position_patient = '0020,0032'; // Image Position (Patient)
|
||||
case image_orientation_patient = '0020,0037'; // Image Orientation (Patient)
|
||||
case frame_of_reference_uid = '0020,0052'; // Frame of Reference UID
|
||||
case position_reference_indicator = '0020,1040'; // Position Reference Indicator
|
||||
case slice_location = '0020,1041'; // Slice Location
|
||||
case samples_per_pixel = '0028,0002'; // Samples per Pixel
|
||||
case photometric_interpretation = '0028,0004'; // Photometric Interpretation
|
||||
case rows = '0028,0010'; // Rows
|
||||
case columns = '0028,0011'; // Columns
|
||||
case pixel_spacing = '0028,0030'; // Pixel Spacing
|
||||
case bits_allocated = '0028,0100'; // Bits Allocated
|
||||
case bits_stored = '0028,0101'; // Bits Stored
|
||||
case high_bit = '0028,0102'; // High Bit
|
||||
case pixel_representation = '0028,0103'; // Pixel Representation
|
||||
case window_center = '0028,1050'; // Window Center
|
||||
case window_width = '0028,1051'; // Window Width
|
||||
case rescale_intercept = '0028,1052'; // Rescale Intercept
|
||||
case rescale_slope = '0028,1053'; // Rescale Slope
|
||||
case ino_wave_private = '0011,1060';
|
||||
case rad_fusion_sender_id = '1971,1020';
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
"sentry/sentry-laravel": "^4.10",
|
||||
"spatie/laravel-medialibrary": "^11.11",
|
||||
"spatie/laravel-permission": "^6.10",
|
||||
"symfony/expression-language": "^7.2",
|
||||
"vinkla/hashids": "^12.0",
|
||||
"yajra/laravel-datatables": "^11.0"
|
||||
},
|
||||
|
@ -14,6 +14,7 @@ public function up(): void
|
||||
$table->id();
|
||||
$table->boolean('is_active')->index();
|
||||
$table->string('server_name')->unique();
|
||||
$table->string('geo_code', 2)->index();
|
||||
$table->string('host');
|
||||
$table->integer('port');
|
||||
$table->string('rest_api_endpoint');
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
use App\Domain\Rule\MatchCondition;
|
||||
use App\Models\AssignmentPanel;
|
||||
use App\Models\Department;
|
||||
use App\Models\Organization;
|
||||
@ -21,7 +20,7 @@ public function up(): void
|
||||
$table->foreignIdFor(User::class)->nullable()->constrained()->nullOnDelete();
|
||||
$table->foreignIdFor(AssignmentPanel::class)->nullable()->constrained()->nullOnDelete();
|
||||
$table->string('name')->nullable();
|
||||
$table->string('match_condition')->default(MatchCondition::ANY->value);
|
||||
$table->string('condition');
|
||||
$table->unsignedTinyInteger('priority')->default(0);
|
||||
$table->timestamps();
|
||||
|
||||
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Domain\Rule\MatchMode;
|
||||
use App\Models\DicomRoutingRule;
|
||||
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('dicom_rule_conditions', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignIdFor(DicomRoutingRule::class)->constrained()->cascadeOnDelete();
|
||||
$table->string('dicom_tag');
|
||||
$table->string('search_pattern');
|
||||
$table->boolean('case_sensitive')->default(false);
|
||||
$table->string('match_mode')->default(MatchMode::Exact->value);
|
||||
$table->unsignedTinyInteger('priority')->default(0);
|
||||
$table->timestamps();
|
||||
|
||||
$table->index(['dicom_routing_rule_id', 'priority']);
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('dicom_rule_conditions');
|
||||
}
|
||||
};
|
@ -2,14 +2,10 @@
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Domain\Rule\MatchCondition;
|
||||
use App\Domain\Rule\MatchMode;
|
||||
use App\Models\Department;
|
||||
use App\Models\DicomRoutingRule;
|
||||
use App\Models\DicomRuleCondition;
|
||||
use App\Models\DicomServer;
|
||||
use App\Models\Organization;
|
||||
use App\Services\StudyRouter\RawDicomTags;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class OrganizationSeeder extends Seeder
|
||||
@ -36,14 +32,14 @@ public function run(): void
|
||||
$dept_chev_xr = Department::create(
|
||||
[
|
||||
'is_active' => true,
|
||||
'name' => 'Chevron XR',
|
||||
'name' => 'Chev-CR',
|
||||
'organization_id' => $chev->id,
|
||||
]
|
||||
);
|
||||
$chev_dep_ct_mr = Department::create(
|
||||
[
|
||||
'is_active' => true,
|
||||
'name' => 'Chevron CT/MR',
|
||||
'name' => 'Chev-MR',
|
||||
'organization_id' => $chev->id,
|
||||
]
|
||||
);
|
||||
@ -61,7 +57,7 @@ public function run(): void
|
||||
'name' => 'Chevron MR/CT',
|
||||
'organization_id' => $chev->id,
|
||||
'department_id' => $chev_dep_ct_mr->id,
|
||||
'match_condition' => MatchCondition::ALL->value,
|
||||
'condition' => '(study.institution_name ?? "" starts with "chevron") and (study.modality not in ["CR", "DX", "MG"])',
|
||||
]
|
||||
);
|
||||
|
||||
@ -71,45 +67,16 @@ public function run(): void
|
||||
'name' => 'Chevron X-ray',
|
||||
'organization_id' => $chev->id,
|
||||
'department_id' => $dept_chev_xr->id,
|
||||
'match_condition' => MatchCondition::ALL->value,
|
||||
'priority' => 10,
|
||||
'condition' => '(study.institution_name ?? "" starts with "chevron") and (study.modality in ["CR", "DX", "MG"])',
|
||||
'priority' => 99,
|
||||
]
|
||||
);
|
||||
|
||||
DicomRuleCondition::create([
|
||||
'dicom_tag' => RawDicomTags::InstitutionName->value,
|
||||
'search_pattern' => 'chevron',
|
||||
'dicom_routing_rule_id' => $rul_chev_mr_ct->id,
|
||||
'match_mode' => MatchMode::Contains->value,
|
||||
'case_sensitive' => false,
|
||||
]);
|
||||
DicomRuleCondition::create([
|
||||
'dicom_tag' => RawDicomTags::Modality->value,
|
||||
'search_pattern' => 'MR,CT',
|
||||
'dicom_routing_rule_id' => $rul_chev_mr_ct->id,
|
||||
'match_mode' => MatchMode::InList->value,
|
||||
'case_sensitive' => true,
|
||||
]);
|
||||
|
||||
DicomRuleCondition::create([
|
||||
'dicom_tag' => RawDicomTags::InstitutionName->value,
|
||||
'search_pattern' => 'chevron',
|
||||
'dicom_routing_rule_id' => $rul_chev_xr->id,
|
||||
'match_mode' => MatchMode::Contains->value,
|
||||
'case_sensitive' => false,
|
||||
]);
|
||||
DicomRuleCondition::create([
|
||||
'dicom_tag' => RawDicomTags::Modality->value,
|
||||
'search_pattern' => 'CR,DX,MG',
|
||||
'dicom_routing_rule_id' => $rul_chev_xr->id,
|
||||
'match_mode' => MatchMode::InList->value,
|
||||
'case_sensitive' => true,
|
||||
]);
|
||||
|
||||
DicomServer::create(
|
||||
[
|
||||
'is_active' => true,
|
||||
'server_name' => 'Orthanc Main',
|
||||
'server_name' => 'CTG-1',
|
||||
'geo_code' => 'BD',
|
||||
'host' => 'pacs.mylabctg.com',
|
||||
'port' => 8042,
|
||||
'rest_api_endpoint' => 'http://pacs.mylabctg.com:8042/',
|
||||
@ -122,8 +89,9 @@ public function run(): void
|
||||
DicomServer::create(
|
||||
[
|
||||
'is_active' => false,
|
||||
'server_name' => 'Orthanc XR',
|
||||
'server_name' => 'MAA-1',
|
||||
'host' => 'pacs.mylabctg.com',
|
||||
'geo_code' => 'IN',
|
||||
'port' => 8043,
|
||||
'rest_api_endpoint' => 'http://pacs.mylabctg.com:8042/',
|
||||
'ae_title' => 'RADFUSION',
|
||||
|
@ -27,6 +27,8 @@
|
||||
'resources/assets/vendor/libs/bootstrap-datepicker/bootstrap-datepicker.scss',
|
||||
'resources/assets/vendor/libs/bootstrap-daterangepicker/bootstrap-daterangepicker.scss',
|
||||
])
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/7.2.3/css/flag-icons.min.css" crossorigin="anonymous" referrerpolicy="no-referrer" />
|
||||
@endsection
|
||||
|
||||
@section('vendor-script')
|
||||
|
Loading…
Reference in New Issue
Block a user