Files
gravity/บริหารจัดการคิวนวดแผนไทย/app/Services/FhirService.php
T
2026-09-16 23:20:08 +07:00

141 lines
4.7 KiB
PHP

<?php
namespace App\Services;
/**
* Class FhirService
* HL7 FHIR R4 Interoperability Engine (Patient, Encounter, Observation, Procedure)
*
* @package App\Services
*/
class FhirService
{
private string $serverUrl;
private string $facilityId;
public function __construct()
{
$config = require __DIR__ . '/../../config/integration.php';
$fhir = $config['fhir'];
$this->serverUrl = rtrim($fhir['server_url'], '/');
$this->facilityId = $fhir['facility_id'] ?? 'THAI_MED_CENTER';
}
/**
* Build FHIR R4 Patient Resource
*/
public function buildPatientResource(array $patient): array
{
return [
'resourceType' => 'Patient',
'id' => (string)$patient['id'],
'identifier' => [
[
'use' => 'official',
'system' => 'https://www.dopa.go.th/cid',
'value' => $patient['cid'],
],
[
'use' => 'usual',
'system' => "https://his.hospital.local/hn/{$this->facilityId}",
'value' => $patient['hn'],
]
],
'active' => true,
'name' => [
[
'use' => 'official',
'text' => trim(($patient['first_name_th'] ?? '') . ' ' . ($patient['last_name_th'] ?? '')),
'family' => $patient['last_name_th'] ?? '',
'given' => [$patient['first_name_th'] ?? ''],
]
],
'gender' => strtolower($patient['gender'] ?? 'unknown'),
'birthDate' => $patient['birth_date'] ?? null,
'telecom' => [
[
'system' => 'phone',
'value' => $patient['phone'] ?? '',
'use' => 'mobile',
]
],
];
}
/**
* Build FHIR R4 Observation Resource for Pain Score (VAS 0-10)
*/
public function buildPainScoreObservation(int $patientId, int $encounterId, int $painScore, string $type = 'Pre-treatment'): array
{
return [
'resourceType' => 'Observation',
'status' => 'final',
'category' => [
[
'coding' => [
[
'system' => 'http://terminology.hl7.org/CodeSystem/observation-category',
'code' => 'exam',
'display' => 'Exam',
]
]
]
],
'code' => [
'coding' => [
[
'system' => 'http://loinc.org',
'code' => '72514-3',
'display' => 'Pain severity - 0-10 verbal numeric rating [Score] - Reported',
]
],
'text' => "VAS Pain Score ({$type})",
],
'subject' => [
'reference' => "Patient/{$patientId}",
],
'encounter' => [
'reference' => "Encounter/{$encounterId}",
],
'effectiveDateTime' => date('c'),
'valueInteger' => $painScore,
];
}
/**
* Export complete bundle to FHIR Server
*/
public function exportEncounterBundle(array $queue, array $soapNote): array
{
$patientRes = $this->buildPatientResource(['id' => $queue['patient_id'], 'cid' => $queue['cid'] ?? '', 'hn' => $queue['hn'] ?? '', 'first_name_th' => $queue['patient_name'] ?? '']);
$bundle = [
'resourceType' => 'Bundle',
'type' => 'transaction',
'entry' => [
[
'resource' => $patientRes,
'request' => ['method' => 'PUT', 'url' => "Patient/{$queue['patient_id']}"],
]
],
];
if (isset($soapNote['pre_pain_score'])) {
$obsPre = $this->buildPainScoreObservation((int)$queue['patient_id'], (int)$queue['id'], (int)$soapNote['pre_pain_score'], 'Pre-treatment');
$bundle['entry'][] = [
'resource' => $obsPre,
'request' => ['method' => 'POST', 'url' => "Observation"],
];
}
if (isset($soapNote['post_pain_score'])) {
$obsPost = $this->buildPainScoreObservation((int)$queue['patient_id'], (int)$queue['id'], (int)$soapNote['post_pain_score'], 'Post-treatment');
$bundle['entry'][] = [
'resource' => $obsPost,
'request' => ['method' => 'POST', 'url' => "Observation"],
];
}
return $bundle;
}
}