feat(treatment): skip reasons and reopening for session areas
Skipping an area recorded only that it was skipped. Why it was skipped is clinical history — the next session needs to read it — so `skip` now takes an optional note, the same way completing an area already did, and the panel asks for it inline instead of firing on the first click. An operator finds out mid-laser that they closed the wrong area, and until now had to carry that mistake to the end of the session. `reopen` puts a settled area — completed or skipped — back to in_progress and clears finished_at, keeping the recorded parameters and note so they can be seen and overwritten. It stops at the same boundary everything else in this domain stops at: once the session is finished the record is history, and reopening it is 409. Also drops /admin/my-services. The staff role has one job — today's sessions — and the dashboard already lists the services they may perform, so the page was a second place to read the same list. Route, page, sidebar entry and the two links to it are gone; the services stat card is no longer a link because it no longer has a destination. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -151,10 +151,22 @@ class SessionExecutionController extends BaseController
|
||||
)->toArray());
|
||||
}
|
||||
|
||||
/** دلیلِ صرفنظر بخشی از سابقه است، پس `note` اینجا هم مثل «اتمام ناحیه» پذیرفته میشود. */
|
||||
#[Route('/api/v1/dashboard/staff/session-area/{uuid}/skip', name: 'staff_session_area_skip', methods: ['POST'])]
|
||||
public function skipArea(#[CurrentUser] User $user, string $uuid): JsonResponse
|
||||
public function skipArea(#[CurrentUser] User $user, string $uuid, Request $request): JsonResponse
|
||||
{
|
||||
return $this->success($this->executor->skipArea($this->requireAreaRecord($user, $uuid))->toArray());
|
||||
$record = $this->requireAreaRecord($user, $uuid);
|
||||
$data = json_decode($request->getContent(), true) ?? [];
|
||||
$note = is_string($data['note'] ?? null) ? trim($data['note']) : null;
|
||||
|
||||
return $this->success($this->executor->skipArea($record, $note !== '' ? $note : null)->toArray());
|
||||
}
|
||||
|
||||
/** اشتباهِ حین کار: ناحیهای که زودتر بسته شده تا وقتی جلسه باز است برمیگردد. */
|
||||
#[Route('/api/v1/dashboard/staff/session-area/{uuid}/reopen', name: 'staff_session_area_reopen', methods: ['POST'])]
|
||||
public function reopenArea(#[CurrentUser] User $user, string $uuid): JsonResponse
|
||||
{
|
||||
return $this->success($this->executor->reopenArea($this->requireAreaRecord($user, $uuid))->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -129,11 +129,32 @@ class SessionAreaRecord
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** بیمار امروز فقط یک ناحیه میخواهد — بقیه صرفنظر میشوند، نه ناتمام رها. */
|
||||
public function skip(): self
|
||||
/**
|
||||
* بیمار امروز فقط یک ناحیه میخواهد — بقیه صرفنظر میشوند، نه ناتمام رها.
|
||||
*
|
||||
* دلیلِ صرفنظر بخشی از سابقهٔ درمان است: «چرا این ناحیه انجام نشد» را جلسهٔ بعد
|
||||
* باید بتوان خواند، وگرنه فقط یک خلأ بیتوضیح میماند.
|
||||
*/
|
||||
public function skip(?string $note = null): self
|
||||
{
|
||||
$this->status = self::STATUS_SKIPPED;
|
||||
$this->finishedAt = time();
|
||||
$this->note = $note;
|
||||
$this->touch();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* برگرداندن ناحیهٔ بستهشده به حالت باز — برای اشتباهِ حین کار.
|
||||
*
|
||||
* `parameters` و `note` پاک نمیشوند تا اپراتور ببیند چه ثبت شده بود و رویش
|
||||
* بنویسد؛ `startedAt` هم میماند چون کار واقعاً شروع شده بود.
|
||||
*/
|
||||
public function reopen(): self
|
||||
{
|
||||
$this->status = $this->startedAt === null ? self::STATUS_PENDING : self::STATUS_IN_PROGRESS;
|
||||
$this->finishedAt = null;
|
||||
$this->touch();
|
||||
|
||||
return $this;
|
||||
|
||||
@@ -104,13 +104,41 @@ final class SessionExecutor
|
||||
}
|
||||
|
||||
/** بیمار امروز فقط یک ناحیه میخواهد — بقیه صرفنظر میشوند، نه ناتمام رها. */
|
||||
public function skipArea(SessionAreaRecord $record): SessionAreaRecord
|
||||
public function skipArea(SessionAreaRecord $record, ?string $note = null): SessionAreaRecord
|
||||
{
|
||||
if ($record->isSettled()) {
|
||||
throw new AppException(ErrorCodes::ERR_VALIDATION_001, 'این ناحیه قبلاً بسته شده است', 422);
|
||||
}
|
||||
|
||||
$record->skip();
|
||||
$record->skip($note);
|
||||
$this->em->flush();
|
||||
|
||||
return $record;
|
||||
}
|
||||
|
||||
/**
|
||||
* باز کردن دوبارهٔ ناحیهای که اشتباه بسته شده.
|
||||
*
|
||||
* فقط تا وقتی جلسه باز است: بعد از بستن جلسه، رکورد سابقهٔ درمان است و ویرایشش
|
||||
* یعنی بازنویسی سند — همان مرزی که `TreatmentCaseEditor` هم رویش ایستاده.
|
||||
*/
|
||||
public function reopenArea(SessionAreaRecord $record): SessionAreaRecord
|
||||
{
|
||||
if (!$record->isSettled()) {
|
||||
throw new AppException(ErrorCodes::ERR_VALIDATION_001, 'این ناحیه باز است', 422);
|
||||
}
|
||||
|
||||
$session = $record->getSession();
|
||||
|
||||
if (in_array($session->getStatus(), [TreatmentSession::STATUS_DONE, TreatmentSession::STATUS_CANCELLED], true)) {
|
||||
throw new AppException(
|
||||
ErrorCodes::ERR_CONFLICT_001,
|
||||
'جلسه بسته شده است؛ ناحیه دیگر قابل تغییر نیست',
|
||||
409,
|
||||
);
|
||||
}
|
||||
|
||||
$record->reopen();
|
||||
$this->em->flush();
|
||||
|
||||
return $record;
|
||||
|
||||
Reference in New Issue
Block a user