refactor(resource): drop the branch domain from resources
Resources never needed a branch: devices and rooms belong to the clinic itself, and the picker always had exactly one option — a mandatory click that decided nothing. - `address_uuid` is now optional on resource and pool creation; when it is missing the environment's own address is used. Clients still sending it keep working. - The panel no longer asks for or displays a branch anywhere: resource form, list column and filter, pool form and column, detail row, and the resource-first booking page. - Availability no longer gates on `doctor_addresses.active`. That gate shut down every device of a clinic whose address row happened to be inactive, with a message no page in the panel could act on — no endpoint writes that column at all. `address_id` stays on the resource: the timezone and the tenant pair are derived from it. It is simply no longer the user's decision. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -73,8 +73,8 @@ class ResourceController extends BaseController
|
||||
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!is_array($data) || !is_string($data['address_uuid'] ?? null)) {
|
||||
return $this->error(ErrorCodes::ERR_VALIDATION_002, 'فیلد address_uuid الزامی است', 422, 'address_uuid');
|
||||
if (!is_array($data)) {
|
||||
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'بدنهٔ درخواست نامعتبر است', 422);
|
||||
}
|
||||
|
||||
if (!is_string($data['type_uuid'] ?? null)) {
|
||||
@@ -87,7 +87,11 @@ class ResourceController extends BaseController
|
||||
return $this->error(ErrorCodes::ERR_VALIDATION_002, 'انتخاب پزشک ناظر الزامی است', 422, 'supervisor_doctor_uuid');
|
||||
}
|
||||
|
||||
$address = $this->context->address($user, $data['address_uuid']);
|
||||
// شعبه از کاربر پرسیده نمیشود؛ آدرسِ خودِ محیط مبناست. `address_uuid` فقط برای
|
||||
// سازگاری با کلاینتهای قدیمی پذیرفته میشود.
|
||||
$address = is_string($data['address_uuid'] ?? null) && $data['address_uuid'] !== ''
|
||||
? $this->context->address($user, $data['address_uuid'])
|
||||
: $this->context->defaultAddress($user);
|
||||
$type = $this->context->type($user, $data['type_uuid']);
|
||||
$supervisor = $this->context->supervisor($user, $data['supervisor_doctor_uuid']);
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ class ResourcePoolController extends BaseController
|
||||
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!is_array($data) || !is_string($data['address_uuid'] ?? null)) {
|
||||
return $this->error(ErrorCodes::ERR_VALIDATION_002, 'فیلد address_uuid الزامی است', 422, 'address_uuid');
|
||||
if (!is_array($data)) {
|
||||
return $this->error(ErrorCodes::ERR_VALIDATION_001, 'بدنهٔ درخواست نامعتبر است', 422);
|
||||
}
|
||||
|
||||
if (!is_string($data['type_uuid'] ?? null)) {
|
||||
@@ -64,8 +64,11 @@ class ResourcePoolController extends BaseController
|
||||
return $this->error(ErrorCodes::ERR_VALIDATION_002, 'نام استخر الزامی است', 422, 'name');
|
||||
}
|
||||
|
||||
// مثل منبع: شعبه پرسیده نمیشود و آدرسِ خودِ محیط مبناست.
|
||||
$pool = new ResourcePool(
|
||||
$this->context->address($user, $data['address_uuid']),
|
||||
is_string($data['address_uuid'] ?? null) && $data['address_uuid'] !== ''
|
||||
? $this->context->address($user, $data['address_uuid'])
|
||||
: $this->context->defaultAddress($user),
|
||||
$this->context->type($user, $data['type_uuid']),
|
||||
$name,
|
||||
);
|
||||
|
||||
@@ -171,9 +171,13 @@ final class ResourceAvailabilityService
|
||||
return new DayAvailability($midnight, $dayOfWeek, [], ['resource_inactive']);
|
||||
}
|
||||
|
||||
if (!$resource->getAddress()->isActive()) {
|
||||
return new DayAvailability($midnight, $dayOfWeek, [], ['address_inactive']);
|
||||
}
|
||||
/**
|
||||
* فعالبودنِ آدرس اینجا سنجیده **نمیشود**.
|
||||
*
|
||||
* منابع دامنهٔ شعبه ندارند: آدرس فقط حاملِ منطقهٔ زمانی و جفتِ محیط است و هیچ
|
||||
* جای پنل هم روشن/خاموشش نمیکند. وقتی میشد، یک ردیفِ قدیمیِ `active = 0` کلِ
|
||||
* دستگاههای کلینیک را با پیامی خاموش میکرد که کاربر راهی برای رفعش نداشت.
|
||||
*/
|
||||
|
||||
$override = $overrideMap[$midnight] ?? null;
|
||||
$holiday = $holidayMap[$midnight] ?? null;
|
||||
|
||||
@@ -54,6 +54,31 @@ final class ResourceContext
|
||||
return $this->branches->resolve($user, $addressUuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* آدرسِ خودِ محیط — مطب یا کلینیک.
|
||||
*
|
||||
* منابع دامنهٔ «شعبه» ندارند: دستگاه و اتاق مالِ همین کلینیکاند و پرسیدنِ شعبه از
|
||||
* کاربر یک انتخابِ همیشهیکسان بود. آدرس همچنان نگه داشته میشود چون منطقهٔ زمانی و
|
||||
* جفتِ محیطِ منبع از آن مشتق میشوند، ولی کاربر دیگر انتخابش نمیکند.
|
||||
*
|
||||
* محیطی که چند آدرس دارد، اولینش را میگیرد؛ ترتیب از خودِ مخزن میآید و پایدار است.
|
||||
*/
|
||||
public function defaultAddress(User $user): DoctorAddress
|
||||
{
|
||||
$addresses = $this->branches->listForContext($user);
|
||||
|
||||
if ($addresses === []) {
|
||||
throw new AppException(
|
||||
ErrorCodes::ERR_VALIDATION_002,
|
||||
'برای این محیط آدرسی ثبت نشده است — ابتدا آدرس کلینیک را کامل کنید',
|
||||
422,
|
||||
'address_uuid',
|
||||
);
|
||||
}
|
||||
|
||||
return $addresses[array_key_first($addresses)];
|
||||
}
|
||||
|
||||
public function type(User $user, string $uuid): ResourceType
|
||||
{
|
||||
return $this->owned($user, $this->types->findByUuid($uuid), 'نوع منبع یافت نشد');
|
||||
|
||||
@@ -16,7 +16,7 @@ final readonly class DayAvailability
|
||||
* @param list<TimeInterval> $intervals بازههای آزاد، بهصورت timestamp مطلق
|
||||
* @param list<string> $reasons `national_holiday`، `tenant_holiday`، `no_shift`،
|
||||
* `branch_closed`، `outside_branch_hours`، `exception`،
|
||||
* `resource_inactive`، `branch_inactive`
|
||||
* `resource_inactive`
|
||||
*/
|
||||
public function __construct(
|
||||
public int $date,
|
||||
|
||||
Reference in New Issue
Block a user