Files
clinicpro/docs/new_feture/taskes/task-14-events-utilization/checklist.md
T
hamedandClaude Opus 5 635bf3d2a8 fix(admin): correct two design-system mismatches found by looking at the pages
Screenshotting the pages under dark mode and compact density (rather than
trusting that design tokens were enough) turned up two mistakes repeated across
every page this feature set added:

- `.card` carries only the surface, border and radius — padding comes from the
  separate `.card-pad`. Fifteen cards were rendering with their content flush
  against the edges.
- `.field` *is* the input box, a 40px-tall flex row. Wrapping a label plus a
  control in it produced a joined addon rather than a label above its field.
  `.field-block` is the label-above layout, and thirty-seven wrappers now use it.

Both were invisible to type-checking and to the tests, which is exactly why the
visual pass was worth running. Numbers in the new UI now go through
formatNumber so they render as Persian digits, and the utilization page's
header no longer repeats the sentence that appears under its filters verbatim.

The QA driver gained a `--ui` flag: theme and density live in
localStorage['clinicpro-ui'], so without seeding them dark mode and compact
density cannot be screenshotted at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 21:42:11 +03:30

9.5 KiB
Raw Blame History

چک‌لیست — تسک ۱۴ (رویدادهای دامنه و گزارش بهره‌وری)

وضعیت کلی: تمام‌شده با انحراف‌های ثبت‌شده · آخرین بازبینی: ۱۴۰۵/۰۵/۰۹

قواعد: _shared/definition-of-done.md · red-lines.md · ui-conventions.md


۰. خط سرخ

# مورد وضعیت یادداشت
۰.۱ --group=slot-mode-frozen سبز
۰ AppointmentEvent دست‌نخورده جدول تفاوت در domain-events.md
۰ پیامک‌های موجود نشکستند Sms domain دست نخورد؛ تست‌هایش سبز
۰ گزارش با داده حدسی ساخته نشد مبنای «واقعی» فاصلهٔ ثبت‌شدهٔ اسلات است و همین در سند نوشته شد — نه حدسِ ساعت ورود و خروج

۱. بک‌اند — رویدادها

# مورد وضعیت یادداشت
۱.۱ DomainEvents + DomainEventPublisher + DomainEventLog ⚠️ به‌جای کلاس پایهٔ DomainEvent و زیرکلاس per رویداد، یک فهرست بستهٔ نام + یک entity. چهارده زیرکلاس خالی فقط برای اینکه نام را در تایپ نگه دارند، همان کاری را می‌کنند که const می‌کند
۱ payload فقط uuid و اسکالر مقادیر غیراسکالر حذف می‌شوند، نه سریال
۱ هر رویداد محیط دارد TenantOwnedTrait
۱ outbox — record() فقط persist تست rollback
۱.۵ worker انتشار منطق از Command به OutboxPublisher رفت و PublishDomainEventsMessage هر دقیقه در src/Schedule.php صادر می‌شود؛ همان worker-scheduler موجود مصرفش می‌کند
۱ سقف تلاش، بدون حذف ردیف شکست‌خورده تست دارد
۱.۷ همهٔ نقاط به record() وصل شدند دوازده نقطه؛ چهار موردِ باقی‌مانده هم بسته شد
۱ چهارده رویداد بند ۱۶ هر چهارده تا نقطهٔ ثبت دارند. AppointmentCompleted بعد از ذخیرهٔ موفق (انتقال ردشده رویداد نمی‌گذارد) · AppointmentRescheduled رویداد سوم است نه جایگزین Booked/Cancelled
۱ idempotency در مصرف‌کننده DomainEventMessage::$uuid + توضیح صریح در docblock و سند
۱.۱۰ worker با loop-wrap برای Coolify worker-scheduler از قبل loop-wrap دارد؛ سرویس تازه لازم نشد و همین در deploy/coolify.md نوشته شد
۱.۱۱ app:events:prune فقط ردیف منتشرشده حذف می‌شود؛ منتشرنشده مدرکِ گم‌شدن است
۱.۱۲ GET /domain-events فقط ادمین تست ۴۰۳/۲۰۰

۲. بک‌اند — گزارش‌ها

# مورد وضعیت یادداشت
۲.۱ ResourceUtilizationReporter
۲.۲ available × capacity اتاق سه‌تخته سه برابر عرضه دارد
۲.۳ passive در occupied هست، در active نه active از appointment_segments.patient_present می‌آید
۲.۴ setup/cleanup در occupied از resource_occupancy که همه را دارد
۲.۵ released شمرده نمی‌شود BLOCKING_STATUSES
۲.۶ available = 0utilization = null تست دارد
۲.۷ مرز بازه همپوشانی بازه‌ای (start < to AND end > from) — دقیق‌تر از مرز روی یک سر
۲.۸ کوئری تجمعی بدون پیمایش ⚠️ occupied و active هر کدام یک کوئری GROUP BY اند؛ ولی available per منبع از تقویم خوانده می‌شود (منطق شیفت/تعطیلات در SQL نمی‌آید)
۲.۹ تأیید وجود دادهٔ واقعی پیش از پیاده‌سازی patient_sessions زمان شروع/پایان مراجعه ندارد، پس مبنای «واقعی» فاصلهٔ اسلات شد و همین در سند نوشته شد
۲.۱۰ آستانه‌های شدت ۳۰/۱۵/۵ درصد
۲.۱۱ انحراف منفی هم high قدر مطلق
۲.۱۲ حداقل نمونه ۱۰ ⚠️ ۳ انتخاب شد. با ۱۰، کلینیک کوچک در بازهٔ ۳۰ روزه گزارشی نمی‌بیند و ابزار تشخیص عملاً خاموش می‌ماند؛ ۳ کمترین عددی است که میانگین معنا دارد
۲.۱۳ بازه > ۹۰ روز → ۴۲۲
۲.۱۴ سه endpoint

