* оптимизация обновления при редактировании спец контингента * добавил поддержку заключительных диагнозов * изменил определение законченной операции * добавил поддержку исхода операции * добавил определение отмены для операции через назначение * работа над диапазонами календарей, подсчет статистики * добавил статусы отчетов и подкорректировал привязку спец контингента к отчету * добавил новые сервисы для будущего кеширования * частичное разделение логики подсчета пациентов
125 lines
4.5 KiB
PHP
125 lines
4.5 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\Department;
|
||
use App\Models\DepartmentPatient;
|
||
use App\Models\MedicalHistorySnapshot;
|
||
use App\Models\MetrikaResult;
|
||
use App\Models\ObservationPatient;
|
||
use App\Models\Report;
|
||
use App\Models\UnwantedEvent;
|
||
use App\Models\User;
|
||
use Carbon\CarbonPeriod;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Log;
|
||
|
||
class AutoReportService
|
||
{
|
||
public function __construct(
|
||
protected ReportService $reportService,
|
||
protected DateRangeService $dateRangeService
|
||
) {}
|
||
|
||
/**
|
||
* Заполнить отчеты для пользователя за период
|
||
*/
|
||
public function fillReportsForUser(
|
||
User $user,
|
||
string $startDate,
|
||
string $endDate,
|
||
Department $department,
|
||
bool $force = false
|
||
): int {
|
||
$createdCount = 0;
|
||
|
||
// Для многодневного диапазона расширяем конец на 1 день,
|
||
// чтобы покрыть последние сутки (07:00 -> 07:00) целиком.
|
||
$start = \Carbon\Carbon::createFromFormat('Y-m-d', $startDate, 'Asia/Yakutsk');
|
||
$end = \Carbon\Carbon::createFromFormat('Y-m-d', $endDate, 'Asia/Yakutsk');
|
||
$periodEnd = $start->equalTo($end)
|
||
? $end->copy()
|
||
: $end->copy()->addDay();
|
||
|
||
// Создаем период по дням
|
||
$period = CarbonPeriod::create($start->toDateString(), $periodEnd->toDateString());
|
||
|
||
foreach ($period as $date) {
|
||
$dateRange = $this->dateRangeService->getNormalizedDateRange($user, $date, $date);
|
||
try {
|
||
$reportCreated = $this->createReportForDate($user, $department, $dateRange, $force);
|
||
|
||
if ($reportCreated) {
|
||
$createdCount++;
|
||
}
|
||
} catch (\Exception $e) {
|
||
Log::error("Ошибка создания отчета для {$user->id} на {$date->format('Y-m-d')}: {$e->getMessage()}");
|
||
throw $e; // или continue в зависимости от требований
|
||
}
|
||
}
|
||
|
||
return $createdCount;
|
||
}
|
||
|
||
/**
|
||
* Создать отчет для конкретной даты
|
||
*/
|
||
public function createReportForDate(User $user, Department $department, DateRange $dateRange, bool $force = false): bool
|
||
{
|
||
$scopedUser = $this->scopeUserToDepartment($user, $department);
|
||
|
||
// Проверяем, существует ли уже отчет на эту дату
|
||
$existingReport = Report::where('rf_department_id', $department->department_id)
|
||
->exactPeriod($dateRange->startSql(), $dateRange->endSql())
|
||
->first();
|
||
|
||
if ($existingReport && !$force) {
|
||
return false; // Отчет уже существует
|
||
}
|
||
|
||
// Если есть существующий отчет и force=true - удаляем его
|
||
if ($existingReport && $force) {
|
||
$this->deleteExistingReport($existingReport);
|
||
}
|
||
|
||
// Получаем данные для отчета
|
||
$reportData = $this->prepareReportData($scopedUser, $department, $dateRange);
|
||
|
||
// Создаем отчет
|
||
DB::transaction(function () use ($scopedUser, $reportData) {
|
||
$this->reportService->storeReport($reportData, $scopedUser, true);
|
||
});
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Подготовить данные для отчета
|
||
*/
|
||
private function prepareReportData(User $user, Department $department, DateRange $dateRange): array
|
||
{
|
||
return $this->reportService->buildAutoFillReportPayload($user, $department, $dateRange);
|
||
}
|
||
|
||
private function scopeUserToDepartment(User $user, Department $department): User
|
||
{
|
||
$scopedUser = clone $user;
|
||
$scopedUser->rf_department_id = $department->department_id;
|
||
$scopedUser->setRelation('department', $department);
|
||
|
||
return $scopedUser;
|
||
}
|
||
|
||
private function deleteExistingReport(Report $report): void
|
||
{
|
||
DB::transaction(function () use ($report) {
|
||
MetrikaResult::where('rf_report_id', $report->report_id)->delete();
|
||
MedicalHistorySnapshot::where('rf_report_id', $report->report_id)->delete();
|
||
UnwantedEvent::where('rf_report_id', $report->report_id)->delete();
|
||
ObservationPatient::where('rf_report_id', $report->report_id)->delete();
|
||
DB::table('reports')->where('report_id', $report->report_id)->delete();
|
||
});
|
||
}
|
||
|
||
}
|