Перевод на DDD

This commit is contained in:
brusnitsyn
2026-07-31 17:19:03 +09:00
parent 2dd55b9d11
commit 2c6d4a04cc
48 changed files with 1796 additions and 0 deletions

View File

@@ -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]
);
}
}

View File

@@ -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.
}
}

View File

@@ -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,
]);
}
}
}

View File

@@ -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.
}
}

View File

@@ -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,
];
}
}