Перевод на доменную архитектуру
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Reports\Services;
|
||||
|
||||
use App\Models\Department;
|
||||
use App\Models\MisStationarBranch;
|
||||
use App\Models\Report;
|
||||
use App\Models\User;
|
||||
use App\Services\DateRange;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Разрешает контекст отчётного периода, необходимый для read-side сервисов.
|
||||
*
|
||||
* Класс хранит в одном месте правила поиска отчётов по периоду и решения
|
||||
* snapshot-vs-replica, чтобы не дублировать их по контроллерам и сервисам.
|
||||
*/
|
||||
class ReportReadContextResolver
|
||||
{
|
||||
/**
|
||||
* Определить MIS branch id для отчётного отделения.
|
||||
*/
|
||||
public function resolveBranchId(Department $department): ?int
|
||||
{
|
||||
return MisStationarBranch::query()
|
||||
->where('rf_DepartmentID', $department->rf_mis_department_id)
|
||||
->value('StationarBranchID');
|
||||
}
|
||||
|
||||
/**
|
||||
* Определить, нужно ли читать submitted-снапшоты вместо live-данных.
|
||||
*/
|
||||
public function shouldUseSnapshots(
|
||||
Department $department,
|
||||
DateRange $dateRange,
|
||||
bool $beforeCreate = false
|
||||
): bool {
|
||||
if ($beforeCreate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$report = $this->getReportForPeriod($department->department_id, $dateRange);
|
||||
|
||||
return $report?->status === 'submitted';
|
||||
}
|
||||
|
||||
/**
|
||||
* Для самых изменчивых статусов врачи должны продолжать видеть live-данные за текущие сутки.
|
||||
*/
|
||||
public function shouldUseReplicaForLiveStatus(User $user, string $status, DateRange $dateRange): bool
|
||||
{
|
||||
if ($user->isHeadOfDepartment() || $user->isAdmin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array($status, ['plan', 'emergency', 'recipient', 'current', 'reanimation'], true)
|
||||
&& $dateRange->isOneDay
|
||||
&& $dateRange->isEndDateToday();
|
||||
}
|
||||
|
||||
/**
|
||||
* Вернуть submitted-отчёты, относящиеся к выбранному отчётному окну.
|
||||
*
|
||||
* @return Collection<int, Report>
|
||||
*/
|
||||
public function getReportsForDateRange(int $departmentId, DateRange $dateRange): Collection
|
||||
{
|
||||
if ($dateRange->isOneDay) {
|
||||
return Report::query()
|
||||
->where('rf_department_id', $departmentId)
|
||||
->exactPeriod($dateRange->startSql(), $dateRange->endSql())
|
||||
->onlySubmitted()
|
||||
->orderBy('period_end', 'DESC')
|
||||
->get();
|
||||
}
|
||||
|
||||
return Report::query()
|
||||
->where('rf_department_id', $departmentId)
|
||||
->withinPeriod($dateRange->startSql(), $dateRange->endSql())
|
||||
->onlySubmitted()
|
||||
->orderBy('period_end', 'DESC')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recipient-снапшоты читаются из последнего отчёта в выбранном окне.
|
||||
*
|
||||
* @param array<int, int> $reportIds
|
||||
* @return array<int, int>
|
||||
*/
|
||||
public function getRecipientReportIds(array $reportIds): array
|
||||
{
|
||||
if (empty($reportIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [reset($reportIds)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Найти отчёт, который определяет видимость снапшотов для запрошенного периода.
|
||||
*/
|
||||
private function getReportForPeriod(int $departmentId, DateRange $dateRange): ?Report
|
||||
{
|
||||
$query = Report::query()
|
||||
->where('rf_department_id', $departmentId)
|
||||
->exactPeriod($dateRange->startSql(), $dateRange->endSql())
|
||||
->orderByDesc('report_id');
|
||||
|
||||
if ($dateRange->isOneDay) {
|
||||
return $query->first();
|
||||
}
|
||||
|
||||
return $query->onlySubmitted()->first();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user