Работа над журналом для ст. мед сестер
This commit is contained in:
@@ -0,0 +1,256 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Reports\Services;
|
||||
|
||||
use App\Models\Department;
|
||||
use App\Models\DepartmentPatient;
|
||||
use App\Models\DepartmentPatientOperation;
|
||||
use App\Models\MedicalHistorySnapshot;
|
||||
use App\Models\MisServiceMedical;
|
||||
use App\Models\Report;
|
||||
use App\Models\User;
|
||||
use App\Services\DateRangeService;
|
||||
use App\Services\UnifiedPatientService;
|
||||
use Illuminate\Support\Collection;
|
||||
use InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Управляет manual/special пациентами отчёта и их операциями.
|
||||
*
|
||||
* Сервис держит orchestration вокруг legacy UnifiedPatientService, пока
|
||||
* patient-write сценарии постепенно выносятся из ReportService.
|
||||
*/
|
||||
class ManualPatientManagementService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DateRangeService $dateRangeService,
|
||||
private readonly UnifiedPatientService $unifiedPatientService,
|
||||
private readonly ReportReadContextResolver $contextResolver,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function createManualPatient(Department $department, User $user, array $data): DepartmentPatient
|
||||
{
|
||||
$report = $this->resolveReportForManualPatient($department, $user, $data);
|
||||
|
||||
return $this->unifiedPatientService->createManualPatient($department, $user, $data, $report->report_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function setManualPatientOutcome(User $user, int $departmentPatientId, array $data): DepartmentPatient
|
||||
{
|
||||
$patient = DepartmentPatient::query()
|
||||
->where('department_patient_id', $departmentPatientId)
|
||||
->firstOrFail();
|
||||
|
||||
$updatedPatient = $this->unifiedPatientService->recordManualOutcome($patient, $data);
|
||||
$this->syncManualPatientSnapshots($updatedPatient, $user, []);
|
||||
|
||||
return $updatedPatient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function updateManualPatient(User $user, int $departmentPatientId, array $data): DepartmentPatient
|
||||
{
|
||||
$patient = $this->resolveManageableManualPatient($user, $departmentPatientId);
|
||||
|
||||
$updatedPatient = $this->unifiedPatientService->updateManualPatient($patient, $data);
|
||||
$this->syncManualPatientSnapshots($updatedPatient, $user, $data);
|
||||
|
||||
return $updatedPatient;
|
||||
}
|
||||
|
||||
public function linkManualPatientToMis(int $departmentPatientId, int $medicalHistoryId): DepartmentPatient
|
||||
{
|
||||
$patient = DepartmentPatient::query()
|
||||
->where('department_patient_id', $departmentPatientId)
|
||||
->firstOrFail();
|
||||
|
||||
return $this->unifiedPatientService->linkManualPatientToMis($patient, $medicalHistoryId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, DepartmentPatientOperation>
|
||||
*/
|
||||
public function getManualPatientOperations(User $user, int $departmentPatientId): Collection
|
||||
{
|
||||
$patient = $this->resolveManageableManualPatient($user, $departmentPatientId);
|
||||
|
||||
return $patient->operations()
|
||||
->with('serviceMedical')
|
||||
->orderByDesc('started_at')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function createManualPatientOperation(
|
||||
User $user,
|
||||
int $departmentPatientId,
|
||||
array $data
|
||||
): DepartmentPatientOperation {
|
||||
$patient = $this->resolveManageableManualPatient($user, $departmentPatientId);
|
||||
$service = $this->resolveMedicalService((int) $data['service_id']);
|
||||
|
||||
return $patient->operations()->create([
|
||||
'rf_kl_service_medical_id' => $service->ServiceMedicalID,
|
||||
'service_code' => $service->ServiceMedicalCode,
|
||||
'service_name' => $service->ServiceMedicalName,
|
||||
'urgency' => $data['urgency'],
|
||||
'started_at' => $data['started_at'],
|
||||
'ended_at' => $data['ended_at'],
|
||||
'created_by' => $user->id,
|
||||
])->load('serviceMedical');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function updateManualPatientOperation(
|
||||
User $user,
|
||||
int $departmentPatientId,
|
||||
int $operationId,
|
||||
array $data
|
||||
): DepartmentPatientOperation {
|
||||
$patient = $this->resolveManageableManualPatient($user, $departmentPatientId);
|
||||
$service = $this->resolveMedicalService((int) $data['service_id']);
|
||||
|
||||
$operation = $patient->operations()
|
||||
->where('department_patient_operation_id', $operationId)
|
||||
->firstOrFail();
|
||||
|
||||
$operation->update([
|
||||
'rf_kl_service_medical_id' => $service->ServiceMedicalID,
|
||||
'service_code' => $service->ServiceMedicalCode,
|
||||
'service_name' => $service->ServiceMedicalName,
|
||||
'urgency' => $data['urgency'],
|
||||
'started_at' => $data['started_at'],
|
||||
'ended_at' => $data['ended_at'],
|
||||
]);
|
||||
|
||||
return $operation->fresh()->load('serviceMedical');
|
||||
}
|
||||
|
||||
public function deleteManualPatientOperation(User $user, int $departmentPatientId, int $operationId): void
|
||||
{
|
||||
$patient = $this->resolveManageableManualPatient($user, $departmentPatientId);
|
||||
|
||||
$patient->operations()
|
||||
->where('department_patient_operation_id', $operationId)
|
||||
->firstOrFail()
|
||||
->delete();
|
||||
}
|
||||
|
||||
private function resolveManageableManualPatient(User $user, int $departmentPatientId): DepartmentPatient
|
||||
{
|
||||
$query = DepartmentPatient::query()
|
||||
->where('department_patient_id', $departmentPatientId)
|
||||
->whereIn('source_type', ['manual', 'special']);
|
||||
|
||||
if (! $user->isAdmin() && ! $user->isHeadOfDepartment()) {
|
||||
$query->where('rf_department_id', $user->department->department_id);
|
||||
}
|
||||
|
||||
return $query->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
private function syncManualPatientSnapshots(DepartmentPatient $patient, User $user, array $data): void
|
||||
{
|
||||
$reportIds = $patient->rf_report_id
|
||||
? [$patient->rf_report_id]
|
||||
: (isset($data['startAt'], $data['endAt']) && $data['startAt'] && $data['endAt']
|
||||
? $this->contextResolver
|
||||
->getReportsForDateRange(
|
||||
$patient->rf_department_id,
|
||||
$this->dateRangeService->getNormalizedDateRange(
|
||||
$user,
|
||||
(string) $data['startAt'],
|
||||
(string) $data['endAt']
|
||||
)
|
||||
)
|
||||
->pluck('report_id')
|
||||
->values()
|
||||
->all()
|
||||
: []);
|
||||
|
||||
if (empty($reportIds)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MedicalHistorySnapshot::query()
|
||||
->whereIn('rf_report_id', $reportIds)
|
||||
->where('rf_department_patient_id', $patient->department_patient_id)
|
||||
->update([
|
||||
'patient_kind' => $patient->patient_kind,
|
||||
'full_name' => $patient->full_name,
|
||||
'birth_date' => $patient->birth_date,
|
||||
'diagnosis_code' => $patient->diagnosis_code,
|
||||
'diagnosis_name' => $patient->diagnosis_name,
|
||||
'admitted_at' => $patient->admitted_at,
|
||||
'outcome_type' => $patient->is_current ? null : $patient->outcome_type,
|
||||
'outcome_at' => $patient->is_current ? null : $patient->outcome_at,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
private function resolveReportForManualPatient(Department $department, User $user, array $data): Report
|
||||
{
|
||||
$reportId = $data['report_id'] ?? null;
|
||||
if ($reportId) {
|
||||
return Report::query()
|
||||
->where('report_id', $reportId)
|
||||
->where('rf_department_id', $department->department_id)
|
||||
->firstOrFail();
|
||||
}
|
||||
|
||||
if (! isset($data['startAt'], $data['endAt']) || ! $data['startAt'] || ! $data['endAt']) {
|
||||
throw new InvalidArgumentException('Не указан отчет или диапазон для привязки спецконтингента');
|
||||
}
|
||||
|
||||
$dateRange = $this->dateRangeService->getNormalizedDateRange(
|
||||
$user,
|
||||
(string) $data['startAt'],
|
||||
(string) $data['endAt']
|
||||
);
|
||||
|
||||
$existingReport = Report::query()
|
||||
->where('rf_department_id', $department->department_id)
|
||||
->exactPeriod($dateRange->startSql(), $dateRange->endSql())
|
||||
->first();
|
||||
|
||||
if ($existingReport) {
|
||||
return $existingReport;
|
||||
}
|
||||
|
||||
return Report::query()->create([
|
||||
'rf_department_id' => $department->department_id,
|
||||
'rf_user_id' => $user->id,
|
||||
'rf_lpudoctor_id' => $data['user_id'] ?? $user->rf_lpudoctor_id,
|
||||
'sent_at' => $dateRange->endSql(),
|
||||
'created_at' => $dateRange->endSql(),
|
||||
'period_start' => $dateRange->startSql(),
|
||||
'period_end' => $dateRange->endSql(),
|
||||
'status' => 'draft',
|
||||
]);
|
||||
}
|
||||
|
||||
private function resolveMedicalService(int $serviceId): MisServiceMedical
|
||||
{
|
||||
return MisServiceMedical::query()
|
||||
->where('ServiceMedicalID', $serviceId)
|
||||
->firstOrFail();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user