* добавил объединение изменений движений

* добавил автоматическое создание движения при редактировании
* добавил функционал для сохранения отчета и пациентов
* изменил форматирование дат
* добавил частичную перезагрузку при сохранении изменений
This commit is contained in:
brusnitsyn
2026-05-05 17:06:15 +09:00
parent 51a4b5b9de
commit 717641e4bb
18 changed files with 712 additions and 60 deletions

View File

@@ -55,8 +55,8 @@ class DateRangeService
? $this->parseDate($startAtInput)
: Carbon::now('Asia/Yakutsk');
$endDate = $endDate->copy()->setTime(7, 0);
$startDate = $startDate->copy()->subDay()->setTime(7, 0);
$endDate = $endDate->copy()->setTime(9, 0);
$startDate = $startDate->copy()->subDay()->setTime(9, 0);
return new DateRange(
startDate: $startDate,
@@ -85,10 +85,10 @@ class DateRangeService
$startDate = Carbon::now('Asia/Yakutsk')
->startOfYear() // 1 января текущего года
->subDay()
->setTime(7, 0);
->setTime(9, 0);
$endDate = Carbon::now('Asia/Yakutsk')
->setTime(7, 0);
->setTime(9, 0);
return [
$startDate->format('Y-m-d H:i:s'),
@@ -123,11 +123,11 @@ class DateRangeService
$endDate = $this->parseDate($endAt);
if ($startDate->isSameDay($endDate)) {
$startDate = $startDate->subDay()->setTime(7, 0);
$endDate = $endDate->setTime(7, 0);
$startDate = $startDate->subDay()->setTime(9, 0);
$endDate = $endDate->setTime(9, 0);
} else {
$startDate = $startDate->setTime(7, 0);
$endDate = $endDate->setTime(7, 0);
$startDate = $startDate->setTime(9, 0);
$endDate = $endDate->setTime(9, 0);
}
return [
@@ -140,10 +140,10 @@ class DateRangeService
{
$startDate = Carbon::now('Asia/Yakutsk')
->subDay()
->setTime(7, 0);
->setTime(9, 0);
$endDate = Carbon::now('Asia/Yakutsk')
->setTime(7, 0);
->setTime(9, 0);
return [
$startDate->format('Y-m-d H:i:s'),
@@ -197,8 +197,8 @@ class DateRangeService
{
// Для автоматического заполнения используем логику как для врача
// (вчера 07:00 - сегодня 07:00)
$startDate = $date->copy()->subDay()->setTime(7, 0);
$endDate = $date->copy()->setTime(7, 0);
$startDate = $date->copy()->subDay()->setTime(9, 0);
$endDate = $date->copy()->setTime(9, 0);
return new DateRange(
startDate: $startDate,

View File

@@ -0,0 +1,143 @@
<?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,
];
}
}