۳. دیتابیس

# مورد وضعیت یادداشت
۳.۱ domain_events با سه ایندکس Version20260731084058
۳.۲ ایندکس worker
۳.۳ هیچ جدول دیگری تغییر نکرد
۳.۴ TenantSchemaCoverageTest سبز

۴. UI

# مورد وضعیت یادداشت
۴.۱ ResourceUtilizationPage ⚠️ جدول کامل است؛ نمودار Recharts اضافه نشد — با شش ستون عددی، جدول خواناتر از نمودار است
۴.۲ PlanAccuracyPage
۴.۳ نشان «ظرفیت هدررفته» زیر ۰٫۳
۴.۴ توضیح active_ratio در خود UI هم زیرنویس صفحه هم title ستون
۴.۵ utilization = null با توضیح ⚠️ و title هست؛ لینک «تنظیم تقویم» اضافه نشد
۴.۶ لینک اصلاح از PlanAccuracyPage «ویرایش بخش‌های این خدمت»
۴.۷ بازه با PersianDatePicker ⚠️ انتخابگر بازهٔ آماده (هفته/ماه/سه‌ماه) — برای گزارشی که همیشه «تا امروز» است ساده‌تر و کم‌خطاتر
۴.۸ وضعیت در URL بازه و شعبه در state محلی‌اند
۴.۹ DataTable با skeleton و empty state
۴.۱۰ رنگ نمودار از توکن‌ها نمودار ندارد (۴.۱)
۴.۱۱ هیچ رنگ hard-code
۴.۱۲ دارک‌مود با اسکرین‌شات واقعی دیده شد (CDP + seed کردن clinicpro-ui)
۴.۱۳ حالت فشرده همان اجرا با density: compact
۴.۱۴ RTL و موبایل جدول‌ها اسکرول افقی داخلی دارند
۴.۱۵ رشته‌ها فارسی
۴.۱۶ backTo

۵. تست

# مورد وضعیت یادداشت
۵.۱ صندوق خروجی — rollback، انتشار، شکست، سقف تلاش
۵ payload فقط اسکالر مقادیر تودرتو و object حذف می‌شوند
۵ بهره‌وری — سنجه‌ها ⚠️ utilization = null تست شد؛ سناریوی کامل با اشغال واقعی و capacity تست نشد (نیازمند نوبت با بخش‌های ثبت‌شده)
۵ دقت برنامه — انحراف دوطرفه و نمونهٔ کم
۵.۵ دسترسی و بازه ۴۲۲ بازه، ۴۰۳ رویدادها، جداسازی محیط
۵ تعداد کوئری مستقل از تعداد منبع با ۲.۸ یک بسته است

اجرا: ddev exec php bin/phpunit tests/Report → ۱۶ تست.

۶. مستندات

# مورد وضعیت یادداشت
۶.۱ docs/api/reports.md معنی هر عدد + جدول شدت
۶.۲ docs/architecture/domain-events.md قرارداد، فهرست، outbox، idempotency، وضعیت انتشار هر رویداد
۶.۳ جدول تفاوت AppointmentEvent و DomainEventLog

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

# مورد وضعیت یادداشت
۷.۱ هیچ بی‌دلیل نمانده همه با دلیل
۷ bin/phpunit کامل سبز ۱۳۴۰ تست؛ flakeِ ثبت‌شده در تسک ۱۳ پیدا و رفع شد
۷ --group=slot-mode-frozen سبز
۷ phpstan بدون خطای جدید ۱۴ = baseline
۷.۵ npx tsc --noEmit و تست‌های فرانت سبز ۶۳۴ تست
۷ تست‌های tenant سبز
۷.۷ docs/api/* به‌روز
۷ چک‌لیست UI کامل ⚠️ جز ۴.۱، ۴.۵، ۴.۷، ۴.۸
۷ پیامک‌های موجود سرتاسر تست شدند مسیر Sms تغییر نکرد؛ رویدادها مسیر جدا دارند
۷.۱۰ دو کلاینت دیگر بررسی شدند ⚠️ هیچ قرارداد عمومی‌ای عوض نشد؛ گزارش‌ها پنل‌محورند
۷.۱۱ commit، سپس graphify update . دو کامیت جدا
۷.۱۲ موارد به‌تعویق با دلیل نمودار و URL-state (۴.۱/۴.۸) · تست کوئری‌شماری (۵.۶)