* добавил удаление карты, если она была добавлена не из МИС
* добавил диалог при удалении карты * добавил сохранение движения * добавил вывод сохраненного отчета * изменил логику сохранения отчета
This commit is contained in:
@@ -208,4 +208,13 @@ class DateRangeService
|
||||
isOneDay: true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет, является ли запрошенный период полностью прошедшим
|
||||
*/
|
||||
public function isPastPeriod(DateRange $dateRange): bool
|
||||
{
|
||||
// Период считается "прошлым", если его конец строго раньше начала текущих суток
|
||||
return $dateRange->end()->lt(now()->startOfDay());
|
||||
}
|
||||
}
|
||||
|
||||
119
app/Services/NurseMedicalHistoryService.php
Normal file
119
app/Services/NurseMedicalHistoryService.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\MedicalHistory;
|
||||
use App\Models\MigrationPatient;
|
||||
use App\Models\ReportNursePatient;
|
||||
use App\Models\UnifiedMedicalHistory;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class NurseMedicalHistoryService
|
||||
{
|
||||
public function getHistories(DateRange $dateRange, int $departmentId)
|
||||
{
|
||||
$query = ReportNursePatient::query();
|
||||
|
||||
$query->where('recipient_date', '>=', $dateRange->startSql())
|
||||
->where('recipient_date', '<', $dateRange->endSql())
|
||||
// 1. Оставляем только тех пациентов, у которых БЫЛО движение в этом отделении
|
||||
->whereHas('latestMigration', fn($q) => $q->where('department_id', $departmentId))
|
||||
|
||||
// 2. Загружаем ТОЛЬКО последнее движение в этом отделении (не все миграции)
|
||||
->with(['latestMigration' => fn($q) => $q->where('department_id', $departmentId)]);
|
||||
|
||||
$result = $query->paginate();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getUrgencyHistory(DateRange $dateRange, int $departmentId, int $urgencyId)
|
||||
{
|
||||
$query = ReportNursePatient::query();
|
||||
|
||||
$query->where('recipient_date', '>=', $dateRange->startSql())
|
||||
->where('recipient_date', '<', $dateRange->endSql())
|
||||
->urgency($urgencyId)
|
||||
->whereHas('migrations', function ($m) use ($departmentId) {
|
||||
$m->where('department_id', $departmentId);
|
||||
})
|
||||
->with([
|
||||
'migrations' => fn ($m) => $m->where('department_id', $departmentId),
|
||||
'migrations.operations'
|
||||
]);
|
||||
|
||||
$result = $query->paginate();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getDepartmentHistories(DateRange $dateRange, int $departmentId)
|
||||
{
|
||||
return ReportNursePatient::query()
|
||||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||||
$q->department($departmentId)->current($dateRange);
|
||||
})
|
||||
->with(['latestMigration' => function ($q) use ($departmentId, $dateRange) {
|
||||
$q->department($departmentId)->current($dateRange); // подгружаем только отфильтрованные движения
|
||||
}])
|
||||
->get()
|
||||
// Сортировка по дате поступления в отделение (поле дочерней таблицы)
|
||||
->sortByDesc(fn ($mh) => $mh->latestMigration->ingoing_date ?? $mh->recipient_date)
|
||||
->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить карты поступившие сегодня
|
||||
* @param DateRange $dateRange
|
||||
* @param int $departmentId
|
||||
*/
|
||||
public function getRecipientHistories(DateRange $dateRange, int $departmentId)
|
||||
{
|
||||
$now = Carbon::now();
|
||||
|
||||
return ReportNursePatient::query()
|
||||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||||
$q->department($departmentId)->admitted($dateRange->startSql(), $dateRange->endSql());
|
||||
})
|
||||
->with(['latestMigration' => function ($q) use ($departmentId) {
|
||||
$q->department($departmentId);
|
||||
}])
|
||||
->get();
|
||||
}
|
||||
|
||||
public function getDischargedHistories(DateRange $dateRange, int $departmentId)
|
||||
{
|
||||
return ReportNursePatient::query()
|
||||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||||
$q->department($departmentId)->discharged($dateRange->startSql(), $dateRange->endSql());
|
||||
})
|
||||
->with(['latestMigration' => function ($q) use ($departmentId) {
|
||||
$q->department($departmentId);
|
||||
}])
|
||||
->get();
|
||||
}
|
||||
|
||||
public function getDeceasedHistories(DateRange $dateRange, int $departmentId)
|
||||
{
|
||||
return ReportNursePatient::query()
|
||||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||||
$q->department($departmentId)->deceased($dateRange->startSql(), $dateRange->endSql());
|
||||
})
|
||||
->with(['latestMigration' => function ($q) use ($departmentId) {
|
||||
$q->department($departmentId);
|
||||
}])
|
||||
->get();
|
||||
}
|
||||
|
||||
public function getTransferredHistories(DateRange $dateRange, int $departmentId)
|
||||
{
|
||||
return ReportNursePatient::query()
|
||||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||||
$q->department($departmentId)->transferred($dateRange->startSql(), $dateRange->endSql());
|
||||
})
|
||||
->with(['latestMigration' => function ($q) use ($departmentId) {
|
||||
$q->department($departmentId);
|
||||
}])
|
||||
->get();
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,13 @@
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\ReportNurse;
|
||||
use App\Models\ReportNurseMigrationPatient;
|
||||
use App\Models\ReportNursePatient;
|
||||
use App\Models\UnifiedMedicalHistory;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class NurseReportService
|
||||
{
|
||||
@@ -47,7 +50,13 @@ class NurseReportService
|
||||
'rf_user_id' => $user->id,
|
||||
];
|
||||
|
||||
$report = ReportNurse::create($data);
|
||||
$report = ReportNurse::updateOrCreate(
|
||||
[
|
||||
'report_date' => $data['report_date'], 'period_start' => $data['period_start'],
|
||||
'period_end' => $data['period_end']
|
||||
],
|
||||
$data
|
||||
);
|
||||
|
||||
return $report;
|
||||
}
|
||||
@@ -92,52 +101,164 @@ class NurseReportService
|
||||
->latest('ingoing_date'); // если несколько, берём последнее
|
||||
}]);
|
||||
|
||||
$rawSql = $query->toRawSql();
|
||||
|
||||
// Получаем данные (chunk для памяти, если пациентов > 1000)
|
||||
$patients = $query->cursor();
|
||||
|
||||
$savedCount = 0;
|
||||
$reportData = [];
|
||||
|
||||
foreach ($patients as $patient) {
|
||||
// Подготовка данных для сохранения (денормализация)
|
||||
$data = [
|
||||
'report_nurse_id' => $reportNurse->id,
|
||||
'source_type' => $patient->source_type,
|
||||
'original_id' => $patient->original_id,
|
||||
'medical_card_number' => $patient->medical_card_number,
|
||||
'full_name' => $patient->full_name,
|
||||
'birth_date' => $patient->birth_date,
|
||||
'recipient_date' => $patient->recipient_date,
|
||||
'extract_date' => $patient->extract_date,
|
||||
'death_date' => $patient->death_date,
|
||||
'male' => $patient->male,
|
||||
'urgency_id' => $patient->urgency_id,
|
||||
'hospital_result_id' => $patient->hospital_result_id,
|
||||
'visit_result_id' => $patient->visit_result_id,
|
||||
'comment' => $patient->comment,
|
||||
'user_id' => $userId,
|
||||
];
|
||||
|
||||
// UPSERT: обновляем если запись с таким ключом уже есть, иначе вставляем
|
||||
\DB::table('report_nurse_patients')->upsert(
|
||||
[$data],
|
||||
['report_nurse_id', 'source_type', 'original_id'], // уникальные ключи
|
||||
[
|
||||
'medical_card_number', 'full_name', 'birth_date', 'recipient_date', 'extract_date', 'death_date',
|
||||
'male', 'urgency_id', 'hospital_result_id', 'visit_result_id', 'comment', 'user_id'
|
||||
] // обновляемые поля
|
||||
);
|
||||
|
||||
$savedCount++;
|
||||
$reportData[] = $data;
|
||||
}
|
||||
$savedStats = $this->saveReportSnapshot($reportNurse->id, $patients, $userId);
|
||||
|
||||
return [
|
||||
'saved_count' => $savedCount,
|
||||
...$savedStats,
|
||||
'report_date' => $dateRange->startSql(),
|
||||
'department_id' => $departmentId,
|
||||
];
|
||||
}
|
||||
|
||||
public function saveReportSnapshot(int $reportNurseId, iterable $patients, int $userId): array
|
||||
{
|
||||
if (empty($patients)) {
|
||||
return ['saved_patients' => 0, 'saved_migrations' => 0];
|
||||
}
|
||||
|
||||
$patientBatch = [];
|
||||
$migrationBatch = [];
|
||||
$batchSize = 100;
|
||||
|
||||
foreach ($patients as $patient) {
|
||||
// Подготовка данных пациента
|
||||
$patientBatch[] = [
|
||||
'report_nurse_id' => $reportNurseId,
|
||||
'source_type' => $patient->source_type,
|
||||
'original_id' => $patient->original_id,
|
||||
'medical_card_number' => $patient->medical_card_number,
|
||||
'full_name' => $patient->full_name,
|
||||
'birth_date' => $patient->birth_date,
|
||||
'recipient_date' => $patient->recipient_date,
|
||||
'extract_date' => $patient->extract_date,
|
||||
'death_date' => $patient->death_date,
|
||||
'male' => $patient->male,
|
||||
'urgency_id' => $patient->urgency_id,
|
||||
'hospital_result_id' => $patient->hospital_result_id,
|
||||
'visit_result_id' => $patient->visit_result_id,
|
||||
'comment' => $patient->comment,
|
||||
'user_id' => $userId,
|
||||
];
|
||||
|
||||
// Подготовка данных миграции (если есть)
|
||||
if (!empty($patient->latestMigration)) {
|
||||
$migrationBatch[] = [
|
||||
// Временный ключ для связи с пациентом (заполним после первого upsert)
|
||||
'_temp_key' => [
|
||||
'report_nurse_id' => $reportNurseId,
|
||||
'source_type' => $patient->source_type,
|
||||
'original_id' => $patient->original_id,
|
||||
],
|
||||
'ingoing_date' => $patient->latestMigration->ingoing_date,
|
||||
'out_date' => $patient->latestMigration->out_date,
|
||||
'diagnosis_id' => $patient->latestMigration->diagnosis_id,
|
||||
'diagnosis_code' => $patient->latestMigration->diagnosis_code,
|
||||
'diagnosis_name' => $patient->latestMigration->diagnosis_name,
|
||||
'interrupted_event_id' => $patient->latestMigration->interrupted_event_id,
|
||||
'stationar_branch_id' => $patient->latestMigration->stationar_branch_id,
|
||||
'department_id' => $patient->latestMigration->department_id,
|
||||
'visit_result_id' => $patient->latestMigration->visit_result_id,
|
||||
'stat_cure_result_id' => $patient->latestMigration->stat_cure_result_id,
|
||||
'user_id' => $patient->latestMigration->user_id,
|
||||
'mis_user_id' => $patient->latestMigration->mis_user_id,
|
||||
'comment' => $patient->latestMigration->comment,
|
||||
];
|
||||
}
|
||||
|
||||
// Пакетная запись каждые $batchSize записей
|
||||
if (count($patientBatch) >= $batchSize) {
|
||||
[$savedP, $savedM] = $this->upsertBatches($reportNurseId, $patientBatch, $migrationBatch);
|
||||
$patientBatch = [];
|
||||
$migrationBatch = [];
|
||||
}
|
||||
}
|
||||
|
||||
// Сохраняем остаток
|
||||
[$savedP, $savedM] = $this->upsertBatches($reportNurseId, $patientBatch, $migrationBatch);
|
||||
|
||||
return ['saved_patients' => $savedP, 'saved_migrations' => $savedM];
|
||||
}
|
||||
|
||||
/**
|
||||
* Вспомогательный метод: выполняет upsert для пациентов и миграций
|
||||
*/
|
||||
private function upsertBatches(int $reportNurseId, array $patientBatch, array $migrationBatch): array
|
||||
{
|
||||
if (empty($patientBatch)) {
|
||||
return [0, 0];
|
||||
}
|
||||
|
||||
$savedPatients = 0;
|
||||
$savedMigrations = 0;
|
||||
|
||||
DB::transaction(function () use ($reportNurseId, $patientBatch, $migrationBatch, &$savedPatients, &$savedMigrations) {
|
||||
// UPSERT пациентов
|
||||
$patientUniqueBy = ['report_nurse_id', 'source_type', 'original_id'];
|
||||
$patientUpdateColumns = array_diff(array_keys($patientBatch[0]), $patientUniqueBy);
|
||||
|
||||
DB::table('report_nurse_patients')->upsert(
|
||||
$patientBatch,
|
||||
$patientUniqueBy,
|
||||
$patientUpdateColumns
|
||||
);
|
||||
$savedPatients = count($patientBatch);
|
||||
|
||||
// Получаем ID сохранённых пациентов для связи с миграциями
|
||||
if (!empty($migrationBatch)) {
|
||||
// Извлекаем уникальные ключи для поиска
|
||||
$tempKeys = array_map(fn($m) => $m['_temp_key'], $migrationBatch);
|
||||
|
||||
// Получаем реальные ID из БД
|
||||
$patientIds = DB::table('report_nurse_patients')
|
||||
->whereIn('report_nurse_id', [$reportNurseId])
|
||||
->get()
|
||||
->pluck('id', 'original_id') // key=original_id, value=id
|
||||
->toArray();
|
||||
|
||||
// Формируем финальный массив миграций с реальными medical_history_id
|
||||
$finalMigrations = [];
|
||||
foreach ($migrationBatch as $m) {
|
||||
$tempKey = $m['_temp_key'];
|
||||
$originalId = $tempKey['original_id'];
|
||||
|
||||
if (isset($patientIds[$originalId])) {
|
||||
$finalMigrations[] = [
|
||||
'medical_history_id' => $patientIds[$originalId], // Реальный 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'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($finalMigrations)) {
|
||||
// UPSERT миграций
|
||||
$migrationUniqueBy = ['medical_history_id'];
|
||||
$migrationUpdateColumns = array_diff(array_keys($finalMigrations[0]), $migrationUniqueBy);
|
||||
|
||||
DB::table('report_nurse_migration_patients')->upsert(
|
||||
$finalMigrations,
|
||||
$migrationUniqueBy,
|
||||
$migrationUpdateColumns
|
||||
);
|
||||
$savedMigrations = count($finalMigrations);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return [$savedPatients, $savedMigrations];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user