- Implement real-time validation for overlapping shifts in the ResourceWorkingHoursPanel. - Remove the copy shift functionality to simplify the UI and prevent confusion. - Introduce ResourceExceptionsCard to manage resource exceptions, including leave and maintenance. - Update ClinicAppointmentSettingsPage to utilize new components and improve tab navigation for resource management. - Add comprehensive validation tests for resource calendar to ensure overlapping shifts are correctly handled. - Update API documentation to reflect new validation error messages and rules.
100 lines
4.4 KiB
PHP
100 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Resource;
|
|
|
|
/**
|
|
* قواعد اعتبارسنجی شیفت هفتگی منبع.
|
|
*
|
|
* پنل ادمین همین سه قاعده را حین تایپ هم اجرا میکند، ولی مرجع نهایی سرور است:
|
|
* کلاینت قدیمی، اسکریپت، و درخواست مستقیم به API نباید بتوانند شیفت متداخل بنشانند.
|
|
*/
|
|
class ResourceCalendarValidationTest extends ResourceTestCase
|
|
{
|
|
/** @param array<int|string, mixed> $days */
|
|
private function putCalendar(array $days): array
|
|
{
|
|
[$user, , $address] = $this->clinicWithAddress();
|
|
$resource = $this->createResource($user, $address, $this->resourceType($address));
|
|
|
|
return $this->authJson(
|
|
'PUT',
|
|
"/api/v1/resource/{$resource['data']['uuid']}/calendar",
|
|
$user,
|
|
['days' => $days],
|
|
);
|
|
}
|
|
|
|
/** ۰۹:۰۰–۱۳:۰۰ کنار ۱۲:۰۰–۱۷:۰۰ یعنی یک ساعت ظرفیتِ دوبارهفروختهشده. */
|
|
public function testOverlappingShiftsInTheSameDayAreRejected(): void
|
|
{
|
|
$body = $this->putCalendar([
|
|
0 => [
|
|
['start_minute' => 540, 'end_minute' => 780], // ۰۹:۰۰–۱۳:۰۰
|
|
['start_minute' => 720, 'end_minute' => 1020], // ۱۲:۰۰–۱۷:۰۰
|
|
],
|
|
]);
|
|
|
|
self::assertSame(422, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE));
|
|
self::assertSame('start_minute', $body['errors'][0]['field']);
|
|
self::assertStringContainsString('شنبه', $body['errors'][0]['message'], 'پیام باید نام روز را بگوید نه اندیس');
|
|
self::assertStringContainsString('تداخل', $body['errors'][0]['message']);
|
|
}
|
|
|
|
/** ترتیب ورودی نباید مهم باشد: تداخل بین شیفت اول و سوم هم باید دیده شود. */
|
|
public function testOverlapIsDetectedRegardlessOfInputOrder(): void
|
|
{
|
|
$body = $this->putCalendar([
|
|
2 => [
|
|
['start_minute' => 900, 'end_minute' => 1020], // ۱۵:۰۰–۱۷:۰۰
|
|
['start_minute' => 540, 'end_minute' => 600], // ۰۹:۰۰–۱۰:۰۰
|
|
['start_minute' => 960, 'end_minute' => 1080], // ۱۶:۰۰–۱۸:۰۰ ← با اولی تداخل دارد
|
|
],
|
|
]);
|
|
|
|
self::assertSame(422, $this->responseCode());
|
|
self::assertStringContainsString('دوشنبه', $body['errors'][0]['message']);
|
|
}
|
|
|
|
/** مرزِ چسبیده همپوشانی نیست: ۱۳:۰۰ پایانِ یکی و شروعِ بعدی، شیفت صبح و عصر است. */
|
|
public function testBackToBackShiftsAreAccepted(): void
|
|
{
|
|
$body = $this->putCalendar([
|
|
0 => [
|
|
['start_minute' => 540, 'end_minute' => 780],
|
|
['start_minute' => 780, 'end_minute' => 1020],
|
|
],
|
|
]);
|
|
|
|
self::assertSame(200, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE));
|
|
self::assertCount(2, $body['data']['days']['0']);
|
|
}
|
|
|
|
/** اعتبارسنجی کامل پیش از هر حذفی — روز نامعتبر نباید روزهای درست را پاک کند. */
|
|
public function testAnInvalidDayLeavesTheExistingCalendarUntouched(): void
|
|
{
|
|
[$user, , $address] = $this->clinicWithAddress();
|
|
$resource = $this->createResource($user, $address, $this->resourceType($address));
|
|
$uuid = $resource['data']['uuid'];
|
|
|
|
$this->authJson('PUT', "/api/v1/resource/$uuid/calendar", $user, [
|
|
'days' => [0 => [['start_minute' => 540, 'end_minute' => 1020]]],
|
|
]);
|
|
self::assertSame(200, $this->responseCode());
|
|
|
|
$this->authJson('PUT', "/api/v1/resource/$uuid/calendar", $user, [
|
|
'days' => [
|
|
0 => [['start_minute' => 540, 'end_minute' => 1020]],
|
|
1 => [
|
|
['start_minute' => 540, 'end_minute' => 780],
|
|
['start_minute' => 600, 'end_minute' => 900],
|
|
],
|
|
],
|
|
]);
|
|
self::assertSame(422, $this->responseCode());
|
|
|
|
$body = $this->authJson('GET', "/api/v1/resource/$uuid/calendar", $user);
|
|
self::assertCount(1, $body['data']['days']['0'], 'شنبهٔ قبلی سرِ جایش مانده');
|
|
self::assertSame([], $body['data']['days']['1']);
|
|
}
|
|
}
|