Files
onboard/app/Data/UnifiedPatientData.php
2026-05-06 22:32:11 +09:00

372 lines
17 KiB
PHP

<?php
namespace App\Data;
use App\Models\DepartmentPatient;
use App\Models\MedicalHistory;
use App\Models\MedicalHistorySnapshot;
use App\Models\MigrationPatient;
use App\Models\MisMedicalHistory;
use App\Models\MisMigrationPatient;
use Carbon\Carbon;
use Carbon\CarbonInterface;
use Illuminate\Support\Collection;
class UnifiedPatientData
{
public function __construct(
public string $id,
public string $patientUid,
public string $sourceType,
public ?int $departmentPatientId,
public ?int $medicalHistoryId,
public string $fullname,
public ?string $birthDate,
public ?int $age,
public array $mkb,
public array $operations,
public ?string $patientKind,
public ?string $admittedAt,
public ?string $outcomeType = null,
public ?string $outcomeDate = null,
public ?string $comment = null,
public ?bool $reanimationIsComplete = null,
public bool $isRecipientToday = false,
public bool $isManual = false,
public bool $canManageManual = false,
) {}
public static function fromMisMedicalHistory(
MisMedicalHistory $patient,
bool $isRecipientToday = false,
?DepartmentPatient $linkedManualPatient = null,
?string $comment = null
): self {
$birthDateValue = $patient->BD ? Carbon::parse($patient->BD) : null;
$birthDate = $birthDateValue?->format('Y-m-d');
$manualId = $linkedManualPatient?->department_patient_id;
$outcomeMigration = $patient->relationLoaded('outcomeMigration')
? $patient->outcomeMigration()->first()
: null;
$migration = $patient->relationLoaded('migrations')
? $patient->migrations->first()
: null;
if (! $migration && $patient->relationLoaded('latestMigration')) {
$migration = $patient->latestMigration;
}
$diagnosisMkb = $outcomeMigration?->mainDiagnosis?->mkb ?? $migration?->mainDiagnosis?->mkb;
$operations = $patient->relationLoaded('surgicalOperations')
? $patient->surgicalOperations->map(fn ($operation) => [
'code' => $operation->serviceMedical?->ServiceMedicalCode,
'name' => $operation->serviceMedical?->ServiceMedicalName,
])->values()->all()
: [];
return new self(
id: $manualId ? "manual:{$manualId}" : "mis:{$patient->MedicalHistoryID}",
patientUid: "mis:{$patient->MedicalHistoryID}",
sourceType: $manualId ? 'manual' : 'mis',
departmentPatientId: $manualId,
medicalHistoryId: $patient->MedicalHistoryID,
fullname: $linkedManualPatient?->full_name ?: mb_convert_case(trim("{$patient->FAMILY} {$patient->Name} {$patient->OT}"), MB_CASE_TITLE, 'UTF-8'),
birthDate: $linkedManualPatient?->birth_date?->format('Y-m-d') ?? $birthDate,
age: $birthDateValue?->age ?? $linkedManualPatient?->birth_date?->age,
mkb: [
'ds' => $linkedManualPatient?->diagnosis_code ?: $diagnosisMkb?->DS,
'name' => $linkedManualPatient?->diagnosis_name ?: $diagnosisMkb?->NAME,
],
operations: $operations,
patientKind: $linkedManualPatient?->patient_kind ?: self::resolvePatientKind($patient->rf_EmerSignID),
admittedAt: $linkedManualPatient?->admitted_at?->toIso8601String() ?? $patient->DateRecipient?->toIso8601String(),
outcomeType: $patient->outcome_type ?? $linkedManualPatient?->outcome_type,
outcomeDate: $patient->outcome_date ?? $linkedManualPatient?->outcome_at?->toIso8601String(),
comment: $comment,
reanimationIsComplete: isset($patient->reanimation_is_complete) ? (bool) $patient->reanimation_is_complete : null,
isRecipientToday: $isRecipientToday,
isManual: (bool) $linkedManualPatient,
canManageManual: (bool) $linkedManualPatient,
);
}
public static function fromMedicalHistory(
MedicalHistory $patient,
bool $isRecipientToday = false,
?DepartmentPatient $linkedManualPatient = null,
?string $comment = null
): self {
$birthDate = $patient->birth_date?->format('Y-m-d');
$manualId = $linkedManualPatient?->department_patient_id;
$historyOriginalId = (int) ($patient->original_id ?? $patient->id);
$migration = $patient->relationLoaded('migrations')
? $patient->migrations->first()
: null;
if (! $migration && $patient->relationLoaded('latestMigration')) {
$migration = $patient->latestMigration;
}
$operations = self::extractOperations($patient->relationLoaded('operations') ? $patient->operations : collect());
return new self(
id: $manualId ? "manual:{$manualId}" : "mis:{$historyOriginalId}",
patientUid: "mis:{$historyOriginalId}",
sourceType: $manualId ? 'manual' : 'mis',
departmentPatientId: $manualId,
medicalHistoryId: $historyOriginalId,
fullname: $linkedManualPatient?->full_name ?: $patient->full_name,
birthDate: $linkedManualPatient?->birth_date?->format('Y-m-d') ?? $birthDate,
age: $patient->birth_date?->age ?? $linkedManualPatient?->birth_date?->age,
mkb: [
'ds' => $linkedManualPatient?->diagnosis_code ?: $migration?->diagnosis_code,
'name' => $linkedManualPatient?->diagnosis_name ?: $migration?->diagnosis_name,
],
operations: $operations,
patientKind: $linkedManualPatient?->patient_kind ?: self::resolvePatientKind($patient->urgency_id),
admittedAt: $linkedManualPatient?->admitted_at?->toIso8601String() ?? $patient->recipient_date?->toIso8601String(),
outcomeType: $patient->outcome_type ?? $linkedManualPatient?->outcome_type,
outcomeDate: $patient->outcome_date ?? $linkedManualPatient?->outcome_at?->toIso8601String(),
comment: $comment,
reanimationIsComplete: isset($patient->reanimation_is_complete) ? (bool) $patient->reanimation_is_complete : null,
isRecipientToday: $isRecipientToday,
isManual: (bool) $linkedManualPatient,
canManageManual: (bool) $linkedManualPatient,
);
}
public static function fromMisMigrationPatient(
MisMigrationPatient $migration,
bool $isRecipientToday = false,
?DepartmentPatient $linkedManualPatient = null,
?string $comment = null
): self {
$birthDateValue = $migration->medicalHistory->BD ? Carbon::parse($migration->medicalHistory->BD) : null;
$birthDate = $birthDateValue?->format('Y-m-d');
$manualId = $linkedManualPatient?->department_patient_id;
$medicalHistory = $migration->medicalHistory;
$outcomeMigration = $medicalHistory->relationLoaded('outcomeMigration')
? $medicalHistory->outcomeMigration()->first()
: null;
$operations = $medicalHistory->relationLoaded('surgicalOperations')
? $medicalHistory->surgicalOperations->map(fn ($operation) => [
'code' => $operation->serviceMedical?->ServiceMedicalCode,
'name' => $operation->serviceMedical?->ServiceMedicalName,
])->values()->all()
: [];
return new self(
id: $manualId ? "manual:{$manualId}" : "mis:{$medicalHistory->MedicalHistoryID}",
patientUid: "mis:{$medicalHistory->MedicalHistoryID}",
sourceType: $manualId ? 'manual' : 'mis',
departmentPatientId: $manualId,
medicalHistoryId: $medicalHistory->MedicalHistoryID,
fullname: $linkedManualPatient?->full_name ?: mb_convert_case(trim("{$medicalHistory->FAMILY} {$medicalHistory->Name} {$medicalHistory->OT}"), MB_CASE_TITLE, 'UTF-8'),
birthDate: $linkedManualPatient?->birth_date?->format('Y-m-d') ?? $birthDate,
age: $birthDateValue?->age ?? $linkedManualPatient?->birth_date?->age,
mkb: [
'ds' => $linkedManualPatient?->diagnosis_code ?: $outcomeMigration?->mainDiagnosis?->mkb?->DS,
'name' => $linkedManualPatient?->diagnosis_name ?: $outcomeMigration?->mainDiagnosis?->mkb?->NAME,
],
operations: $operations,
patientKind: $linkedManualPatient?->patient_kind ?: self::resolvePatientKind($medicalHistory->rf_EmerSignID),
admittedAt: $linkedManualPatient?->admitted_at?->toIso8601String() ?? $medicalHistory->DateRecipient?->toIso8601String(),
outcomeType: $migration->outcome_type ?? $linkedManualPatient?->outcome_type,
outcomeDate: $migration->outcome_date ?? $linkedManualPatient?->outcome_at?->toIso8601String(),
comment: $comment,
reanimationIsComplete: isset($medicalHistory->reanimation_is_complete) ? (bool) $medicalHistory->reanimation_is_complete : null,
isRecipientToday: $isRecipientToday,
isManual: (bool) $linkedManualPatient,
canManageManual: (bool) $linkedManualPatient,
);
}
public static function fromMigrationPatient(
MigrationPatient $migration,
bool $isRecipientToday = false,
?DepartmentPatient $linkedManualPatient = null,
?string $comment = null
): self {
$medicalHistory = $migration->medicalHistory;
$birthDate = $medicalHistory?->birth_date?->format('Y-m-d');
$manualId = $linkedManualPatient?->department_patient_id;
$historyOriginalId = (int) ($medicalHistory?->original_id ?? $medicalHistory?->id ?? 0);
$operations = self::extractOperations(
$medicalHistory && $medicalHistory->relationLoaded('operations')
? $medicalHistory->operations
: collect()
);
return new self(
id: $manualId ? "manual:{$manualId}" : "mis:{$historyOriginalId}",
patientUid: "mis:{$historyOriginalId}",
sourceType: $manualId ? 'manual' : 'mis',
departmentPatientId: $manualId,
medicalHistoryId: $historyOriginalId,
fullname: $linkedManualPatient?->full_name ?: $medicalHistory?->full_name ?: 'Пациент без имени',
birthDate: $linkedManualPatient?->birth_date?->format('Y-m-d') ?? $birthDate,
age: $medicalHistory?->birth_date?->age ?? $linkedManualPatient?->birth_date?->age,
mkb: [
'ds' => $linkedManualPatient?->diagnosis_code ?: $migration->diagnosis_code,
'name' => $linkedManualPatient?->diagnosis_name ?: $migration->diagnosis_name,
],
operations: $operations,
patientKind: $linkedManualPatient?->patient_kind ?: self::resolvePatientKind($medicalHistory?->urgency_id),
admittedAt: $linkedManualPatient?->admitted_at?->toIso8601String() ?? $medicalHistory?->recipient_date?->toIso8601String(),
outcomeType: $migration->outcome_type ?? $linkedManualPatient?->outcome_type,
outcomeDate: $migration->outcome_date ?? $linkedManualPatient?->outcome_at?->toIso8601String(),
comment: $comment,
reanimationIsComplete: isset($medicalHistory->reanimation_is_complete) ? (bool) $medicalHistory->reanimation_is_complete : null,
isRecipientToday: $isRecipientToday,
isManual: (bool) $linkedManualPatient,
canManageManual: (bool) $linkedManualPatient,
);
}
public static function fromDepartmentPatient(
DepartmentPatient $patient,
bool $isRecipientToday = false,
?array $operations = null,
?string $comment = null
): self {
return new self(
id: "manual:{$patient->department_patient_id}",
patientUid: $patient->rf_medicalhistory_id ? "mis:{$patient->rf_medicalhistory_id}" : "manual:{$patient->department_patient_id}",
sourceType: 'manual',
departmentPatientId: $patient->department_patient_id,
medicalHistoryId: $patient->rf_medicalhistory_id,
fullname: $patient->full_name,
birthDate: $patient->birth_date?->format('Y-m-d'),
age: $patient->birth_date?->age,
mkb: [
'ds' => $patient->diagnosis_code,
'name' => $patient->diagnosis_name,
],
operations: $operations ?? [],
patientKind: $patient->patient_kind,
admittedAt: $patient->admitted_at?->toIso8601String(),
outcomeType: $patient->outcome_type,
outcomeDate: $patient->outcome_at?->toIso8601String(),
comment: $comment,
reanimationIsComplete: null,
isRecipientToday: $isRecipientToday,
isManual: true,
canManageManual: true,
);
}
public static function fromSnapshot(
MedicalHistorySnapshot $snapshot,
bool $isRecipientToday = false,
?array $operations = null
): self {
$birthDate = self::normalizeDate($snapshot->birth_date);
// if ($snapshot->rf_medicalhistory_id === 334148)
// dd($snapshot);
return new self(
id: $snapshot->rf_department_patient_id ? "manual:{$snapshot->rf_department_patient_id}" : ($snapshot->patient_uid ?: "mis:{$snapshot->rf_medicalhistory_id}"),
patientUid: $snapshot->patient_uid ?: ($snapshot->rf_medicalhistory_id ? "mis:{$snapshot->rf_medicalhistory_id}" : "snapshot:{$snapshot->medical_history_snapshot_id}"),
sourceType: $snapshot->patient_source_type ?: ($snapshot->is_manual ? 'manual' : 'mis'),
departmentPatientId: $snapshot->rf_department_patient_id,
medicalHistoryId: $snapshot->rf_medicalhistory_id,
fullname: $snapshot->full_name ?: 'Пациент без имени',
birthDate: $birthDate,
age: $birthDate ? now()->diffInYears($birthDate) : null,
mkb: [
'ds' => $snapshot->diagnosis_code,
'name' => $snapshot->diagnosis_name,
],
operations: $operations ?? [],
patientKind: $snapshot->patient_kind,
admittedAt: self::normalizeDateTime($snapshot->admitted_at),
outcomeType: $snapshot->outcome_type,
outcomeDate: self::normalizeDateTime($snapshot->outcome_at),
comment: null,
reanimationIsComplete: null,
isRecipientToday: $isRecipientToday,
isManual: (bool) $snapshot->is_manual,
canManageManual: false,
);
}
public function toSnapshotPayload(string $patientType): array
{
return [
'rf_medicalhistory_id' => $this->medicalHistoryId,
'rf_department_patient_id' => $this->departmentPatientId,
'patient_type' => $patientType,
'patient_uid' => $this->patientUid,
'patient_source_type' => $this->sourceType,
'patient_kind' => $this->patientKind,
'full_name' => $this->fullname,
'birth_date' => $this->birthDate,
'diagnosis_code' => $this->mkb['ds'] ?? null,
'diagnosis_name' => $this->mkb['name'] ?? null,
'admitted_at' => $this->admittedAt,
'outcome_type' => $this->outcomeType,
'outcome_at' => $this->outcomeDate,
'is_manual' => $this->isManual,
];
}
public static function unique(Collection $patients): Collection
{
return $patients->unique(fn (self $patient) => $patient->patientUid)->values();
}
private static function resolvePatientKind(?int $emerSignId): ?string
{
return match ($emerSignId) {
1 => 'plan',
2, 4 => 'emergency',
default => null,
};
}
private static function extractOperations(Collection $operations): array
{
return $operations->map(function ($operation) {
$code = $operation->service_medical_code
?? $operation->serviceMedical?->ServiceMedicalCode
?? $operation->serviceMedical?->ServiceMedicalID
?? null;
$name = $operation->service_medical_name
?? $operation->serviceMedical?->ServiceMedicalName
?? null;
return [
'code' => $code,
'name' => $name,
];
})->values()->all();
}
private static function normalizeDateTime($value): ?string
{
if (! $value) {
return null;
}
if ($value instanceof CarbonInterface) {
return $value->toIso8601String();
}
return (string) $value;
}
private static function normalizeDate($value): ?string
{
if (! $value) {
return null;
}
if ($value instanceof CarbonInterface) {
return $value->format('Y-m-d');
}
return (string) $value;
}
}