Files
ladill-care/app/Http/Controllers/Care/RosterController.php
T
isaaccladandCursor b2cebe2908
Deploy Ladill Care / deploy (push) Successful in 1m0s
Add shift templates, unit duty roster grid, and Nursing Services hub.
Phase 3 staff management: real shift entities, week roster linked to temporary assignments, and a nursing ops module surface (registry, today’s allocation, unit shortcuts).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-20 10:40:25 +00:00

104 lines
4.1 KiB
PHP

<?php
namespace App\Http\Controllers\Care;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Models\CareUnit;
use App\Models\Member;
use App\Models\RosterEntry;
use App\Models\Shift;
use App\Services\Care\CarePermissions;
use App\Services\Care\RosterService;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;
class RosterController extends Controller
{
use ScopesToAccount;
public function show(Request $request, CareUnit $careUnit, RosterService $roster): View
{
$this->authorizeAbility($request, 'nursing.roster.view');
$this->authorizeOwner($request, $careUnit);
abort_unless((int) $careUnit->organization_id === (int) $this->organization($request)->id, 404);
$weekStart = $request->filled('week')
? Carbon::parse($request->input('week'))->startOfWeek(Carbon::MONDAY)
: now()->startOfWeek(Carbon::MONDAY);
$grid = $roster->unitWeekGrid($careUnit, $this->ownerRef($request), $weekStart);
$canManage = app(CarePermissions::class)->can($this->member($request), 'nursing.roster.manage');
return view('care.nursing.roster', [
'unit' => $careUnit->load('department.branch'),
'weekStart' => $grid['week_start'],
'days' => $grid['days'],
'shifts' => $grid['shifts'],
'cells' => $grid['cells'],
'members' => $grid['members'],
'memberLabels' => $grid['member_labels'],
'canManage' => $canManage,
'statuses' => config('care.roster_entry_statuses'),
'prevWeek' => $grid['week_start']->copy()->subWeek()->toDateString(),
'nextWeek' => $grid['week_start']->copy()->addWeek()->toDateString(),
]);
}
public function store(Request $request, CareUnit $careUnit, RosterService $roster): RedirectResponse
{
$this->authorizeAbility($request, 'nursing.roster.manage');
$this->authorizeOwner($request, $careUnit);
$organization = $this->organization($request);
abort_unless((int) $careUnit->organization_id === (int) $organization->id, 404);
$validated = $request->validate([
'shift_id' => ['required', 'integer', 'exists:care_shifts,id'],
'member_id' => ['required', 'integer', 'exists:care_members,id'],
'duty_date' => ['required', 'date'],
'notes' => ['nullable', 'string', 'max:1000'],
]);
$shift = Shift::owned($this->ownerRef($request))
->where('organization_id', $organization->id)
->findOrFail($validated['shift_id']);
$member = Member::owned($this->ownerRef($request))
->where('organization_id', $organization->id)
->findOrFail($validated['member_id']);
$roster->assign(
$careUnit,
$shift,
$member,
$validated['duty_date'],
$this->ownerRef($request),
$this->actorRef($request),
$validated['notes'] ?? null,
);
return redirect()
->route('care.care-units.roster', [
'careUnit' => $careUnit,
'week' => Carbon::parse($validated['duty_date'])->startOfWeek(Carbon::MONDAY)->toDateString(),
])
->with('success', 'Staff added to roster.');
}
public function destroy(Request $request, CareUnit $careUnit, RosterEntry $rosterEntry, RosterService $roster): RedirectResponse
{
$this->authorizeAbility($request, 'nursing.roster.manage');
$this->authorizeOwner($request, $careUnit);
$this->authorizeOwner($request, $rosterEntry);
abort_unless((int) $rosterEntry->care_unit_id === (int) $careUnit->id, 404);
$week = $rosterEntry->duty_date->copy()->startOfWeek(Carbon::MONDAY)->toDateString();
$roster->cancel($rosterEntry, $this->ownerRef($request), $this->actorRef($request));
return redirect()
->route('care.care-units.roster', ['careUnit' => $careUnit, 'week' => $week])
->with('success', 'Roster entry cancelled.');
}
}