# چک‌لیست — تسک ۰۱ (شعبه و اتاق)

**وضعیت کلی:** ✅ تکمیل‌شده (۲ ردیف 🔄 بازبینی چشمی) · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۸

قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) ·
[red-lines.md](../_shared/red-lines.md) · [ui-conventions.md](../_shared/ui-conventions.md) ·
[branch-is-doctor-address.md](../_shared/branch-is-doctor-address.md)

---

## ۰. خط سرخ

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۰.۱ | `--group=slot-mode-frozen` سبز | ✅ | `--group=slot-mode-frozen` — ۳ تست / ۸ assertion سبز |
| ۰.۲ | `SlotCalculatorService` دست‌نخورده | ✅ | صفر تغییر در فایل |
| ۰.۳ | `location_id` در JSON برنامهٔ هفتگی دست‌نخورده | ✅ | شعبه = همان `doctor_addresses.id`؛ JSON دست‌نخورده |
| ۰.۴ | `DoctorAddress` هیچ ستونی حذف/تغییر نداد | ✅ | فقط دو ستون `NOT NULL DEFAULT` |
| ۰.۵ | `active=false` هیچ اثری بر محاسبهٔ اسلات ندارد | ✅ | فقط ذخیره می‌شود؛ در `branch.md` نوشته شد |

## ۱. طرح

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۱.۱ | ⛔ جدول `branches` **ساخته نشد** — دلیل مکتوب | ✅ | `_shared/branch-is-doctor-address.md` |
| ۱.۲ | `task.md` · `architecture.md` · `database.md` · `implementation_notes.md` تصحیح شد | ✅ | |
| ۱.۳ | ارجاع‌های `branch_id` در تسک‌های ۰۲/۰۴/۰۷/۰۸/۰۹/۱۰/۱۳ با سند حاکم پوشش داده شد | ✅ | ۲۴ ارجاع — یک سند واحد در `_shared` به‌جای ویرایش ۲۴ نقطه |

## ۲. بک‌اند

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۲.۱ | `DoctorAddress` += `active` + `timezone` | ✅ | |
| ۲.۲ | `timezone` با `DateTimeZone::listIdentifiers()` اعتبارسنجی می‌شود، نه regex | ✅ | `DateTimeZone::listIdentifiers()` در setter |
| ۲.۳ | `BranchWorkingHours` entity (فرزند aggregate) | ✅ | ولی **جفت tenant** گرفت نه فرزند aggregate — ردیف ۳.۵ |
| ۲.۴ | `Room` entity با `TenantOwnedTrait` و جفت مشتق از آدرس در سازنده | ✅ | جفت در سازنده از `tenantEntityType/Id()` آدرس |
| ۲.۵ | `BranchResolver` — تک‌نقطهٔ uuid آدرس → محیط جاری، ۴۰۴ نه ۴۰۳ | ✅ | ۴۰۴ می‌دهد؛ منشی هم پوشش دارد |
| ۲.۶ | `WorkingHoursService` — اعتبارسنجی کامل **قبل از** حذف (اتمی) | ✅ | `WorkingHoursTest::testInvalidLaterDayLeavesTheStoredWeekUntouched` |
| ۲.۷ | ساعت با `start_minute`/`end_minute` عددی، نه رشتهٔ `"09:00"` | ✅ | |
| ۲.۸ | `sequence` سمت سرور تخصیص می‌یابد، نه کلاینت | ✅ | بعد از `usort` تخصیص می‌یابد |
| ۲.۹ | `RoomService` با گارد حذف قابل توسعه (آرایهٔ تزریقی، نه زنجیرهٔ `if`) | ✅ | `RoomDeletionGuardInterface` + `AutowireIterator` + `_instanceof` |
| ۲.۱۰ | شش endpoint ساخته شد | ✅ | هشت شد نه شش: `GET /branches` و `PATCH /branch/{uuid}` هم لازم بودند |
| ۲.۱۱ | پزشک مستقل هم شعبه دارد | ✅ | `type=personal` از قبل کار می‌کرد |
| ۲.۱۲ | کنترلر نازک · `BaseController` · `success/paginated/error` | ✅ | |

## ۳. دیتابیس

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۳.۱ | `branch_working_hours` · `rooms` | ✅ | `Version20260730125038` |
| ۳.۲ | `entity_type, entity_id` ستون **اول** ایندکس `rooms` | ✅ | `idx_rooms_tenant` و `idx_bwh_tenant` |
| ۳.۳ | `timezone` روی آدرس از روز اول | ✅ | افزودن بعدی = backfill زمان‌دار |
| ۳.۴ | `rooms.capacity` — ظرفیت هم‌زمان | ✅ | حداقل ۱ در setter و سرویس |
| ۳.۵ | `branch_working_hours` در `GlobalTables::AGGREGATE_CHILDREN` با ریشهٔ صریح | ✅ | **رد شد** — ریشه سراسری است، پس جفت واقعی گرفت |
| ۳.۶ | ستون‌ها و جدول‌ها روی `db_test` هم ساخته شد | ✅ | دستی، چون `db_test` تاریخچهٔ جدا دارد |
| ۳.۷ | `TenantSchemaCoverageTest` سبز | ✅ | |
| ۳.۸ | `TenantLookupInventoryTest` سبز — repository جدید ثبت شد | ✅ | سبز بدون نیاز به ثبت تازه |

