Files
clinicpro/tests/ClinicService/ServiceItemCatalogCategoryTest.php
T
hamedandClaude Opus 5 f11514950e feat(services): pick a global category from the service page
The service page could not say which category a service belongs to, so the
containment edges defined in settings had nothing to match against.

A Categories tab now selects one — and only selects. Creating, renaming and
deleting stay in Settings > Categories: if every page could create one,
"whole body" would exist three times with three spellings and the
includes edge would stop catching anything.

PATCH /api/v1/service-item/{uuid} carries the choice as
catalog_category_uuid. Absent field leaves the current category alone, null
clears it, and a category from another environment is refused with 422 —
the uuid arrives in the request body where TenantFilter does not reach.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 13:16:53 +03:30

102 lines
4.3 KiB
PHP

<?php
namespace App\Tests\ClinicService;
use App\Auth\Entity\User;
use App\ClinicService\Entity\ServiceItem;
use App\ClinicService\Entity\ServiceSection;
use App\Doctor\Entity\Doctor;
use App\Tests\ApiTestCase;
/**
* تب «دسته‌بندی‌ها»ی صفحهٔ سرویس فقط **انتخاب** می‌کند و همین `PATCH` پشتش است.
*
* دسته ساخته نمی‌شود؛ ساختش فقط از «تنظیمات ← دسته‌بندی‌ها» است. اینجا اثبات می‌شود که
* انتخاب می‌نشیند، پاک می‌شود، و دستهٔ محیط دیگر رد می‌شود.
*/
class ServiceItemCatalogCategoryTest extends ApiTestCase
{
/** @return array{0: User, 1: ServiceItem} */
private function doctorWithItem(): array
{
$owner = $this->createUser(['ROLE_DOCTOR']);
$doctor = new Doctor($owner, 'دکتر دسته‌بندی');
$this->em->persist($doctor);
$this->em->flush();
$section = new ServiceSection('doctor', $doctor->getId(), 'لیزر');
$item = new ServiceItem($section, 'لیزر دست');
$item->setPriceRials(5_000_000);
$this->em->persist($section);
$this->em->persist($item);
$this->em->flush();
return [$owner, $item];
}
private function category(User $user, string $name): string
{
$body = $this->authJson('POST', '/api/v1/service-category', $user, ['name' => $name]);
self::assertSame(201, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE));
return $body['data']['uuid'];
}
// ── ✅ موفق ──────────────────────────────────────────────────────────────
public function testAServiceTakesAGlobalCategory(): void
{
[$owner, $item] = $this->doctorWithItem();
$hand = $this->category($owner, 'دست');
$body = $this->authJson('PATCH', '/api/v1/service-item/' . $item->getUuid(), $owner, [
'catalog_category_uuid' => $hand,
]);
self::assertSame(200, $this->responseCode(), json_encode($body, JSON_UNESCAPED_UNICODE));
self::assertSame($hand, $body['data']['catalog_category_uuid']);
}
public function testNullClearsTheCategory(): void
{
[$owner, $item] = $this->doctorWithItem();
$hand = $this->category($owner, 'دست');
$this->authJson('PATCH', '/api/v1/service-item/' . $item->getUuid(), $owner, ['catalog_category_uuid' => $hand]);
$body = $this->authJson('PATCH', '/api/v1/service-item/' . $item->getUuid(), $owner, ['catalog_category_uuid' => null]);
self::assertSame(200, $this->responseCode());
self::assertNull($body['data']['catalog_category_uuid']);
}
// ── ⚠️ مرزی ─────────────────────────────────────────────────────────────
public function testNotSendingTheFieldLeavesTheCategoryAlone(): void
{
[$owner, $item] = $this->doctorWithItem();
$hand = $this->category($owner, 'دست');
$this->authJson('PATCH', '/api/v1/service-item/' . $item->getUuid(), $owner, ['catalog_category_uuid' => $hand]);
// فیلد در بدنه نیست: ویرایش نام نباید دسته را پاک کند.
$body = $this->authJson('PATCH', '/api/v1/service-item/' . $item->getUuid(), $owner, ['name' => 'لیزر دست کامل']);
self::assertSame($hand, $body['data']['catalog_category_uuid']);
}
// ── ❌ خطا ───────────────────────────────────────────────────────────────
public function testACategoryFromAnotherEnvironmentIsRefused(): void
{
[$owner, $item] = $this->doctorWithItem();
[$stranger] = $this->doctorWithItem();
$foreign = $this->category($stranger, 'دستهٔ پزشک دیگر');
$this->authJson('PATCH', '/api/v1/service-item/' . $item->getUuid(), $owner, [
'catalog_category_uuid' => $foreign,
]);
self::assertSame(422, $this->responseCode());
}
}