122 lines
5.0 KiB
PHP
122 lines
5.0 KiB
PHP
<?php
|
||
|
||
namespace App\Tests\Resource;
|
||
|
||
use App\Resource\Entity\ClinicResource;
|
||
use App\Shared\Constant\ErrorCodes;
|
||
use App\Subscription\Entity\SubscriptionPlan;
|
||
|
||
/**
|
||
* سقف منابع بر اساس پلن اشتراک: free یک منبع، basic سه، professional بینهایت.
|
||
*
|
||
* سقف روی همهٔ منابع محیط اعمال میشود — فعال و غیرفعال — وگرنه یک بار
|
||
* غیرفعالکردن، سقف را دور میزد.
|
||
*/
|
||
class ResourceQuotaTest extends ResourceTestCase
|
||
{
|
||
public function testFreePlanAllowsExactlyOneResource(): void
|
||
{
|
||
$this->setPlanResourceQuota(1);
|
||
|
||
[$user, , $address] = $this->clinicWithAddress();
|
||
$type = $this->resourceType($address);
|
||
|
||
$this->createResource($user, $address, $type, ['name' => 'اتاق ۱']);
|
||
self::assertSame(201, $this->responseCode());
|
||
|
||
$body = $this->createResource($user, $address, $type, ['name' => 'اتاق ۲']);
|
||
|
||
self::assertSame(422, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE));
|
||
self::assertSame(ErrorCodes::ERR_RESOURCE_LIMIT_001, $body['errors'][0]['code']);
|
||
}
|
||
|
||
public function testBasicPlanAllowsThreeResourcesAndRejectsTheFourth(): void
|
||
{
|
||
$this->setPlanResourceQuota(3);
|
||
|
||
[$user, , $address] = $this->clinicWithAddress();
|
||
$type = $this->resourceType($address);
|
||
|
||
foreach (['اتاق ۱', 'اتاق ۲', 'اتاق ۳'] as $name) {
|
||
$this->createResource($user, $address, $type, ['name' => $name]);
|
||
self::assertSame(201, $this->responseCode(), $name);
|
||
}
|
||
|
||
$body = $this->createResource($user, $address, $type, ['name' => 'اتاق ۴']);
|
||
|
||
self::assertSame(422, $this->responseCode());
|
||
self::assertSame(ErrorCodes::ERR_RESOURCE_LIMIT_001, $body['errors'][0]['code']);
|
||
self::assertStringContainsString('۳', $this->toPersianDigits($body['errors'][0]['message']));
|
||
}
|
||
|
||
public function testProfessionalPlanIsUnlimited(): void
|
||
{
|
||
$this->setPlanResourceQuota(SubscriptionPlan::UNLIMITED);
|
||
|
||
[$user, , $address] = $this->clinicWithAddress();
|
||
$type = $this->resourceType($address);
|
||
|
||
foreach (range(1, 5) as $i) {
|
||
$this->createResource($user, $address, $type, ['name' => "اتاق $i"]);
|
||
self::assertSame(201, $this->responseCode(), "resource #$i");
|
||
}
|
||
}
|
||
|
||
/** غیرفعالکردن منبع، جای خالی نمیسازد. */
|
||
public function testDeactivatedResourcesStillCountTowardTheQuota(): void
|
||
{
|
||
$this->setPlanResourceQuota(1);
|
||
|
||
[$user, , $address] = $this->clinicWithAddress();
|
||
$type = $this->resourceType($address);
|
||
|
||
$first = $this->createResource($user, $address, $type, ['name' => 'اتاق ۱']);
|
||
$this->authJson('PATCH', '/api/v1/resource/' . $first['data']['uuid'], $user, ['active' => false]);
|
||
self::assertSame(200, $this->responseCode());
|
||
|
||
$this->createResource($user, $address, $type, ['name' => 'اتاق ۲']);
|
||
self::assertSame(422, $this->responseCode());
|
||
}
|
||
|
||
/** حذف منبع، جا را واقعاً آزاد میکند — شمارش زندهٔ دیتابیس است نه شمارندهٔ ذخیرهشده. */
|
||
public function testDeletingAResourceFreesTheSlot(): void
|
||
{
|
||
$this->setPlanResourceQuota(1);
|
||
|
||
[$user, , $address] = $this->clinicWithAddress();
|
||
$type = $this->resourceType($address);
|
||
|
||
$first = $this->createResource($user, $address, $type, ['name' => 'اتاق ۱']);
|
||
$this->authJson('DELETE', '/api/v1/resource/' . $first['data']['uuid'], $user);
|
||
self::assertSame(200, $this->responseCode());
|
||
|
||
$this->createResource($user, $address, $type, ['name' => 'اتاق ۲']);
|
||
self::assertSame(201, $this->responseCode());
|
||
}
|
||
|
||
/** سقف مالِ همان محیط است؛ پر شدن یک کلینیک، کلینیک دیگر را قفل نمیکند. */
|
||
public function testQuotaIsCountedPerTenantPair(): void
|
||
{
|
||
$this->setPlanResourceQuota(1);
|
||
|
||
[$userA, , $addressA] = $this->clinicWithAddress();
|
||
$this->createResource($userA, $addressA, $this->resourceType($addressA), ['name' => 'اتاق A']);
|
||
self::assertSame(201, $this->responseCode());
|
||
|
||
[$userB, , $addressB] = $this->clinicWithAddress('شعبهٔ کلینیک دوم');
|
||
$this->createResource($userB, $addressB, $this->resourceType($addressB), ['name' => 'اتاق B']);
|
||
|
||
self::assertSame(201, $this->responseCode());
|
||
self::assertSame(1, $this->em->getRepository(ClinicResource::class)->countForPair(
|
||
$addressB->tenantEntityType(),
|
||
$addressB->tenantEntityId(),
|
||
));
|
||
}
|
||
|
||
private function toPersianDigits(string $value): string
|
||
{
|
||
return strtr($value, ['0' => '۰', '1' => '۱', '2' => '۲', '3' => '۳', '4' => '۴',
|
||
'5' => '۵', '6' => '۶', '7' => '۷', '8' => '۸', '9' => '۹']);
|
||
}
|
||
}
|