From 1972fdd20f77b8436808aa6426281888df72167e Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Sat, 1 Aug 2026 23:05:33 +0330 Subject: [PATCH] Document the resource-first model and retire the deleted tasks' checklists MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docs/architecture/resource-first-model.md describes the shape: the three entities, why an option is a ServiceItem rather than a fourth table, the four-level resolution chain, the two conditions on the eligibility filter and what each of them prevented, and why containment is a graph beside the display tree rather than the tree itself. docs/api/resource.md gains both offering endpoints with the response captured from a real call, including a row where the price comes from the branch and one where it comes from the resource — the two cases the *_source fields exist for. docs/api/appointment.md documents resource_uuid, the doctor inference, and the nullable resource/service_option in the response. The checklists for tasks 9 to 14 keep their rows but open with a banner saying the task was removed, when, by whose decision, and which commit to revert. They are history now; deleting them would erase the record of work that shipped and was then withdrawn. Verified end to end: 1304 tests, slot-mode-frozen green, phpstan at 14, tsc clean, 648 panel tests, and app:seed-scenarios --reset builds all three environments. Co-Authored-By: Claude Opus 5 --- TEST_USERS.md | 15 ++- docs/api/appointment.md | 8 ++ docs/api/resource.md | 72 +++++++++++ docs/architecture/resource-first-model.md | 122 ++++++++++++++++++ .../taskes/task-09-policy-engine/checklist.md | 13 ++ .../task-10-policy-admin-sandbox/checklist.md | 13 ++ .../checklist.md | 13 ++ .../task-12-treatment-course/checklist.md | 13 ++ .../checklist.md | 13 ++ .../task-14-events-utilization/checklist.md | 13 ++ .../task-15-resource-first-model/checklist.md | 24 ++-- 11 files changed, 300 insertions(+), 19 deletions(-) create mode 100644 docs/architecture/resource-first-model.md diff --git a/TEST_USERS.md b/TEST_USERS.md index a755355b..b248089b 100644 --- a/TEST_USERS.md +++ b/TEST_USERS.md @@ -95,17 +95,18 @@ POST /api/v1/auth/switch-context {"db_uuid": ""} | ۰۵ برنامهٔ چندبخشی | سرویس اصلی هر محیط سه بخش دارد: بی‌حسی ۵د (اتاق انحصاری) → انتظار ۳۰د (اتاق **passive**) → لیزر ۲۰د (اتاق + دستگاه) | `GET /api/v1/service-item/{uuid}/segments` | | ۰۶ موتور دسترس‌پذیری | همان برنامه با منابع واقعی جستجو می‌شود | `POST /api/v1/appointment-availability` | | ۰۷ نگه‌داشتن و ثبت | **۲ نوبت در هر محیط از مسیر واقعی** hold → confirm، با بخش و اشغال منبع | `GET /api/v1/appointment/{uuid}/segments` | +| **منبع↔سرویس** | رابطهٔ چند‌به‌چند با مدت و قیمت اختصاصی: دو دستگاه یک سرویس را با اعداد متفاوت می‌دهند | `GET /api/v1/resource/{uuid}/services` | +| **دستهٔ مشترک** | دسته روی سرویس و منبع؛ یال «شامل بودن» بین دسته‌ها | مودال «سرویس‌ها» در صفحهٔ منابع | | ۰۸ عکس قیمت | لیست قیمت فعال + `PriceSnapshot` روی نوبت‌های واقعی با بیعانه | `GET /api/v1/price-lists` | -| ۰۹ موتور سیاست | **۶ سیاست، یکی از هر دسته** (انتخاب، صلاحیت، منبع، زمان، فاصله، قیمت) | `GET /api/v1/policies` | -| ۱۱ پکیج و دفتر اعتبار | پکیج ۶ جلسه‌ای + ۲ پکیج خریداری‌شده + ردیف مصرف در دفتر | `GET /api/v1/packages` | -| ۱۲ دورهٔ درمان | پروتکل ۶ جلسه‌ای با پارامتر انرژی هر جلسه + دورهٔ فعال با ۶ جلسه | `GET /api/v1/treatment-course/{uuid}` | -| ۱۳ لغو و لیست انتظار | سیاست عمومی + سیاست سخت‌گیرانه روی یک سرویس، رکورد عدم حضور، ۲ نفر در لیست انتظار | `GET /api/v1/waitlist` · `/cancellation-policy` | -| ۱۴ رویداد و بهره‌وری | `HoldCreated` و `AppointmentBooked` در outbox + دقیقهٔ اشغال واقعی هر منبع | `GET /api/v1/reports/resource-utilization?branch_uuid=…` | + +> **تسک‌های ۹ تا ۱۴ (سیاست، پکیج، دوره، لغو/انتظار، رویداد و گزارش) به تصمیم مالک محصول +> از محصول حذف شده‌اند.** مدل فعلی فقط منبع، سرویس و گزینه است — +> [`docs/architecture/resource-first-model.md`](docs/architecture/resource-first-model.md). نوبت‌های موتور جدید **از `new Appointment(...)` ساخته نمی‌شوند**؛ از `AppointmentPlanBuilder` → `AvailabilityEngine` → `HoldService` → `BookingService` رد -می‌شوند. برای همین اشغال منبع و رویداد دامنه واقعی‌اند: گزارش بهره‌وری عدد نشان می‌دهد و -تقویم دستگاه واقعاً پر است. +می‌شوند. برای همین اشغال منبع واقعی است و تقویم دستگاه واقعاً پر است — نه ردیف‌هایی که +با INSERT ساخته شده‌اند و هیچ‌وقت از موتور رد نشده‌اند. ## چه چیزی با این داده قابل تست است diff --git a/docs/api/appointment.md b/docs/api/appointment.md index 2d6df05d..22492f5f 100644 --- a/docs/api/appointment.md +++ b/docs/api/appointment.md @@ -250,6 +250,7 @@ Book an appointment slot. | `slot_start` | integer | ✅ | Slot start (Unix timestamp) | | `slot_end` | integer | ⚠️ | Slot end (Unix timestamp). **با `service_item_uuids` نادیده گرفته می‌شود** و سرور خودش حساب می‌کند (به مقدار کلاینت اعتماد نمی‌شود)؛ در آن حالت الزامی هم نیست. بدون سرویس، مقدار کلاینت حفظ می‌شود و الزامی است | | `service_item_uuids` | string[] | ❌ | یک یا چند UUID سرویس. سرویس‌ها **ذخیره** می‌شوند (`service_items`)، اولین سرویس سرویسِ اصلی (`service_item`) است، و مدت/بافر روی نوبت ثبت می‌شود (`service_total_minutes` / `service_buffer_minutes`). UUID ناموجود، سرویسِ غیرbookable، سرویس بدون مدت، یا سرویسِ محیطی دیگر ⇒ `422` | +| `resource_uuid` | string (UUID) | ⚠️ | منبعی که نوبت **برایش** گرفته می‌شود (دستگاه، اتاق، یا خودِ پزشک). اگر داده شود `doctor_uuid` اختیاری است و برای منبعِ پزشک از خودش استنتاج می‌شود؛ محل نوبت هم از شعبهٔ همان منبع می‌آید. منبع باید در همان محیط رزرو باشد و اگر سرویس انتخاب‌شده را ارائه ندهد ⇒ `422` | | `for_self` | boolean | ❌ | `true` (default) = patient is the logged-in payer; `false` = booking for someone else | | `patient_name` | string | ⚠️ | Required when `for_self=false`; otherwise filled from the payer's profile | | `patient_mobile` | string | ⚠️ | Required when `for_self=false`; otherwise the payer's mobile | @@ -259,6 +260,13 @@ Book an appointment slot. | `note` | string | ❌ | Patient note | | `city_id` | integer | ❌ | شناسه‌ی شهرِ دامنه‌ی جاری (از `city.json` سایت). برای گاردِ پورسانت نماینده: اگر شهر نماینده‌ی فعال داشته باشد، `booking_representation_id` نوبت ست می‌شود. پورسانت فقط وقتی واریز می‌شود که این نماینده با نماینده‌ی پزشک یکی باشد. خالی/ناموجود ⇒ بدون پورسانت | +> **`doctor_uuid` یا `resource_uuid`:** دست‌کم یکی الزامی است؛ نبودِ هر دو ⇒ `422`. مسیر +> قدیمیِ فقط-`doctor_uuid` دست‌نخورده است و سایت عمومی همان را می‌فرستد. +> +> **پاسخ:** علاوه بر فیلدهای قبلی، `resource` (`uuid`, `name`, `type`) و `service_option` +> (`uuid`, `name`) برمی‌گردند. نوبت‌های پیش از مدل منبع‌محور هر دو را `null` دارند، پس +> کلاینت باید با `null` کنار بیاید. +> > **مدت در حالت سرویسی:** مدت از `ServiceBookingCalculator` می‌آید — همان مؤلفه‌ای که > `GET /api/v1/appointment-service-slots` هم با آن اسلات‌ها را می‌سازد. یعنی `solo` و > `additional` سرویس‌ها لحاظ می‌شوند و نه جمعِ سادهٔ `duration_minutes`؛ وگرنه نوبتِ ثبت‌شده diff --git a/docs/api/resource.md b/docs/api/resource.md index ec22bc45..e9a44c3f 100644 --- a/docs/api/resource.md +++ b/docs/api/resource.md @@ -237,6 +237,78 @@ `PATCH` همان فیلدهاست؛ `address_uuid` پذیرفته **نمی‌شود** (جفت محیط از آدرس مشتق شده و write-once است) و `type_uuid` قابل تغییر است. +### `GET /api/v1/resource/{uuid}/services` + +سرویس‌هایی که این منبع ارائه می‌دهد، با **مقدار مؤثر** و اینکه هر عدد از کدام سطح آمده. + +`duration_minutes`/`price_rials` مقدارِ ثبت‌شده روی همین رابطه‌اند و `null` یعنی «ارث از +سطح بالاتر»، نه صفر. `effective_*` نتیجهٔ زنجیرهٔ حل است و `*_source` می‌گوید کدام سطح +برنده شده — بدون آن، پنل نمی‌تواند کنار خانهٔ خالی بنویسد عدد از کجا می‌آید. + +زنجیره از خاص به عام: `resource_option` → `resource_service` → `branch` → `service_default`. + +خروجی واقعی (۲۰۰): + +```json +[ + { + "service_uuid": "f49baba9-68e9-4d61-aa90-fc8c784607e0", + "service_name": "لیزر CO2", + "duration_minutes": null, + "price_rials": null, + "active": true, + "effective_duration_minutes": 40, + "effective_price_rials": 18000000, + "duration_source": "service_default", + "price_source": "branch" + }, + { + "service_uuid": "7f13ab0d-2f64-4e8c-8e12-154172b6620a", + "service_name": "ویزیت عمومی", + "duration_minutes": null, + "price_rials": 1200000, + "active": true, + "effective_duration_minutes": 15, + "effective_price_rials": 1200000, + "duration_source": "service_default", + "price_source": "resource_option" + } +] +``` + +**دسترسی:** `appointment_settings.view`. **۴۰۴:** منبع محیط دیگر. + +### `PUT /api/v1/resource/{uuid}/services` + +جایگزینی **کامل**، مثل مهارت‌ها: سرویسی که در بدنه نیست از این منبع برداشته می‌شود و +`{"services":[]}` همه را پاک می‌کند. + +```json +{ + "services": [ + { "service_uuid": "f49baba9-…", "duration_minutes": 15, "price_rials": 9500000, "active": true }, + { "service_uuid": "7f13ab0d-…", "duration_minutes": "", "price_rials": null } + ] +} +``` + +| فیلد | نوع | الزامی | توضیح | +|---|---|---|---| +| `service_uuid` | string (UUID) | ✅ | سرویس یا گزینهٔ سرویس؛ هر دو `ServiceItem` اند | +| `duration_minutes` | int \| null \| `""` | ❌ | مدت اختصاصی این منبع. `null` و رشتهٔ خالی یعنی **ارث**، نه صفر. مقدار ≤ ۰ ⇒ `422` | +| `price_rials` | int \| null \| `""` | ❌ | همان قاعده؛ منفی ⇒ `422`. صفرِ صریح یعنی رایگان و ارث نمی‌گیرد | +| `active` | boolean | ❌ | پیش‌فرض `true`. غیرفعال یعنی «فعلاً این را نمی‌دهد» ولی اعداد ذخیره‌شده می‌مانند | + +پاسخ ۲۰۰ همان فهرست `GET` است (با مقادیر تازه حل‌شده). + +**۴۲۲:** `services` غایب یا غیرآرایه · `service_uuid` غایب یا ناموجود · سرویسِ محیط دیگر +(«سرویس انتخاب‌شده به این محل نوبت‌دهی تعلق ندارد») · مدت یا قیمت نامعتبر. + +> **این رابطه روی انتخاب منبع اثر می‌گذارد.** وقتی برای یک سرویس دست‌کم یک ردیف ثبت شده +> باشد، `appointment-availability` فقط منابعی از **همان نوع** را کاندید می‌کند که ردیف +> فعال دارند. تا وقتی هیچ ردیفی نیست، هیچ فیلتری اعمال نمی‌شود — محیطی که هنوز +> رابطه‌ها را پر نکرده نباید یک‌شبه بی‌وقت شود. + ### `PUT /api/v1/resource/{uuid}/skills` جایگزینی **کامل**: مهارتی که در بدنه نیست، برداشته می‌شود. `{"skills":[]}` همه را diff --git a/docs/architecture/resource-first-model.md b/docs/architecture/resource-first-model.md new file mode 100644 index 00000000..b130b0e8 --- /dev/null +++ b/docs/architecture/resource-first-model.md @@ -0,0 +1,122 @@ +# مدل منبع‌محور: منبع، سرویس، گزینه + +سیستم نوبت‌دهی روی **منبع** ساخته شده، نه روی پزشک. منبع هر چیزی است که زمانش رزرو +می‌شود: پزشک، دستگاه لیزر، یونیت دندانپزشکی، اتاق عمل، مربی. همین باعث می‌شود از مطب یک +پزشک تا مرکز لیزر و درمانگاه، همه با یک مدل داده کار کنند. + +## سه موجودیت + +| مفهوم | کجاست | نکته | +|---|---|---| +| **منبع** | `ClinicResource` | تقویم، استثنا، مهارت، ظرفیت و اشغال دارد. پزشک/پرسنل/اتاق با `ResourceLinker` به منبع وصل می‌شوند | +| **سرویس** | `ServiceItem` | مدت (solo/additional)، قیمت، دستهٔ کاتالوگ | +| **گزینهٔ سرویس** | باز هم `ServiceItem` | عضو یک `ItemGroup` با بازهٔ انتخاب (`select_min`/`select_max`) | + +**چرا گزینه جدول جدا ندارد:** «لیزر» و «لیزر پا» هر دو یک چیزند — چیزی که قیمت و مدت +دارد و می‌شود رزروش کرد. جدول سوم یعنی `PriceListItem`، `Tariff`، +`appointment_service_items`، `SegmentTemplate` و کل مسیر `appointment-service-slots` +باید دو نوع ورودی بشناسند؛ یعنی دو منبع حقیقت برای یک مفهوم. + +## رابطهٔ منبع↔سرویس + +`ResourceServiceOffering` — چند‌به‌چند با تنظیمات اختصاصی: + +``` +resource_service_offerings(resource_id, service_item_id, duration_minutes, price_rials, active) +``` + +- ردیف با **آیتم والد** = «منبع + سرویس»؛ ردیف با **آیتم عضو گروه** = «منبع + گزینه». + یک جدول، هر دو سطحِ سند. +- `null` یعنی «ارث از سطح بالاتر»، **نه صفر**. صفرِ صریح یک مقدار واقعی است (سرویس رایگان). +- `active = false` یعنی «فعلاً این منبع این را نمی‌دهد» — ردیف می‌ماند تا تنظیماتش با + خاموش/روشن کردن از دست نرود. +- فرزند aggregate منبع است: ستون محیط ندارد چون منبع خودش دارد، و سازنده اجبار می‌کند + منبع و سرویس در یک محیط باشند. + +## زنجیرهٔ حل مدت و قیمت + +`ResourceServiceResolver` — از خاص به عام: + +``` +۱. منبع + گزینه → ResourceServiceOffering(resource, option) source: resource_option +۲. منبع + سرویس → ResourceServiceOffering(resource, parent) source: resource_service +۳. شعبه + آیتم → ServiceBranchOverride(item, address) source: branch +۴. پیش‌فرض آیتم → ServiceItem source: service_default +``` + +دو قاعده که سکوت‌شان باگ می‌سازد: + +- **مدت و قیمت جدا حل می‌شوند.** منبعی که فقط مدتش فرق دارد نباید قیمتش هم از همان سطح + بیاید، وگرنه اولین override تعرفهٔ شعبه را بی‌صدا می‌بلعد. +- **منبعِ هر مقدار برگردانده می‌شود** (`durationSource` / `priceSource`). بدون آن، پنل + نمی‌تواند کنار عدد بنویسد «از شعبه»، و «چرا این عدد؟» می‌شود جست‌وجو در چهار جدول. + +## انتخاب منبع + +`ClinicResourceRepository::findEligible($address, $type, $skillIds, $service)`: + +1. شعبه + نوع + فعال +2. مهارت‌های لازم (همه، نه یکی) +3. **رابطهٔ سرویس** — فقط اگر برای آن سرویس و **همان نوع منبع** ردیفی ثبت شده باشد +4. ترتیب: منابعی که دستهٔ سرویس را پوشش می‌دهند اول + +بند ۳ دو قید دارد که هر کدام یک شکست واقعی را جلو گرفته‌اند: + +- **مشروط بودن:** محیطی که هنوز رابطه‌ها را پر نکرده باید مثل قبل کار کند، وگرنه با + اولین deploy بی‌وقت می‌شود. +- **محدود به نوع:** «کدام منبع این سرویس را می‌دهد» دربارهٔ نقشِ انجام‌دهنده است. بدون این + قید، ثبت رابطه برای دستگاه‌ها باعث می‌شد اتاقِ همان برنامه واجد شرایط نباشد و کل رزرو + بشکند. + +## دسته‌بندی + +دسته سراسریِ محیط است و **هم سرویس‌ها هم منابع** از آن استفاده می‌کنند +(`ServiceItem::$catalogCategory` و `resource_catalog_categories`). + +دو رابطهٔ متفاوت که نباید قاطی شوند: + +| رابطه | جدول | معنا | +|---|---|---| +| سلسله‌مراتب نمایشی | `CatalogCategory::$parent` | چیدمان منو؛ درخت، تک‌والدی، `MAX_DEPTH = 4` | +| **شامل بودن** | `catalog_category_includes` | «تمام بدن شامل دست است»؛ گراف جهت‌دار بدون دور | + +درخت برای «شامل بودن» کافی نیست: «دست» باید هم‌زمان زیر «تمام بدن» و «اندام فوقانی» +باشد و درخت تک‌والدی این را نمی‌تواند بگوید. + +`CategoryClosureResolver` بستار گذرا را حساب می‌کند (تمام بدن → نیم‌تنه → پا ⇒ تمام بدن +شامل پا). همهٔ یال‌های محیط با یک کوئری خوانده و در حافظه پیمایش می‌شوند؛ مجموعهٔ +بازدیدشده هم‌زمان نتیجه و محافظ دور است، و `assertNoCycle` ساختِ حلقه را رد می‌کند. + +**تعارض انتخاب:** انتخاب هم‌زمان دو آیتم که دستهٔ یکی دیگری را در بر می‌گیرد ⇒ `422` با +کد `category_overlap`. این جای رابطهٔ دستی `incompatible_with` را برای حالت ناحیه‌ای +می‌گیرد — یک بار روی دسته، نه به‌ازای هر جفت آیتم. آن رابطه برای ناسازگاری‌هایی که ربطی +به ناحیه ندارند سرِ جایش می‌ماند. + +## نوبت + +نوبت هم منبع را نگه می‌دارد هم گزینه را، و عددهایش را snapshot می‌کند: + +| ستون | چرا | +|---|---| +| `resource_id` | نوبت **برای** کدام منبع است. تکرار `resource_occupancy` نیست: آن می‌گوید چه چیزی و کِی اشغال شد (شامل اتاقِ یک بخش)، این می‌گوید بیمار چه چیزی را انتخاب کرد | +| `service_option_item_id` | بدون دانستن گزینه، بازتولید عددِ ذخیره‌شده ممکن نیست | +| `service_total_minutes` | از خروجی resolver، نه از `ServiceItem` | +| `PriceSnapshot` | قیمتِ لحظهٔ رزرو؛ تغییر فردای تعرفه صورتحساب دیروز را تکان نمی‌دهد | + +هر دو ستون تهی‌پذیرند: نوبت‌های پیش از این مدل منبع ندارند و migration نباید بشکندشان. + +## رزرو + +`POST /api/v1/appointment` هم `doctor_uuid` می‌پذیرد هم `resource_uuid`: + +- با منبعِ پزشک، پزشک از خودِ منبع استنتاج می‌شود. +- محل نوبت از **شعبهٔ منبع** می‌آید؛ فرستادن جداگانهٔ `clinic_uuid` فقط راهی برای ناسازگار + کردن این دو بود. +- منبع باید در همان محیط رزرو باشد. uuid از بدنهٔ درخواست می‌آید و `TenantFilter` پوششش + نمی‌دهد، پس بدون این بررسی بیمار می‌توانست دستگاه کلینیک دیگری را روی نوبت این کلینیک + بنشاند. +- منبعی که سرویس انتخاب‌شده را ارائه نمی‌دهد همان‌جا رد می‌شود، نه وقتی بیمار سرِ قرار + حاضر شده. + +جزئیات قرارداد: [`docs/api/appointment.md`](../api/appointment.md) و +[`docs/api/resource.md`](../api/resource.md). diff --git a/docs/new_feture/taskes/task-09-policy-engine/checklist.md b/docs/new_feture/taskes/task-09-policy-engine/checklist.md index 494271f8..389cfd62 100644 --- a/docs/new_feture/taskes/task-09-policy-engine/checklist.md +++ b/docs/new_feture/taskes/task-09-policy-engine/checklist.md @@ -1,5 +1,18 @@ # چک‌لیست — تسک ۰۹ (موتور قوانین شش‌دسته‌ای) +> # ⛔ این تسک از محصول حذف شد +> +> **تصمیم مالک محصول، ۱۴۰۵/۰۵/۱۰:** مدل نوبت‌دهی به منبع/سرویس/گزینه محدود شد و هر چیز +> خارج از آن حذف شد. کد، جدول‌ها، endpointها، تست‌ها و صفحات پنل این تسک در کامیت +> «Remove the policy, package, course, cancellation and event subsystems» برداشته شدند. +> +> ریسکش پیش از اجرا دو بار مطرح و دو بار تأیید شد. ردیف‌های زیر **تاریخچه**اند، نه کار +> جاری؛ برای برگرداندن به همان کامیت رجوع کنید. +> +> مدل جایگزین: [`docs/architecture/resource-first-model.md`](../../../architecture/resource-first-model.md) +> و چک‌لیست [تسک ۱۵](../task-15-resource-first-model/checklist.md). + + **وضعیت کلی:** ✅ تمام‌شده با انحراف‌های ثبت‌شده · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹ قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) · diff --git a/docs/new_feture/taskes/task-10-policy-admin-sandbox/checklist.md b/docs/new_feture/taskes/task-10-policy-admin-sandbox/checklist.md index 012aba57..6f5bc16d 100644 --- a/docs/new_feture/taskes/task-10-policy-admin-sandbox/checklist.md +++ b/docs/new_feture/taskes/task-10-policy-admin-sandbox/checklist.md @@ -1,5 +1,18 @@ # چک‌لیست — تسک ۱۰ (فرم ساخت قانون و محیط آزمایش) +> # ⛔ این تسک از محصول حذف شد +> +> **تصمیم مالک محصول، ۱۴۰۵/۰۵/۱۰:** مدل نوبت‌دهی به منبع/سرویس/گزینه محدود شد و هر چیز +> خارج از آن حذف شد. کد، جدول‌ها، endpointها، تست‌ها و صفحات پنل این تسک در کامیت +> «Remove the policy, package, course, cancellation and event subsystems» برداشته شدند. +> +> ریسکش پیش از اجرا دو بار مطرح و دو بار تأیید شد. ردیف‌های زیر **تاریخچه**اند، نه کار +> جاری؛ برای برگرداندن به همان کامیت رجوع کنید. +> +> مدل جایگزین: [`docs/architecture/resource-first-model.md`](../../../architecture/resource-first-model.md) +> و چک‌لیست [تسک ۱۵](../task-15-resource-first-model/checklist.md). + + **وضعیت کلی:** ✅ تمام‌شده با انحراف‌های ثبت‌شده · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹ قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) · diff --git a/docs/new_feture/taskes/task-11-package-credit-ledger/checklist.md b/docs/new_feture/taskes/task-11-package-credit-ledger/checklist.md index 99b087a4..e93fa913 100644 --- a/docs/new_feture/taskes/task-11-package-credit-ledger/checklist.md +++ b/docs/new_feture/taskes/task-11-package-credit-ledger/checklist.md @@ -1,5 +1,18 @@ # چک‌لیست — تسک ۱۱ (پکیج و دفتر اعتبار جلسات) +> # ⛔ این تسک از محصول حذف شد +> +> **تصمیم مالک محصول، ۱۴۰۵/۰۵/۱۰:** مدل نوبت‌دهی به منبع/سرویس/گزینه محدود شد و هر چیز +> خارج از آن حذف شد. کد، جدول‌ها، endpointها، تست‌ها و صفحات پنل این تسک در کامیت +> «Remove the policy, package, course, cancellation and event subsystems» برداشته شدند. +> +> ریسکش پیش از اجرا دو بار مطرح و دو بار تأیید شد. ردیف‌های زیر **تاریخچه**اند، نه کار +> جاری؛ برای برگرداندن به همان کامیت رجوع کنید. +> +> مدل جایگزین: [`docs/architecture/resource-first-model.md`](../../../architecture/resource-first-model.md) +> و چک‌لیست [تسک ۱۵](../task-15-resource-first-model/checklist.md). + + **وضعیت کلی:** ✅ تمام‌شده با انحراف‌های ثبت‌شده · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹ قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) · diff --git a/docs/new_feture/taskes/task-12-treatment-course/checklist.md b/docs/new_feture/taskes/task-12-treatment-course/checklist.md index c76792db..4df2c7cb 100644 --- a/docs/new_feture/taskes/task-12-treatment-course/checklist.md +++ b/docs/new_feture/taskes/task-12-treatment-course/checklist.md @@ -1,5 +1,18 @@ # چک‌لیست — تسک ۱۲ (دوره درمان) +> # ⛔ این تسک از محصول حذف شد +> +> **تصمیم مالک محصول، ۱۴۰۵/۰۵/۱۰:** مدل نوبت‌دهی به منبع/سرویس/گزینه محدود شد و هر چیز +> خارج از آن حذف شد. کد، جدول‌ها، endpointها، تست‌ها و صفحات پنل این تسک در کامیت +> «Remove the policy, package, course, cancellation and event subsystems» برداشته شدند. +> +> ریسکش پیش از اجرا دو بار مطرح و دو بار تأیید شد. ردیف‌های زیر **تاریخچه**اند، نه کار +> جاری؛ برای برگرداندن به همان کامیت رجوع کنید. +> +> مدل جایگزین: [`docs/architecture/resource-first-model.md`](../../../architecture/resource-first-model.md) +> و چک‌لیست [تسک ۱۵](../task-15-resource-first-model/checklist.md). + + **وضعیت کلی:** ✅ تمام‌شده با انحراف‌های ثبت‌شده · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹ قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) · diff --git a/docs/new_feture/taskes/task-13-cancellation-waitlist/checklist.md b/docs/new_feture/taskes/task-13-cancellation-waitlist/checklist.md index d4de1f5f..76d41dd1 100644 --- a/docs/new_feture/taskes/task-13-cancellation-waitlist/checklist.md +++ b/docs/new_feture/taskes/task-13-cancellation-waitlist/checklist.md @@ -1,5 +1,18 @@ # چک‌لیست — تسک ۱۳ (سیاست لغو، عدم حضور، لیست انتظار) +> # ⛔ این تسک از محصول حذف شد +> +> **تصمیم مالک محصول، ۱۴۰۵/۰۵/۱۰:** مدل نوبت‌دهی به منبع/سرویس/گزینه محدود شد و هر چیز +> خارج از آن حذف شد. کد، جدول‌ها، endpointها، تست‌ها و صفحات پنل این تسک در کامیت +> «Remove the policy, package, course, cancellation and event subsystems» برداشته شدند. +> +> ریسکش پیش از اجرا دو بار مطرح و دو بار تأیید شد. ردیف‌های زیر **تاریخچه**اند، نه کار +> جاری؛ برای برگرداندن به همان کامیت رجوع کنید. +> +> مدل جایگزین: [`docs/architecture/resource-first-model.md`](../../../architecture/resource-first-model.md) +> و چک‌لیست [تسک ۱۵](../task-15-resource-first-model/checklist.md). + + **وضعیت کلی:** ✅ تمام‌شده با انحراف‌های ثبت‌شده · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹ قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) · diff --git a/docs/new_feture/taskes/task-14-events-utilization/checklist.md b/docs/new_feture/taskes/task-14-events-utilization/checklist.md index 966e6906..49b3b8d0 100644 --- a/docs/new_feture/taskes/task-14-events-utilization/checklist.md +++ b/docs/new_feture/taskes/task-14-events-utilization/checklist.md @@ -1,5 +1,18 @@ # چک‌لیست — تسک ۱۴ (رویدادهای دامنه و گزارش بهره‌وری) +> # ⛔ این تسک از محصول حذف شد +> +> **تصمیم مالک محصول، ۱۴۰۵/۰۵/۱۰:** مدل نوبت‌دهی به منبع/سرویس/گزینه محدود شد و هر چیز +> خارج از آن حذف شد. کد، جدول‌ها، endpointها، تست‌ها و صفحات پنل این تسک در کامیت +> «Remove the policy, package, course, cancellation and event subsystems» برداشته شدند. +> +> ریسکش پیش از اجرا دو بار مطرح و دو بار تأیید شد. ردیف‌های زیر **تاریخچه**اند، نه کار +> جاری؛ برای برگرداندن به همان کامیت رجوع کنید. +> +> مدل جایگزین: [`docs/architecture/resource-first-model.md`](../../../architecture/resource-first-model.md) +> و چک‌لیست [تسک ۱۵](../task-15-resource-first-model/checklist.md). + + **وضعیت کلی:** ✅ تمام‌شده با انحراف‌های ثبت‌شده · **آخرین بازبینی:** ۱۴۰۵/۰۵/۰۹ قواعد: [_shared/definition-of-done.md](../_shared/definition-of-done.md) · diff --git a/docs/new_feture/taskes/task-15-resource-first-model/checklist.md b/docs/new_feture/taskes/task-15-resource-first-model/checklist.md index 53d5af74..51f936c5 100644 --- a/docs/new_feture/taskes/task-15-resource-first-model/checklist.md +++ b/docs/new_feture/taskes/task-15-resource-first-model/checklist.md @@ -135,21 +135,21 @@ | # | مورد | وضعیت | یادداشت | |---|---|---|---| -| ۹.۱ | `docs/api/appointment.md` — `resource_uuid` و پاسخ جدید | ⏳ | | -| ۹.۲ | `docs/api/appointment.md` — بخش‌های حذف‌شده پاک شد | ⏳ | | -| ۹.۳ | `docs/api/clinic.md` — endpoint سرویس‌های منبع | ⏳ | | -| ۹.۴ | سند معماری مدل منبع‌محور | ⏳ | | -| ۹.۵ | چک‌لیست تسک‌های ۹ تا ۱۴ با وضعیت «حذف‌شده» | ⏳ | | -| ۹.۶ | `TEST_USERS.md` به‌روز شد | ⏳ | | +| ۹.۱ | `docs/api/appointment.md` — `resource_uuid` و پاسخ جدید | ✅ | `resource_uuid` در جدول فیلدها + پاسخ `resource`/`service_option` | +| ۹.۲ | `docs/api/appointment.md` — بخش‌های حذف‌شده پاک شد | ✅ | `docs/api/appointment.md` هیچ ارجاعی به دامنه‌های حذف‌شده نداشت — بررسی شد | +| ۹.۳ | `docs/api/clinic.md` — endpoint سرویس‌های منبع | ✅ | `docs/api/resource.md` — `GET/PUT resource/{uuid}/services` با JSON واقعی از اجرای واقعی | +| ۹.۴ | سند معماری مدل منبع‌محور | ✅ | `docs/architecture/resource-first-model.md` | +| ۹.۵ | چک‌لیست تسک‌های ۹ تا ۱۴ با وضعیت «حذف‌شده» | ✅ | بنر ⛔ روی چک‌لیست تسک‌های ۹ تا ۱۴ با تاریخ و کامیت مرجع | +| ۹.۶ | `TEST_USERS.md` به‌روز شد | ✅ | جدول موتور نوبت‌دهی به‌روز شد؛ ردیف‌های حذف‌شده رفتند و منبع↔سرویس و دستهٔ مشترک آمدند | ## ۱۰. تأیید نهایی | # | مورد | وضعیت | یادداشت | |---|---|---|---| -| ۱۰.۱ | `ddev exec php bin/phpunit` کامل سبز | ⏳ | | -| ۱۰.۲ | `--group=slot-mode-frozen` سبز | ⏳ | خط قرمز | -| ۱۰.۳ | `phpstan` روی baseline ۱۴ خطا | ⏳ | | -| ۱۰.۴ | `npx tsc --noEmit` بدون خطا | ⏳ | | -| ۱۰.۵ | `npx vitest run assets/admin` سبز | ⏳ | | -| ۱۰.۶ | `app:seed-scenarios --reset -n` بدون خطا | ⏳ | | +| ۱۰.۱ | `ddev exec php bin/phpunit` کامل سبز | ✅ | `1304 tests, 3776 assertions` سبز | +| ۱۰.۲ | `--group=slot-mode-frozen` سبز | ✅ | `OK (3 tests, 8 assertions)` — خط قرمز دست‌نخورده | +| ۱۰.۳ | `phpstan` روی baseline ۱۴ خطا | ✅ | ۱۴ خطا، همان baseline | +| ۱۰.۴ | `npx tsc --noEmit` بدون خطا | ✅ | بدون خطا | +| ۱۰.۵ | `npx vitest run assets/admin` سبز | ✅ | ۶۴۸ تست در ۹۸ فایل سبز | +| ۱۰.۶ | `app:seed-scenarios --reset -n` بدون خطا | ✅ | `--reset -n` بدون خطا؛ سیدر حالا رابطهٔ منبع↔سرویس هم می‌سازد | | ۱۰.۷ | کامیت + `graphify update` + کامیت گراف | ⏳ | |