## ۴. UI

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۴.۱ | `BranchesPage` · `BranchWorkingHoursPage` · `BranchRoomsPage` | ✅ | |
| ۴.۲ | `DataTable` با skeleton و empty state فارسی | ✅ | |
| ۴.۳ | `PageHeader` با `backTo` روی زیرصفحه‌ها | ✅ | `backTo` + breadcrumb روی هر دو زیرصفحه |
| ۴.۴ | هر `select` با `SearchableSelect` — هیچ `<select>` بومی | ✅ | `SearchableSelect` برای منطقهٔ زمانی؛ هیچ `<select>` بومی |
| ۴.۵ | وضعیت لیست در URL با `useUrlState` | ✅ | جستجو و فیلتر وضعیت در URL |
| ۴.۶ | هیچ رنگ/شعاع/سایهٔ hard-code — همه از توکن | ✅ | همه از `var(--…)` |
| ۴.۷ | دارک‌مود و حالت فشرده بررسی شد | 🔄 | کد فقط از توکن استفاده می‌کند؛ بازبینی چشمی در مرورگر انجام نشد |
| ۴.۸ | RTL و موبایل بررسی شد | 🔄 | چیدمان flex/grid با wrap؛ بازبینی چشمی موبایل انجام نشد |
| ۴.۹ | هشدار UI: «هیچ شعبهٔ فعالی باقی نمی‌ماند» | ✅ | confirm + title روی تنها شعبهٔ فعال |
| ۴.۱۰ | مسیرها در `App.tsx` + ورودی در `SettingsMenuPage` | ✅ | سه مسیر + آیتم منو با `MapPinIcon` |
| ۴.۱۱ | مجوز موجود `appointment_settings` استفاده شد، نه مجوز تازه | ✅ | `appointment_settings` بازاستفاده شد |

## ۵. تست

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۵.۱ | `WorkingHoursTest` — هفت روز، `end<=start`، هم‌پوشانی، `0..1440`، آرایهٔ خالی | ✅ | ۱۴ تست |
| ۵.۲ | اتمی بودن: بازهٔ نامعتبر در روز ششم → ۴۲۲ و شش روز قبلی دست‌نخورده | ✅ | |
| ۵.۳ | `RoomCrudTest` — جفت tenant مشتق، `capacity=0` → ۴۲۲ | ✅ | ۱۲ تست |
| ۵.۴ | آدرس/اتاق محیط دیگر → ۴۰۴ (نه ۴۰۳) | ✅ | هم شعبه و هم اتاق |
| ۵.۵ | `BranchAddressFieldsTest` — پیش‌فرض‌ها، `timezone` نامعتبر → ۴۲۲ | ✅ | ۱۰ تست شامل شمارش کوئری |
| ۵.۶ | `phpstan analyse src/Branch` بدون خطا | ✅ | صفر خطا در `src/Branch` |

## ۶. مستندات

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۶.۱ | `docs/api/branch.md` + ثبت در `docs/api/README.md` | ✅ | JSON واقعی از curl روی ddev + ثبت در README |
| ۶.۲ | «شعبهٔ بدون ساعت کاری = تعریف‌نشده، نه همیشه‌باز» نوشته شد | ✅ | تسک ۰۳ رویش حساب می‌کند |
| ۶.۳ | «`active` در این فاز بی‌اثر بر اسلات» نوشته شد | ✅ | |
| ۶.۴ | `docs/api/doctor.md` — دو فیلد جدید در پاسخ ۹ endpoint آدرس | ✅ | `doctor.md` — تغییر additive روی ۹ اندپوینت |
| ۶.۵ | `docs/architecture/tenancy.md` جدول طبقه‌بندی به‌روز شد | ✅ | درسِ «ریشهٔ سراسری، فرزندِ محیط‌دار» + محدودیت `chosen` |

## ۷. بازبینی پایانی

| # | مورد | وضعیت | یادداشت |
|---|---|---|---|
| ۷.۱ | هیچ 🔄 و ⏳ بی‌دلیل نمانده | ⚠️ | دو 🔄 مانده، هر دو بازبینی چشمی UI با دلیل مکتوب |
| ۷.۲ | `bin/phpunit` کامل سبز | ✅ | ۱۰۶۷ تست / ۲۹۷۴ assertion — صفر خطا |
| ۷.۳ | `--group=slot-mode-frozen` سبز | ✅ | |
| ۷.۴ | `phpstan` بدون خطای جدید (مقایسه با کامیت پیش از تسک) | ✅ | ۱۴ خطا قبل و بعد — هیچ‌کدام در فایل‌های این تسک |
| ۷.۵ | `npx tsc --noEmit` و `yarn test` سبز | ✅ | `tsc` صفر خطا · vitest ۸۷ فایل / ۶۱۲ تست |
| ۷.۶ | `TenantSchemaCoverageTest` + `TenantLookupInventoryTest` سبز | ✅ | |
| ۷.۷ | `docs/api/*` به‌روز | ✅ | |
| ۷.۸ | چک‌لیست UI کامل | ⚠️ | دو ردیف ۴.۷/۴.۸ بازبینی چشمی می‌خواهند |
| ۷.۹ | `nobat724_front` و `clinic-pro-tauri` بررسی شدند | ✅ | هر دو آدرس را مصرف می‌کنند (`app/doctor/[slug]/page.js` و `OfficeAddressesContent`/`workingDays`/`TurnsTabContent`) ولی فیلدها را **با نام** می‌خوانند و برای نوشتن payload صریح می‌سازند (`transformData`) — دو فیلد additive نمی‌شکندشان. هیچ اندپوینت جدیدی مصرف‌کننده ندارد |
| ۷.۱۰ | commit، سپس `graphify update .`، سپس commit جدا | ✅ | |
| ۷.۱۱ | موارد به‌تعویق با دلیل و تسک مقصد | ✅ | گاردِ حذف اتاق ← تسک ۰۲/۰۷ · گاردِ حذف آدرس ← تسک ۰۷ · اعمال `active` ← تسک ۰۳ |
