* добавил автоматическое создание движения при редактировании * добавил функционал для сохранения отчета и пациентов * изменил форматирование дат * добавил частичную перезагрузку при сохранении изменений
144 lines
6.5 KiB
PHP
144 lines
6.5 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\ReportNurse;
|
||
use App\Models\UnifiedMedicalHistory;
|
||
use App\Models\User;
|
||
use Illuminate\Database\Eloquent\Builder;
|
||
use Illuminate\Support\Carbon;
|
||
|
||
class NurseReportService
|
||
{
|
||
/**
|
||
* Базовый запрос для всех отчётов
|
||
* Фильтрует по отделению и периоду, подгружает связи
|
||
*/
|
||
protected function baseQuery(DateRange $dateRange, int $departmentId): Builder
|
||
{
|
||
return UnifiedMedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->dateRange($dateRange->startSql(), $dateRange->endSql());
|
||
})
|
||
->with(['latestMigration' => function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->dateRange($dateRange->startSql(), $dateRange->endSql());
|
||
}]);
|
||
}
|
||
|
||
/**
|
||
* Сохранить отчет
|
||
*/
|
||
public function saveReport(DateRange $dateRange, ?int $userId = null, ?int $lpuDoctorId = null, ?int $departmentId = null)
|
||
{
|
||
$user = $userId ? User::find($userId) : auth()->user();
|
||
|
||
$lpuDoctorId = $lpuDoctorId ?? $user->rf_lpudoctor_id;
|
||
$departmentId = $departmentId ?? $user->rf_department_id;
|
||
|
||
$data = [
|
||
'report_date' => Carbon::now()->format('Y-m-d'),
|
||
'sent_at' => Carbon::now()->format('Y-m-d H:i:s'),
|
||
'period_type' => 'day',
|
||
'period_start' => $dateRange->startSql(),
|
||
'period_end' => $dateRange->endSql(),
|
||
'status_id' => 2, // опубликован
|
||
'rf_lpudoctor_id' => $lpuDoctorId,
|
||
'rf_department_id' => $departmentId,
|
||
'rf_user_id' => $user->id,
|
||
];
|
||
|
||
$report = ReportNurse::create($data);
|
||
|
||
return $report;
|
||
}
|
||
|
||
/**
|
||
* Сохранить снимок пациентов за период
|
||
*/
|
||
public function saveSnapshot(DateRange $dateRange, ReportNurse $reportNurse, ?int $departmentId = null, ?int $userId = null): array
|
||
{
|
||
$departmentId = $departmentId ?? $reportNurse->department->rf_mis_department_id;
|
||
$userId = $userId ?? $reportNurse->rf_user_id;
|
||
$startYear = Carbon::now()->startOfYear()->format('Y-m-d');
|
||
|
||
$query = UnifiedMedicalHistory::query()
|
||
// Фильтруем движения по отделению + пересечение дат
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange, $startYear) {
|
||
$q->where('department_id', $departmentId)
|
||
// пребывание пересекается с отчётным периодом
|
||
->where('ingoing_date', '<=', $dateRange->endSql())
|
||
->where('ingoing_date', '>=', $startYear)
|
||
->where(function ($sub) use ($dateRange) {
|
||
$sub->whereNull('out_date')
|
||
->orWhere('out_date', '>=', $dateRange->startSql())
|
||
->where('out_date', '<=', $dateRange->endSql());
|
||
})
|
||
->where(function ($sub) use ($dateRange) {
|
||
$sub->whereNull('out_date')
|
||
->orWhere('out_date', '>=', $dateRange->startSql())
|
||
->where('out_date', '<=', $dateRange->endSql());
|
||
});
|
||
})
|
||
// Подгружаем последнее движение для денормализации
|
||
->with(['latestMigration' => function ($q) use ($departmentId, $dateRange, $startYear) {
|
||
$q->where('department_id', $departmentId)
|
||
->where('ingoing_date', '<=', $dateRange->endSql())
|
||
->where('ingoing_date', '>=', $startYear)
|
||
->where(function ($sub) use ($dateRange) {
|
||
$sub->whereNull('out_date')
|
||
->orWhere('out_date', '>=', $dateRange->startSql())
|
||
->where('out_date', '<=', $dateRange->endSql());
|
||
})
|
||
->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;
|
||
}
|
||
|
||
return [
|
||
'saved_count' => $savedCount,
|
||
'report_date' => $dateRange->startSql(),
|
||
'department_id' => $departmentId,
|
||
];
|
||
}
|
||
}
|