Работа над журналом для ст. мед сестер
This commit is contained in:
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Reports\Services;
|
||||
|
||||
use App\Domain\Reports\ValueObjects\MetrikaConfig;
|
||||
use App\Models\Department;
|
||||
use App\Models\MisLpuDoctor;
|
||||
use App\Models\Report;
|
||||
use App\Models\UnwantedEvent;
|
||||
use App\Models\User;
|
||||
use App\Services\DateRange;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Read-side сервис для metadata отчёта: текущий отчёт, события, планы и периоды.
|
||||
*/
|
||||
class ReportMetadataReadService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly ReportReadContextResolver $contextResolver,
|
||||
) {}
|
||||
|
||||
public function getCurrentReportInfo(Department $department, User $user, DateRange $dateRange): array
|
||||
{
|
||||
$reportToday = $this->contextResolver->resolveReportForPeriod($department->department_id, $dateRange);
|
||||
|
||||
$isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
|
||||
$useSnapshots = $isHeadOrAdmin || ! $dateRange->isEndDateToday() || $reportToday;
|
||||
|
||||
if ($useSnapshots && $isHeadOrAdmin && $reportToday) {
|
||||
$fillableUserId = $reportToday->rf_lpudoctor_id ?? null;
|
||||
} else {
|
||||
$fillableUserId = request()->query('userId', $user->rf_lpudoctor_id);
|
||||
}
|
||||
|
||||
$unwantedEvents = $this->getUnwantedEvents($department, $dateRange);
|
||||
$isActiveSendButton = $this->isSendButtonActive($user, $dateRange, $reportToday);
|
||||
|
||||
$message = null;
|
||||
if ($reportToday) {
|
||||
$reportDoctor = $reportToday->lpuDoctor;
|
||||
$message = "Отчет создан пользователем: $reportDoctor->FAM_V $reportDoctor->IM_V $reportDoctor->OT_V";
|
||||
}
|
||||
|
||||
$statusMessage = $reportToday
|
||||
? ($reportToday->status === 'submitted'
|
||||
? 'Этот отчет в статусе: опубликован'
|
||||
: 'Этот отчет в статусе: черновик')
|
||||
: null;
|
||||
|
||||
$lpuDoctor = $this->getDoctorInfo($fillableUserId, $dateRange);
|
||||
$date = $isHeadOrAdmin ? [
|
||||
$dateRange->startDate->getTimestampMs(),
|
||||
$dateRange->endDate->getTimestampMs(),
|
||||
] : $dateRange->endDate->getTimestampMs();
|
||||
|
||||
return [
|
||||
'report_id' => $reportToday?->report_id,
|
||||
'unwantedEvents' => $unwantedEvents,
|
||||
'isActiveSendButton' => $isActiveSendButton,
|
||||
'message' => $dateRange->isOneDay ? $message : null,
|
||||
'status' => $reportToday?->status ?? 'draft',
|
||||
'statusMessage' => $dateRange->isOneDay ? $statusMessage : null,
|
||||
'canPublish' => (bool) $reportToday && ($reportToday->status === 'draft') && $isActiveSendButton,
|
||||
'isOneDay' => $dateRange->isOneDay,
|
||||
'isHeadOrAdmin' => $isHeadOrAdmin,
|
||||
'dates' => $date,
|
||||
'userId' => $fillableUserId,
|
||||
'userName' => $lpuDoctor ? "$lpuDoctor->FAM_V $lpuDoctor->IM_V $lpuDoctor->OT_V" : null,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, array<string, mixed>>
|
||||
*/
|
||||
public function getUnwantedEvents(Department $department, DateRange $dateRange): Collection
|
||||
{
|
||||
return UnwantedEvent::query()
|
||||
->whereHas('report', function ($query) use ($department, $dateRange) {
|
||||
$query->where('rf_department_id', $department->department_id);
|
||||
|
||||
if ($dateRange->isOneDay) {
|
||||
$query->exactPeriod($dateRange->startSql(), $dateRange->endSql());
|
||||
} else {
|
||||
$query->withinPeriod($dateRange->startSql(), $dateRange->endSql());
|
||||
}
|
||||
})
|
||||
->get()
|
||||
->map(function (UnwantedEvent $item) {
|
||||
return [
|
||||
...$item->toArray(),
|
||||
'created_at' => Carbon::parse($item->created_at)->format('Создано d.m.Y в H:i'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Report>
|
||||
*/
|
||||
public function getReportsForDateRange(int $departmentId, DateRange $dateRange): Collection
|
||||
{
|
||||
return $this->contextResolver->getReportsForDateRange($departmentId, $dateRange);
|
||||
}
|
||||
|
||||
public function getRecipientPlanOfYear(Department $department, DateRange $dateRange): array
|
||||
{
|
||||
$periodPlanModel = $department->recipientPlanOfYear();
|
||||
$monthsInPeriod = ceil($dateRange->startDate->diffInMonths($dateRange->endDate));
|
||||
$annualPlan = $periodPlanModel ? (int) $periodPlanModel->value : 0;
|
||||
$oneMonthPlan = ceil($annualPlan / 12);
|
||||
$periodPlan = round($oneMonthPlan * $monthsInPeriod);
|
||||
|
||||
$query = $department->reports()
|
||||
->with('metrikaResults')
|
||||
->where('period_start', '>', $dateRange->startSql())
|
||||
->where('period_end', '<=', $dateRange->endSql());
|
||||
|
||||
if ($dateRange->isOneDay) {
|
||||
$query->where('period_start', '>=', $dateRange->startFirstOfMonth())
|
||||
->where('period_end', '<=', $dateRange->endSql());
|
||||
} else {
|
||||
$query->where('period_start', '>', $dateRange->startSql())
|
||||
->where('period_end', '<=', $dateRange->endSql());
|
||||
}
|
||||
|
||||
$progress = 0;
|
||||
|
||||
foreach ($query->get() as $report) {
|
||||
$outcome = $report->metrikaResults()
|
||||
->where('rf_metrika_item_id', MetrikaConfig::OUTCOME)
|
||||
->first();
|
||||
|
||||
if ($outcome) {
|
||||
$progress += (int) $outcome->value;
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'plan' => $periodPlan,
|
||||
'progress' => $progress,
|
||||
];
|
||||
}
|
||||
|
||||
private function isSendButtonActive(User $user, DateRange $dateRange, ?Report $reportToday): bool
|
||||
{
|
||||
if (! $user->isHeadOfDepartment() && ! $user->isAdmin()) {
|
||||
if ($reportToday && $reportToday->status === 'submitted') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $dateRange->isEndDateToday();
|
||||
}
|
||||
|
||||
return (bool) $reportToday && $dateRange->isOneDay;
|
||||
}
|
||||
|
||||
private function getDoctorInfo(?int $doctorId, DateRange $dateRange): ?MisLpuDoctor
|
||||
{
|
||||
if (! $doctorId || ! $dateRange->isOneDay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return MisLpuDoctor::query()
|
||||
->where('LPUDoctorID', $doctorId)
|
||||
->first();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user