Wire specialty Start consultation to the real consultation page.
Deploy Ladill Care / deploy (push) Successful in 58s
Deploy Ladill Care / deploy (push) Successful in 58s
Doctors leave the specialty shell into Care consultations instead of a no-op workspace link. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -8,7 +8,9 @@ use App\Models\Appointment;
|
||||
use App\Models\Department;
|
||||
use App\Models\PatientAttachment;
|
||||
use App\Models\Visit;
|
||||
use App\Services\Care\AppointmentService;
|
||||
use App\Services\Care\CareQueueBridge;
|
||||
use App\Services\Care\ConsultationService;
|
||||
use App\Services\Care\OrganizationResolver;
|
||||
use App\Services\Care\SpecialtyClinicalRecordService;
|
||||
use App\Services\Care\SpecialtyModuleService;
|
||||
@@ -107,6 +109,69 @@ class SpecialtyModuleController extends Controller
|
||||
return back()->with('success', 'Added to invoice '.$bill->invoice_number.'.');
|
||||
}
|
||||
|
||||
public function startConsultation(
|
||||
Request $request,
|
||||
string $module,
|
||||
Visit $visit,
|
||||
SpecialtyModuleService $modules,
|
||||
AppointmentService $appointments,
|
||||
ConsultationService $consultations,
|
||||
): RedirectResponse {
|
||||
$this->authorizeAbility($request, 'consultations.manage');
|
||||
|
||||
$definition = $modules->definition($module);
|
||||
abort_unless($definition, 404);
|
||||
|
||||
$organization = $this->organization($request);
|
||||
$member = $this->member($request);
|
||||
abort_unless($modules->memberCanAccess($organization, $member, $module), 403);
|
||||
abort_unless($visit->organization_id === $organization->id, 404);
|
||||
$this->authorizeBranch($request, (int) $visit->branch_id);
|
||||
|
||||
$visit->loadMissing(['appointment.consultation', 'appointment.practitioner']);
|
||||
$appointment = $visit->appointment;
|
||||
if (! $appointment || $appointment->organization_id !== $organization->id) {
|
||||
return back()->with('error', 'This visit has no appointment to start a consultation from.');
|
||||
}
|
||||
|
||||
$owner = $this->ownerRef($request);
|
||||
$openConsultation = $appointment->consultation;
|
||||
if ($openConsultation && $openConsultation->status !== \App\Models\Consultation::STATUS_COMPLETED) {
|
||||
return redirect()
|
||||
->route('care.consultations.show', $openConsultation)
|
||||
->with('success', 'Consultation already in progress.');
|
||||
}
|
||||
|
||||
try {
|
||||
if (in_array($appointment->status, [
|
||||
Appointment::STATUS_WAITING,
|
||||
Appointment::STATUS_CHECKED_IN,
|
||||
], true)) {
|
||||
$appointments->startConsultation(
|
||||
$appointment,
|
||||
$owner,
|
||||
$appointment->practitioner_id,
|
||||
$owner,
|
||||
);
|
||||
$appointment = $appointment->fresh(['practitioner', 'visit']);
|
||||
} elseif ($appointment->status !== Appointment::STATUS_IN_CONSULTATION) {
|
||||
return back()->with('error', 'This appointment cannot start a consultation from its current status.');
|
||||
}
|
||||
|
||||
$consultation = $consultations->startFromAppointment(
|
||||
$appointment,
|
||||
$owner,
|
||||
$owner,
|
||||
);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
return back()->with('error', $e->getMessage());
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route('care.consultations.show', $consultation)
|
||||
->with('success', 'Consultation started.');
|
||||
}
|
||||
|
||||
public function saveClinical(
|
||||
Request $request,
|
||||
string $module,
|
||||
@@ -327,6 +392,7 @@ class SpecialtyModuleController extends Controller
|
||||
'patient.emergencyContacts',
|
||||
'patient.attachments',
|
||||
'appointment.practitioner',
|
||||
'appointment.consultation',
|
||||
'bill.lineItems',
|
||||
'consultations',
|
||||
]);
|
||||
@@ -346,6 +412,7 @@ class SpecialtyModuleController extends Controller
|
||||
'patient.emergencyContacts',
|
||||
'patient.attachments',
|
||||
'appointment.practitioner',
|
||||
'appointment.consultation',
|
||||
'bill.lineItems',
|
||||
'consultations',
|
||||
]);
|
||||
|
||||
@@ -75,9 +75,35 @@
|
||||
])
|
||||
|
||||
@if ($workspaceVisit)
|
||||
@php
|
||||
$appointment = $workspaceVisit->appointment;
|
||||
$openConsultation = $appointment?->consultation;
|
||||
$canStartConsultation = $appointment && in_array($appointment->status, [
|
||||
\App\Models\Appointment::STATUS_WAITING,
|
||||
\App\Models\Appointment::STATUS_CHECKED_IN,
|
||||
], true);
|
||||
$consultationInProgress = $appointment
|
||||
&& (
|
||||
$appointment->status === \App\Models\Appointment::STATUS_IN_CONSULTATION
|
||||
|| ($openConsultation && $openConsultation->status !== \App\Models\Consultation::STATUS_COMPLETED)
|
||||
);
|
||||
@endphp
|
||||
@if ($consultationInProgress && $openConsultation)
|
||||
<a href="{{ route('care.consultations.show', $openConsultation) }}"
|
||||
class="flex w-full items-center justify-center rounded-xl bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-700">
|
||||
Open consultation
|
||||
</a>
|
||||
@elseif ($canStartConsultation)
|
||||
<form method="POST" action="{{ route('care.specialty.consultation.start', ['module' => $moduleKey, 'visit' => $workspaceVisit]) }}">
|
||||
@csrf
|
||||
<button type="submit" class="flex w-full items-center justify-center rounded-xl bg-indigo-600 px-3 py-2 text-sm font-semibold text-white hover:bg-indigo-700">
|
||||
{{ $actions['start'] ?? 'Start consultation' }}
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
<a href="{{ route('care.specialty.workspace', ['module' => $moduleKey, 'visit' => $workspaceVisit]) }}"
|
||||
class="flex w-full items-center justify-center rounded-xl border border-slate-200 bg-slate-50 px-3 py-2 text-sm font-medium text-slate-800 hover:bg-slate-100">
|
||||
{{ $actions['start'] ?? 'Open workspace' }}
|
||||
Specialty workspace
|
||||
</a>
|
||||
@if ($workspaceVisit->patient)
|
||||
<a href="{{ route('care.patients.show', $workspaceVisit->patient) }}"
|
||||
|
||||
@@ -115,6 +115,7 @@ Route::middleware(['auth', 'platform.session'])->group(function () {
|
||||
Route::post('/specialty/{module}/workspace/{visit}/clinical', [SpecialtyModuleController::class, 'saveClinical'])->name('care.specialty.clinical.save');
|
||||
Route::post('/specialty/{module}/workspace/{visit}/documents', [SpecialtyModuleController::class, 'uploadDocument'])->name('care.specialty.documents.upload');
|
||||
Route::post('/specialty/{module}/workspace/{visit}/services', [SpecialtyModuleController::class, 'addService'])->name('care.specialty.services.add');
|
||||
Route::post('/specialty/{module}/workspace/{visit}/start-consultation', [SpecialtyModuleController::class, 'startConsultation'])->name('care.specialty.consultation.start');
|
||||
Route::get('/specialty/{module}', [SpecialtyModuleController::class, 'show'])->name('care.specialty.show');
|
||||
Route::post('/specialty/{module}/call-next', [SpecialtyModuleController::class, 'callNext'])->name('care.specialty.call-next');
|
||||
|
||||
|
||||
@@ -205,4 +205,66 @@ class CareSpecialtyShellTest extends TestCase
|
||||
$bill->lineItems()->where('description', 'Emergency consultation')->exists()
|
||||
);
|
||||
}
|
||||
|
||||
public function test_specialty_start_consultation_opens_consultation_page(): void
|
||||
{
|
||||
app(SpecialtyModuleService::class)->activate(
|
||||
$this->organization,
|
||||
$this->owner->public_id,
|
||||
'dentistry',
|
||||
);
|
||||
|
||||
$department = Department::query()
|
||||
->where('branch_id', $this->branch->id)
|
||||
->where('type', 'dental')
|
||||
->firstOrFail();
|
||||
|
||||
$patient = Patient::create([
|
||||
'owner_ref' => $this->owner->public_id,
|
||||
'organization_id' => $this->organization->id,
|
||||
'branch_id' => $this->branch->id,
|
||||
'patient_number' => 'P-DEN-1',
|
||||
'first_name' => 'Abena',
|
||||
'last_name' => 'Osei',
|
||||
'gender' => 'female',
|
||||
'date_of_birth' => '1993-01-01',
|
||||
]);
|
||||
|
||||
$visit = Visit::create([
|
||||
'owner_ref' => $this->owner->public_id,
|
||||
'organization_id' => $this->organization->id,
|
||||
'branch_id' => $this->branch->id,
|
||||
'patient_id' => $patient->id,
|
||||
'status' => Visit::STATUS_OPEN,
|
||||
'checked_in_at' => now(),
|
||||
]);
|
||||
|
||||
$appointment = Appointment::create([
|
||||
'owner_ref' => $this->owner->public_id,
|
||||
'organization_id' => $this->organization->id,
|
||||
'branch_id' => $this->branch->id,
|
||||
'patient_id' => $patient->id,
|
||||
'department_id' => $department->id,
|
||||
'visit_id' => $visit->id,
|
||||
'type' => Appointment::TYPE_WALK_IN,
|
||||
'status' => Appointment::STATUS_WAITING,
|
||||
'scheduled_at' => now(),
|
||||
'waiting_at' => now(),
|
||||
'checked_in_at' => now(),
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($this->owner)
|
||||
->post(route('care.specialty.consultation.start', [
|
||||
'module' => 'dentistry',
|
||||
'visit' => $visit,
|
||||
]));
|
||||
|
||||
$consultation = \App\Models\Consultation::query()
|
||||
->where('appointment_id', $appointment->id)
|
||||
->first();
|
||||
$this->assertNotNull($consultation);
|
||||
|
||||
$response->assertRedirect(route('care.consultations.show', $consultation));
|
||||
$this->assertSame(Appointment::STATUS_IN_CONSULTATION, $appointment->fresh()->status);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user