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>
This commit is contained in:
hamed
2026-08-02 13:16:53 +03:30
co-authored by Claude Opus 5
parent e08876f7b4
commit f11514950e
6 changed files with 274 additions and 0 deletions
+17
View File
@@ -551,6 +551,23 @@ override فقط وقتی اعمال می‌شود که `branch_uuid` به `valid
خطاها: `404` دستهٔ نامعتبر · `422` نبودِ `child_category_uuid`، حلقه، یا دستهٔ محیط دیگر.
### دستهٔ سرویس — `catalog_category_uuid` روی `POST/PATCH /api/v1/service-item[/{uuid}]`
سرویس **یک** دسته دارد (`ManyToOne`)، برخلاف منبع که چند دسته می‌گیرد؛ اندپوینت جدایی
ندارد و همان `PATCH` سرویس این فیلد را می‌پذیرد.
| مقدار | اثر |
|---|---|
| `"<uuid>"` | دسته ست می‌شود |
| `null` یا `""` | دسته پاک می‌شود |
| فیلد در بدنه نباشد | دستهٔ فعلی دست‌نخورده می‌ماند |
پاسخ ۲۰۰ کلِ سرویس است و `catalog_category_uuid` را برمی‌گرداند. **۴۲۲:** دستهٔ محیط دیگر
(`{"code":"ERR_VALIDATION_002","message":"دسته‌بندی یافت نشد","field":"catalog_category_uuid"}`).
در پنل، تب «دسته‌بندی‌ها»ی `/admin/service/{uuid}` فقط همین انتخاب را انجام می‌دهد؛ دکمهٔ
ساخت دسته عمداً آنجا نیست.
### دستهٔ منبع — `PUT /api/v1/resource/{uuid}/categories`
مستند کامل در [`resource.md`](resource.md).