Deploy Ladill Care / deploy (push) Successful in 57s
Replace broad doctor/nurse specialty access with granular roles and primary apps, permission inheritance for lab/BB managers, and cannot-rules for discharge, lab approve, and cashier vs billing officer. Co-authored-by: Cursor <cursoragent@cursor.com>
98 lines
3.1 KiB
PHP
98 lines
3.1 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Care;
|
|
|
|
use App\Models\Branch;
|
|
use App\Models\Member;
|
|
use App\Models\Organization;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Collection;
|
|
|
|
/**
|
|
* Resolves which Care branch the current user is working in.
|
|
*
|
|
* Doctors may be assigned to multiple sites (telemedicine) but only those
|
|
* explicitly linked on their practitioner desks — never org-wide by default.
|
|
* Hospital admins pick among all branches; that choice is remembered in session.
|
|
*/
|
|
class BranchContext
|
|
{
|
|
public const SESSION_KEY = 'care.preferred_branch_id';
|
|
|
|
public function __construct(
|
|
protected OrganizationResolver $organizations,
|
|
) {}
|
|
|
|
public function canSwitch(?Member $member): bool
|
|
{
|
|
if ($member === null) {
|
|
return false;
|
|
}
|
|
|
|
if ($member->role === 'doctor' || app(CarePermissions::class)->usesPractitionerBranchScope($member)) {
|
|
return count($this->organizations->doctorAssignedBranchIds($member)) > 1;
|
|
}
|
|
|
|
// Other site clinicians stay on their assigned branch — never a picker.
|
|
if (in_array($member->role, app(CarePermissions::class)->floorCareRoles(), true)
|
|
&& ! app(CarePermissions::class)->usesPractitionerBranchScope($member)) {
|
|
return false;
|
|
}
|
|
|
|
return $this->organizations->allowedBranchIds($member) === null;
|
|
}
|
|
|
|
/**
|
|
* Active branches the member may see.
|
|
*
|
|
* @return Collection<int, Branch>
|
|
*/
|
|
public function branches(Request $request, Organization $organization, ?Member $member): Collection
|
|
{
|
|
$ids = $this->organizations->allowedBranchIds($member);
|
|
|
|
return Branch::owned((string) $organization->owner_ref)
|
|
->where('organization_id', $organization->id)
|
|
->where('is_active', true)
|
|
->when($ids !== null, fn ($q) => $q->whereIn('id', $ids !== [] ? $ids : [0]))
|
|
->orderBy('name')
|
|
->get();
|
|
}
|
|
|
|
/**
|
|
* Preferred working branch id (0 when none allowed).
|
|
* Persists switcher selections from ?branch_id= into the session.
|
|
*/
|
|
public function resolve(Request $request, Organization $organization, ?Member $member): int
|
|
{
|
|
$branches = $this->branches($request, $organization, $member);
|
|
$allowed = $branches->pluck('id')->map(fn ($id) => (int) $id)->all();
|
|
if ($allowed === []) {
|
|
return 0;
|
|
}
|
|
|
|
if ($this->canSwitch($member)) {
|
|
if ($request->filled('branch_id')) {
|
|
$requested = (int) $request->input('branch_id');
|
|
if (in_array($requested, $allowed, true)) {
|
|
$request->session()->put(self::SESSION_KEY, $requested);
|
|
|
|
return $requested;
|
|
}
|
|
}
|
|
|
|
$preferred = (int) $request->session()->get(self::SESSION_KEY, 0);
|
|
if ($preferred > 0 && in_array($preferred, $allowed, true)) {
|
|
return $preferred;
|
|
}
|
|
|
|
$fallback = (int) $branches->first()->id;
|
|
$request->session()->put(self::SESSION_KEY, $fallback);
|
|
|
|
return $fallback;
|
|
}
|
|
|
|
return (int) $allowed[0];
|
|
}
|
|
}
|