Перевод на DDD
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Database\Repositories;
|
||||
|
||||
use App\Domain\ReportDuty\Contracts\DutyMetricRepositoryInterface;
|
||||
use App\Models\DutyReportMetricResult;
|
||||
|
||||
class DutyMetricRepository implements DutyMetricRepositoryInterface
|
||||
{
|
||||
public function saveMetric(int $reportId, int $metricId, float|int $value): void
|
||||
{
|
||||
DutyReportMetricResult::updateOrCreate(
|
||||
['rf_report_id' => $reportId, 'rf_metrika_item_id' => $metricId],
|
||||
['value' => $value]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Database\Repositories\Patient;
|
||||
|
||||
use App\Domain\Patient\Contracts\PatientRepositoryInterface;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class PatientRepository implements PatientRepositoryInterface
|
||||
{
|
||||
private const TABLE = 'stt_LastJournalHistoryEntry';
|
||||
private const TTL = 300;
|
||||
private const TTL_KEY = 'mis:journal:';
|
||||
private const JOURNAL_SELECT = [
|
||||
'lj.LastJournalHistoryEntryID', 'lj.rf_MedicalHistoryID', 'lj.rf_MigrationPatientID',
|
||||
'lj.rf_ExtractMigrationPatientId', 'lj.rf_DiagnosID', 'lj.rf_AttendingDoctorID',
|
||||
'lj.rf_BedActionID', 'mh.MedicalHistoryID', 'mh.FAMILY', 'mh.Name', 'mh.OT', 'mh.BD', 'mh.DateRecipient',
|
||||
'mh.DateExtract', 'mp.DateIngoing', 'mp.DateOut', 'mp.rf_StationarBranchID', 'd.DepartmentNAME'
|
||||
];
|
||||
|
||||
public function getCurrentByDepartmentId(int $departmentId): ?\Illuminate\Support\Collection
|
||||
{
|
||||
$query = DB::connection('mis')->table('stt_LastJournalHistoryEntry as lj')
|
||||
->join('stt_MedicalHistory as mh', 'mh.MedicalHistoryID', '=', 'lj.rf_MedicalHistoryID')
|
||||
->join('stt_MigrationPatient as mp', 'mp.MigrationPatientID', '=', 'lj.rf_MigrationPatientID')
|
||||
->leftJoin('stt_StationarBranch as sb', 'sb.StationarBranchID', '=', 'mp.rf_StationarBranchID')
|
||||
->leftJoin('oms_Department as d', 'd.DepartmentID', '=', 'sb.rf_DepartmentID')
|
||||
->select($this::JOURNAL_SELECT)
|
||||
->where('lj.rf_ExtractMigrationPatientId', '=', 0)
|
||||
->where('d.DepartmentID', '=', $departmentId)
|
||||
->orderBy('mh.DateRecipient');
|
||||
|
||||
$results = Cache::remember($this::TTL_KEY . $departmentId, $this::TTL, function () use ($query) {
|
||||
return $query->get();
|
||||
});
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function getById(int $patientId)
|
||||
{
|
||||
// TODO: Implement getById() method.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Database\Repositories;
|
||||
|
||||
use App\Domain\ReportDuty\Contracts\ReportDutyObservablePatientsInterface;
|
||||
use App\Domain\ReportDuty\Models\ReportDuty;
|
||||
use App\Models\ObservableMedicalHistory;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
|
||||
class ReportDutyObservablePatients implements ReportDutyObservablePatientsInterface
|
||||
{
|
||||
public function upsertObservations(ReportDuty $report, array $observables): ?LazyCollection
|
||||
{
|
||||
foreach ($observables as $observable) {
|
||||
ObservableMedicalHistory::updateOrCreate([
|
||||
'original_id' => $observable['original_id'] ?? $observable['id'],
|
||||
'source_type' => $observable['source_type'] ?? 'mis',
|
||||
'observable_in' => $observable['observable_in'] ?? $report->period_start,
|
||||
], [
|
||||
'source_type' => $observable['source_type'] ?? 'mis',
|
||||
'original_id' => $observable['original_id'] ?? $observable['id'],
|
||||
'observable_in' => $observable['observable_in'] ?? $report->period_start,
|
||||
'observable_out' => $observable['observable_out'] ?? null,
|
||||
'observable_reason' => $observable['observable_reason'],
|
||||
'out_reason' => $observable['out_reason'] ?? null,
|
||||
'medical_card_number' => $observable['medical_card_number'],
|
||||
'full_name' => $observable['full_name'],
|
||||
'birth_date' => $observable['birth_date'],
|
||||
'recipient_date' => $observable['recipient_date'],
|
||||
'extract_date' => $observable['extract_date'],
|
||||
'death_date' => $observable['death_date'],
|
||||
'male' => $observable['male'],
|
||||
'urgency_id' => $observable['urgency_id'],
|
||||
'hospital_result_id' => $observable['hospital_result_id'],
|
||||
'visit_result_id' => $observable['visit_result_id'],
|
||||
'comment' => $observable['observable_reason'],
|
||||
'user_id' => $report->rf_user_id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Database\Repositories;
|
||||
|
||||
use App\Domain\ReportDuty\Contracts\ReportDutyRepositoryInterface;
|
||||
use App\Domain\ReportDuty\DTO\CreateReportDutyDto;
|
||||
use Illuminate\Support\Carbon;
|
||||
use App\Domain\ReportDuty\Models\ReportDuty;
|
||||
|
||||
class ReportDutyRepository implements ReportDutyRepositoryInterface
|
||||
{
|
||||
public function findOrCreate(CreateReportDutyDto $dto): ?ReportDuty
|
||||
{
|
||||
$attributes = [
|
||||
'report_date' => $dto->reportDate,
|
||||
'period_start' => $dto->periodStart,
|
||||
'period_end' => $dto->periodEnd,
|
||||
'rf_department_id' => $dto->rfDepartmentId,
|
||||
];
|
||||
|
||||
$data = [
|
||||
'report_date' => $dto->reportDate,
|
||||
'sent_at' => Carbon::now()->format('Y-m-d H:i:s'),
|
||||
'period_type' => $dto->periodType,
|
||||
'period_start' => $dto->periodStart,
|
||||
'period_end' => $dto->periodEnd,
|
||||
'status_id' => $dto->statusId,
|
||||
'rf_lpudoctor_id' => $dto->rfLpuDoctorId,
|
||||
'rf_department_id' => $dto->rfDepartmentId,
|
||||
'rf_user_id' => $dto->rfUserId,
|
||||
];
|
||||
|
||||
// Проверяем существование
|
||||
$exists = ReportDuty::where($attributes)->exists();
|
||||
|
||||
if ($exists) {
|
||||
// Если существует, обновляем только некоторые поля
|
||||
$updateData = array_diff_key($data, array_flip(['rf_lpudoctor_id', 'rf_user_id']));
|
||||
$report = ReportDuty::updateOrCreate($attributes, $updateData);
|
||||
} else {
|
||||
$report = ReportDuty::create($data);
|
||||
}
|
||||
|
||||
return $report;
|
||||
}
|
||||
|
||||
public function save(\App\Domain\ReportDuty\Models\ReportDuty $reportDuty): ?\App\Domain\ReportDuty\Models\ReportDuty
|
||||
{
|
||||
// TODO: Implement save() method.
|
||||
}
|
||||
|
||||
public function update(\App\Domain\ReportDuty\Models\ReportDuty $reportDuty): ?\App\Domain\ReportDuty\Models\ReportDuty
|
||||
{
|
||||
// TODO: Implement update() method.
|
||||
}
|
||||
|
||||
public function findByPeriod(string $startAt, string $endAt): ?\App\Domain\ReportDuty\Models\ReportDuty
|
||||
{
|
||||
// TODO: Implement findByPeriod() method.
|
||||
}
|
||||
|
||||
public function findByDepartment(int $departmentId): ?\App\Domain\ReportDuty\Models\ReportDuty
|
||||
{
|
||||
// TODO: Implement findByDepartment() method.
|
||||
}
|
||||
|
||||
public function findByUser(int $userId): ?\App\Domain\ReportDuty\Models\ReportDuty
|
||||
{
|
||||
// TODO: Implement findByUser() method.
|
||||
}
|
||||
|
||||
public function findById(int $id): ?\App\Domain\ReportDuty\Models\ReportDuty
|
||||
{
|
||||
// TODO: Implement findById() method.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Database\Repositories;
|
||||
|
||||
use App\Domain\ReportDuty\Contracts\ReportDutySnapshotRepositoryInterface;
|
||||
use App\Domain\ReportDuty\DTO\MigrationSnapshotData;
|
||||
use App\Domain\ReportDuty\DTO\PatientSnapshotData;
|
||||
use App\Domain\ReportDuty\DTO\ReanimationSnapshotData;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
|
||||
class ReportDutySnapshotRepository implements ReportDutySnapshotRepositoryInterface
|
||||
{
|
||||
public function upsertSnapshot(
|
||||
int $reportDutyId,
|
||||
LazyCollection $patients,
|
||||
LazyCollection $migrations,
|
||||
LazyCollection $reanimations,
|
||||
int $userId,
|
||||
int $departmentId
|
||||
): array {
|
||||
if ($patients->isEmpty()) {
|
||||
return ['savedPatients' => 0, 'savedMigrations' => 0, 'savedReanimations' => 0];
|
||||
}
|
||||
|
||||
$savedPatients = 0;
|
||||
$savedMigrations = 0;
|
||||
$savedReanimations = 0;
|
||||
|
||||
DB::transaction(function () use (
|
||||
$reportDutyId,
|
||||
$patients,
|
||||
$migrations,
|
||||
$reanimations,
|
||||
$userId,
|
||||
$departmentId,
|
||||
&$savedPatients,
|
||||
&$savedMigrations,
|
||||
&$savedReanimations
|
||||
) {
|
||||
// Получаем дату окончания периода отчета (для фильтрации дат смерти)
|
||||
$reportEndDate = DB::table('report_duties')
|
||||
->where('id', $reportDutyId)
|
||||
->value('period_end');
|
||||
|
||||
// === 1. Подготовка данных пациентов ===
|
||||
$patientBatch = [];
|
||||
foreach ($patients as $patient) {
|
||||
/** @var PatientSnapshotData $patient */
|
||||
// Преобразуем в массив для upsert
|
||||
$patientData = [
|
||||
'report_duty_id' => $reportDutyId,
|
||||
'source_type' => $patient->sourceType,
|
||||
'original_id' => $patient->id,
|
||||
'medical_card_number' => $patient->medicalCardNumber,
|
||||
'full_name' => $patient->fullName,
|
||||
'birth_date' => $patient->birthDate,
|
||||
'recipient_date' => $patient->recipientDate,
|
||||
'male' => $patient->male,
|
||||
'urgency_id' => $patient->urgencyId,
|
||||
'comment' => $patient->comment,
|
||||
'user_id' => $userId,
|
||||
'profit_type_id' => $patient->profitTypeId,
|
||||
];
|
||||
|
||||
// Обработка даты смерти и выбытия
|
||||
if (!empty($patient->deathDate)) {
|
||||
$deathDate = Carbon::parse($patient->deathDate);
|
||||
$extractDate = $patient->extractDate ? Carbon::parse($patient->extractDate) : null;
|
||||
$visitResultId = $patient->visitResultId;
|
||||
|
||||
// Если исход смерти (visit_result_id 5 или 15) и дата смерти позже даты отчёта - очищаем
|
||||
if (in_array($visitResultId, [5, 15]) && $deathDate->gt($reportEndDate)) {
|
||||
$patientData['death_date'] = null;
|
||||
} else {
|
||||
$patientData['death_date'] = $deathDate->format('Y-m-d');
|
||||
}
|
||||
|
||||
// Если пациент умер, а даты выбытия нет, используем дату смерти
|
||||
if (!empty($patientData['death_date']) && empty($patientData['extract_date'])) {
|
||||
$patientData['extract_date'] = $patientData['death_date'];
|
||||
}
|
||||
} else {
|
||||
// Если нет даты смерти, используем extract_date как есть
|
||||
$patientData['extract_date'] = $patient->extractDate;
|
||||
$patientData['death_date'] = null;
|
||||
}
|
||||
|
||||
// Добавляем visit_result_id (если есть)
|
||||
$patientData['visit_result_id'] = $patient->visitResultId;
|
||||
$patientData['extract_date'] = $patientData['extract_date'] ?? null;
|
||||
|
||||
$patientBatch[] = $patientData;
|
||||
}
|
||||
|
||||
// === 2. Upsert пациентов ===
|
||||
$patientUniqueBy = ['report_duty_id', 'source_type', 'original_id'];
|
||||
$patientUpdateColumns = array_diff(array_keys($patientBatch[0]), $patientUniqueBy);
|
||||
|
||||
DB::table('report_duty_patients')->upsert(
|
||||
$patientBatch,
|
||||
$patientUniqueBy,
|
||||
$patientUpdateColumns
|
||||
);
|
||||
$savedPatients = count($patientBatch);
|
||||
|
||||
// === 3. Получаем ID сохранённых пациентов (для связей с миграциями) ===
|
||||
$patientIds = [];
|
||||
if ($migrations->isNotEmpty() || $reanimations->isNotEmpty()) {
|
||||
$patientIds = DB::table('report_duty_patients')
|
||||
->where('report_duty_id', $reportDutyId)
|
||||
->pluck('id', 'original_id')
|
||||
->toArray();
|
||||
}
|
||||
|
||||
// === 4. Подготовка и Upsert миграций ===
|
||||
if ($migrations->isNotEmpty() && !empty($patientIds)) {
|
||||
$migrationBatch = [];
|
||||
/** @var MigrationSnapshotData $migration */
|
||||
foreach ($migrations as $migration) {
|
||||
$patientDbId = $patientIds[$migration->medicalHistoryId] ?? null;
|
||||
if (!$patientDbId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$migrationBatch[] = [
|
||||
'medical_history_id' => $patientDbId,
|
||||
'original_id' => $migration->id,
|
||||
'ingoing_date' => $migration->ingoingDate,
|
||||
'out_date' => $migration->outDate,
|
||||
'diagnosis_id' => $migration->diagnosisId,
|
||||
'diagnosis_code' => $migration->diagnosisCode,
|
||||
'diagnosis_name' => $migration->diagnosisName,
|
||||
'interrupted_event_id' => $migration->interruptedEventId,
|
||||
'stationar_branch_id' => $migration->stationarBranchId,
|
||||
'department_id' => $migration->departmentId,
|
||||
'visit_result_id' => $migration->visitResultId,
|
||||
'stat_cure_result_id' => $migration->statCureResultId,
|
||||
'user_id' => $migration->userId,
|
||||
'mis_user_id' => $migration->misUserId,
|
||||
'comment' => $migration->comment,
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($migrationBatch)) {
|
||||
$migrationUniqueBy = ['medical_history_id', 'ingoing_date'];
|
||||
$migrationUpdateColumns = array_diff(array_keys($migrationBatch[0]), $migrationUniqueBy);
|
||||
|
||||
DB::table('report_duty_migration_patients')->upsert(
|
||||
$migrationBatch,
|
||||
$migrationUniqueBy,
|
||||
$migrationUpdateColumns
|
||||
);
|
||||
$savedMigrations = count($migrationBatch);
|
||||
|
||||
// === 5. Получаем ID сохранённых миграций для реанимаций ===
|
||||
// Строим маппинг [medical_history_id][original_id] => id
|
||||
$migrationIds = [];
|
||||
$migrationRecords = DB::table('report_duty_migration_patients')
|
||||
->whereIn('medical_history_id', array_values($patientIds))
|
||||
->get(['id', 'medical_history_id', 'original_id']);
|
||||
|
||||
foreach ($migrationRecords as $record) {
|
||||
$migrationIds[$record->medical_history_id][$record->original_id] = $record->id;
|
||||
}
|
||||
|
||||
// === 6. Подготовка и Upsert реанимаций ===
|
||||
if ($reanimations->isNotEmpty()) {
|
||||
$reanimationBatch = [];
|
||||
/** @var ReanimationSnapshotData $reanimation */
|
||||
foreach ($reanimations as $reanimation) {
|
||||
$patientDbId = $patientIds[$reanimation->medicalHistoryId] ?? null;
|
||||
if (!$patientDbId) {
|
||||
continue;
|
||||
}
|
||||
$migrationDbId = $migrationIds[$patientDbId][$reanimation->migrationPatientId] ?? null;
|
||||
if (!$migrationDbId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$reanimationBatch[] = [
|
||||
'migration_patient_id' => $migrationDbId,
|
||||
'medical_history_id' => $patientDbId,
|
||||
'original_id' => $reanimation->id,
|
||||
'in_date' => $reanimation->inDate,
|
||||
'out_date' => $reanimation->outDate,
|
||||
'description' => $reanimation->description,
|
||||
'stationar_branch_id' => $reanimation->stationarBranchId,
|
||||
'migration_stationar_branch_id' => $reanimation->migrationStationarBranchId,
|
||||
'migration_department_id' => $reanimation->migrationDepartmentId,
|
||||
'doctor_id' => $reanimation->doctorId,
|
||||
'user_id' => $reanimation->userId,
|
||||
'mis_user_id' => $reanimation->misUserId,
|
||||
'comment' => $reanimation->comment,
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($reanimationBatch)) {
|
||||
$reanimationUniqueBy = ['migration_patient_id', 'in_date'];
|
||||
$reanimationUpdateColumns = array_diff(array_keys($reanimationBatch[0]), $reanimationUniqueBy);
|
||||
|
||||
DB::table('report_duty_reanimations')->upsert(
|
||||
$reanimationBatch,
|
||||
$reanimationUniqueBy,
|
||||
$reanimationUpdateColumns
|
||||
);
|
||||
$savedReanimations = count($reanimationBatch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return [
|
||||
'savedPatients' => $savedPatients,
|
||||
'savedMigrations' => $savedMigrations,
|
||||
'savedReanimations' => $savedReanimations,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Http\Controllers\Web;
|
||||
|
||||
use App\Domain\ReportDuty\Actions\CreateReportDutyAction;
|
||||
use App\Domain\ReportDuty\Actions\GenerateAndSaveReportSnapshotAction;
|
||||
use App\Domain\ReportDuty\Actions\SaveObservablePatientsAction;
|
||||
use App\Domain\ReportDuty\DTO\CreateReportDutyDto;
|
||||
use App\Infrastructure\Http\Requests\CreateDutyReportRequest;
|
||||
use App\Services\DateRange;
|
||||
use Inertia\Inertia;
|
||||
|
||||
class DutyReportController
|
||||
{
|
||||
public function store(
|
||||
CreateDutyReportRequest $request,
|
||||
CreateReportDutyAction $createAction,
|
||||
GenerateAndSaveReportSnapshotAction $snapshotAction
|
||||
) {
|
||||
// Валидация уже выполнена в FormRequest
|
||||
$validated = $request->validated();
|
||||
|
||||
// Создаём DTO и DateRange
|
||||
$dateRange = new DateRange(
|
||||
$validated['period_start'],
|
||||
$validated['period_end']
|
||||
);
|
||||
|
||||
$dto = new CreateReportDutyDto(
|
||||
reportDate: $dateRange->endSql(),
|
||||
periodStart: $dateRange->startSql(),
|
||||
periodEnd: $dateRange->endSql(),
|
||||
periodType: $validated['period_type'] ?? 'day',
|
||||
statusId: $validated['status_id'] ?? 2,
|
||||
rfLpuDoctorId: $request->user()->rf_lpudoctor_id,
|
||||
rfDepartmentId: $request->user()->rf_department_id,
|
||||
rfUserId: $request->user()->id,
|
||||
);
|
||||
|
||||
// Вызов Use Case для создания отчёта
|
||||
$report = $createAction->execute($dto);
|
||||
|
||||
// Вызов Use Case для сохранения снимка и расчёта статистики
|
||||
$stats = $snapshotAction->execute(
|
||||
$report,
|
||||
$dateRange,
|
||||
$request->user()->rf_department_id,
|
||||
$request->user()->id
|
||||
);
|
||||
|
||||
// Сохраняем наблюдаемых пациентов и нежелательные события
|
||||
if ($request->has('observables')) {
|
||||
$observableAction = app(SaveObservablePatientsAction::class);
|
||||
$observableAction->execute($report, $validated['observables']);
|
||||
}
|
||||
|
||||
if ($request->has('unwanted_events')) {
|
||||
$unwantedAction = app(SaveUnwantedEventsAction::class);
|
||||
$unwantedAction->execute($report, $validated['unwanted_events']);
|
||||
}
|
||||
|
||||
// Возвращаем Inertia-ответ (редирект или рендер)
|
||||
return Inertia::location(route('reports.duty.show', $report->id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Http\Controllers\Web;
|
||||
|
||||
use App\Domain\Patient\Actions\GetDepartmentJournalPatientAction;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PatientController
|
||||
{
|
||||
public function getDepartmentPatient(
|
||||
Request $request,
|
||||
GetDepartmentJournalPatientAction $patientAction
|
||||
)
|
||||
{
|
||||
$departmentId = $request->query('departmentId');
|
||||
|
||||
$patients = $patientAction->execute((int) $departmentId);
|
||||
|
||||
return response()->json($patients);
|
||||
}
|
||||
}
|
||||
27
app/Infrastructure/Http/Requests/CreateDutyReportRequest.php
Normal file
27
app/Infrastructure/Http/Requests/CreateDutyReportRequest.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class CreateDutyReportRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return auth()->check();
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'period_start' => ['required', 'date'],
|
||||
'period_end' => ['required', 'date', 'after_or_equal:period_start'],
|
||||
'period_type' => ['nullable', 'string', 'in:day,week,month'],
|
||||
'status_id' => ['nullable', 'integer', 'in:1,2,3'],
|
||||
'observables' => ['nullable', 'array'],
|
||||
'observables.*.id' => ['required', 'integer'],
|
||||
'unwanted_events' => ['nullable', 'array'],
|
||||
'unwanted_events.*.title' => ['required', 'string'],
|
||||
];
|
||||
}
|
||||
}
|
||||
112
app/Infrastructure/Services/MisPatientSnapshotProvider.php
Normal file
112
app/Infrastructure/Services/MisPatientSnapshotProvider.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Services;
|
||||
|
||||
use App\Domain\ReportDuty\Contracts\PatientSnapshotProviderInterface;
|
||||
use App\Models\MedicalHistory;
|
||||
use App\Services\Classification\PatientStatusClassifier;
|
||||
use App\Services\DateRange;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
|
||||
/**
|
||||
* Извлекает пациентов из МИС (Material View)
|
||||
*/
|
||||
class MisPatientSnapshotProvider implements PatientSnapshotProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected PatientStatusClassifier $classifier
|
||||
) {
|
||||
}
|
||||
|
||||
public function getPatients(DateRange $dateRange, int $departmentId): LazyCollection
|
||||
{
|
||||
$startYear = Carbon::now()->startOfYear()->format('Y-m-d');
|
||||
|
||||
return MedicalHistory::query()
|
||||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange, $startYear) {
|
||||
$q->where('department_id', $departmentId)
|
||||
->where('ingoing_date', '<=', $dateRange->endSql())
|
||||
->where(function ($sub) use ($dateRange, $startYear) {
|
||||
$sub->whereNull('out_date')
|
||||
->where('ingoing_date', '>', $startYear);
|
||||
$sub->orWhere(function ($sub2) use ($dateRange, $startYear) {
|
||||
$sub2->whereNotNull('out_date')
|
||||
->where('out_date', '>', $dateRange->startSql())
|
||||
->where('out_date', '>', $startYear);
|
||||
});
|
||||
});
|
||||
})
|
||||
->with([
|
||||
'latestMigration' => function ($q) use ($departmentId) {
|
||||
$q->where('department_id', $departmentId);
|
||||
},
|
||||
'latestMigration.operations',
|
||||
'latestMigration.reanimations',
|
||||
'migrations' => function ($q) use ($departmentId, $dateRange, $startYear) {
|
||||
$q->where('department_id', $departmentId)
|
||||
->where('ingoing_date', '<=', $dateRange->endSql())
|
||||
->where(function ($sub) use ($dateRange, $startYear) {
|
||||
$sub->whereNull('out_date')
|
||||
->where('ingoing_date', '>', $startYear);
|
||||
$sub->orWhere(function ($sub2) use ($dateRange, $startYear) {
|
||||
$sub2->whereNotNull('out_date')
|
||||
->where('out_date', '>', $dateRange->startSql())
|
||||
->where('out_date', '>', $startYear);
|
||||
});
|
||||
});
|
||||
},
|
||||
'migrations.reanimations' => function ($q) use ($dateRange) {
|
||||
$q->where(function ($sub) use ($dateRange) {
|
||||
$sub->whereNull('out_date')
|
||||
->orWhere('out_date', '>=', $dateRange->startSql());
|
||||
});
|
||||
},
|
||||
'operations' => function ($q) use ($departmentId, $dateRange) {
|
||||
$q->where('department_id', $departmentId)
|
||||
->where('start_date', '>=', $dateRange->startSql())
|
||||
->where('start_date', '<', $dateRange->endSql());
|
||||
}
|
||||
])
|
||||
->lazy()
|
||||
->map(function (MedicalHistory $h) use ($dateRange) {
|
||||
$patientStatus = $this->classifier::classify($h, $dateRange);
|
||||
$periodFlags = $this->classifier::classifyPeriodFlags($h, $dateRange);
|
||||
$patientUrgency = null;
|
||||
$patientReanimation = null;
|
||||
if (!in_array($patientStatus, [
|
||||
PatientStatusClassifier::STATUS_DECEASED,
|
||||
PatientStatusClassifier::STATUS_DISCHARGED,
|
||||
PatientStatusClassifier::STATUS_TRANSFERRED
|
||||
])) {
|
||||
$patientUrgency = $this->classifier::classifyUrgency($h->urgency_id);
|
||||
$patientReanimation = $this->classifier::classifyReanimation($h->latestMigration?->reanimations, $dateRange);
|
||||
}
|
||||
|
||||
return new PatientSnapshotData(
|
||||
id: $h->id,
|
||||
sourceType: 'mis',
|
||||
medicalCardNumber: $h->medical_card_number,
|
||||
fullName: $h->full_name,
|
||||
birthDate: $h->birth_date,
|
||||
recipientDate: $h->recipient_date,
|
||||
extractDate: $h->extract_date,
|
||||
deathDate: $h->death_date,
|
||||
male: $h->male,
|
||||
urgencyId: $h->urgency_id,
|
||||
visitResultId: $h->visit_result_id,
|
||||
hospitalResultId: $h->hospital_result_id,
|
||||
comment: $h->comment,
|
||||
profitTypeId: $h->profit_type_id,
|
||||
migrations: $h->migrations->map(fn($m) => $m->toArray())->toArray(),
|
||||
operations: $h->operations->toArray(),
|
||||
patientStatus: $patientStatus,
|
||||
patientUrgency: $patientUrgency,
|
||||
periodFlags: $periodFlags,
|
||||
inReanimation: $patientReanimation,
|
||||
admittedToday: $this->classifier::classifyAdmitted($h->latestMigration?->ingoing_date, $dateRange),
|
||||
inObservable: $this->classifier::classifyObservable($h->observable, $dateRange),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Services;
|
||||
|
||||
use App\Domain\ReportDuty\Contracts\PatientSnapshotProviderInterface;
|
||||
use App\Domain\ReportDuty\DTO\PatientSnapshotData;
|
||||
use App\Models\ReportNurse;
|
||||
use App\Models\ReportNursePatient;
|
||||
use App\Services\Classification\PatientStatusClassifier;
|
||||
use App\Services\DateRange;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
|
||||
/**
|
||||
* Извлекает пациентов из отчёта медсестры (ReportNurse)
|
||||
*/
|
||||
class NurseReportPatientSnapshotProvider implements PatientSnapshotProviderInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected PatientStatusClassifier $classifier
|
||||
) {
|
||||
}
|
||||
|
||||
public function getPatients(DateRange $dateRange, int $departmentId): LazyCollection
|
||||
{
|
||||
// Здесь нужно получить ReportNurse для данного отделения и периода
|
||||
$nurseReport = ReportNurse::where('rf_department_id', $departmentId)
|
||||
->where('period_start', $dateRange->startSql())
|
||||
->where('period_end', $dateRange->endSql())
|
||||
->latest('id')
|
||||
->first();
|
||||
|
||||
if (!$nurseReport) {
|
||||
return LazyCollection::make([]);
|
||||
}
|
||||
|
||||
return ReportNursePatient::query()
|
||||
->where('report_nurse_id', $nurseReport->id)
|
||||
->with([
|
||||
'migrations',
|
||||
'operations' => function ($q) use ($dateRange) {
|
||||
$q->where('start_date', '>=', $dateRange->startSql())
|
||||
->where('start_date', '<', $dateRange->endSql());
|
||||
},
|
||||
'latestMigration',
|
||||
])
|
||||
->lazy()
|
||||
->map(function (ReportNursePatient $h) use ($dateRange) {
|
||||
$patientStatus = $this->classifier::classify($h, $dateRange);
|
||||
$periodFlags = $this->classifier::classifyPeriodFlags($h, $dateRange);
|
||||
$patientUrgency = null;
|
||||
$patientReanimation = null;
|
||||
if (!in_array($patientStatus, [
|
||||
PatientStatusClassifier::STATUS_DECEASED,
|
||||
PatientStatusClassifier::STATUS_DISCHARGED,
|
||||
PatientStatusClassifier::STATUS_TRANSFERRED
|
||||
])) {
|
||||
$patientUrgency = $this->classifier::classifyUrgency($h->urgency_id);
|
||||
$patientReanimation = false; // в отчёте медсестры нет реанимации
|
||||
}
|
||||
|
||||
// Преобразуем миграции в массив (как в оригинале)
|
||||
$migrations = $h->migrations->map(fn($m) => [
|
||||
'id' => $m->original_id,
|
||||
'ingoing_date' => $m->ingoing_date,
|
||||
'out_date' => $m->out_date,
|
||||
'diagnosis_id' => $m->diagnosis_id,
|
||||
'diagnosis_code' => $m->diagnosis_code,
|
||||
'diagnosis_name' => $m->diagnosis_name,
|
||||
'interrupted_event_id' => $m->interrupted_event_id,
|
||||
'stationar_branch_id' => $m->stationar_branch_id,
|
||||
'department_id' => $m->department_id,
|
||||
'visit_result_id' => $m->visit_result_id,
|
||||
'stat_cure_result_id' => $m->stat_cure_result_id,
|
||||
'user_id' => $m->user_id,
|
||||
'mis_user_id' => $m->mis_user_id,
|
||||
'comment' => $m->comment,
|
||||
'reanimations' => [],
|
||||
])->toArray();
|
||||
|
||||
return new PatientSnapshotData(
|
||||
id: $h->original_id,
|
||||
sourceType: 'nurse_report',
|
||||
medicalCardNumber: $h->medical_card_number,
|
||||
fullName: $h->full_name,
|
||||
birthDate: $h->birth_date,
|
||||
recipientDate: $h->recipient_date,
|
||||
extractDate: $h->extract_date,
|
||||
deathDate: $h->death_date,
|
||||
male: $h->male,
|
||||
urgencyId: $h->urgency_id,
|
||||
visitResultId: $h->visit_result_id,
|
||||
hospitalResultId: $h->hospital_result_id,
|
||||
comment: $h->comment,
|
||||
profitTypeId: $h->profit_type_id,
|
||||
migrations: $migrations,
|
||||
operations: $h->operations->toArray(),
|
||||
patientStatus: $patientStatus,
|
||||
patientUrgency: $patientUrgency,
|
||||
periodFlags: $periodFlags,
|
||||
inReanimation: $patientReanimation,
|
||||
admittedToday: $this->classifier::classifyAdmitted($h->latestMigration?->ingoing_date, $dateRange),
|
||||
inObservable: false,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user