Files
clinicpro/docs/new_feture/dental-module/phase-2-tooth-chart.md
T
hamed 2f030edef1 Add dental module phase 4 and phase 5 documentation, including treatment estimates, clinical operations, and preset content
- Introduced phase 4 documentation detailing treatment estimates, data models, state machines, API endpoints, and new dashboard metrics.
- Added phase 5 documentation covering consumables, lab operations, periodontal charts, sterilization cycles, clinical images, and a checklist for professional review.
- Created a preset content document outlining default dental service packages and protocols for clinics.
2026-08-20 16:21:08 +03:30

14 KiB
Raw Blame History

فاز ۲ — چارت دندان و هدف‌گیری دندان روی خدمت ویزیت

پیش‌نیاز: فاز ۱. خروجی قابل تست: دندانپزشک وضعیت دندان‌های بیمار را می‌بیند، ثبت خدمت روی دندان انجام می‌دهد و چارت خودکار به‌روز می‌شود.


۱. هدف

سه چیز:

۱. هر بیمار در هر محیط یک چارت دندان داشته باشد. ۲. ثبت خدمت در ویزیت بتواند دندان و سطح را هدف بگیرد. ۳. چارت بعد از ثبت خدمت خودکار به‌روز شود، و وضعیت‌های قدیمی هم دستی قابل ثبت باشند.


۲. شماره‌گذاری دندان

استاندارد FDI دو رقمی، همان ISO 3950.

دائمی : 1118, 2128, 3138, 4148
شیری  : 5155, 6165, 7175, 8185

ذخیره به‌صورت smallint، نه رشته. دلیل: مقایسه و بازه و ایندکس روی عدد کار می‌کند و «۱۱» و «11» دو مقدار جدا نمی‌سازد.

اعتبارسنجی در یک نقطه:

src/Dental/Validator/ToothNumberValidator.php

استانداردهای Universal و Palmer در لایهٔ داده استفاده نمی‌شوند. اگر بعداً لازم شد، فقط لایهٔ نمایش تبدیل می‌کند.

سطوح دندان:

M مزیال · D دیستال · O اکلوزال · B باکال · L لینگوال · P پالاتال · I اینسایزال

۳. مدل داده

همه در src/Dental/Entity.

ToothChart — جدول dental_tooth_charts

ستون نوع توضیح
id, uuid
entity_type, entity_id جفت محیط
patient_record_id int یکتا در هر محیط
dentition_type string 20 permanent, primary, mixed
last_examined_at int, nullable
created_at, updated_at int

یکتایی: (entity_type, entity_id, patient_record_id).

چارت با اولین نیاز ساخته می‌شود، نه با ساخت پرونده. دلیل: پروندهٔ بیماری که هرگز درمان دندانی نمی‌گیرد نباید ردیف خالی بسازد.

ToothStatus — جدول dental_tooth_statuses

ستون نوع توضیح
id, uuid
chart_id int ON DELETE CASCADE
tooth_number smallint FDI
condition string 30 وضعیت کلی دندان
surface_map json, nullable وضعیت هر سطح
note string 500, nullable
source string 20 manual یا visit
recorded_by_user_id int, nullable
updated_at int

یکتایی: (chart_id, tooth_number).

مقادیر condition:

healthy | caries | filled | crown | bridge_pontic | root_canal
implant | missing | extracted | impacted | to_extract | unerupted

surface_map شکل ثابت دارد:

{ "O": "filled", "M": "caries", "D": "healthy" }

چرا وضعیت جدا از تاریخچه ذخیره می‌شود: رندر چارت باید با یک کوئری انجام شود. اگر وضعیت هر بار از بازپخش تاریخچهٔ ویزیت‌ها ساخته شود، هر باز کردن تب یک محاسبهٔ سنگین است و وضعیت قبل از اولین مراجعه اصلاً قابل ثبت نیست. هزینهٔ پذیرفته‌شده: این جدول باید بعد از هر ویزیت به‌روز شود و این کار فقط در یک کلاس انجام می‌شود، نه پراکنده در کنترلرها.

ToothStatusLog — جدول dental_tooth_status_logs

هر تغییر وضعیت یک ردیف اضافه می‌کند. فقط افزودنی است.

ستون نوع
id, uuid
chart_id, tooth_number
from_condition, to_condition string 30
surface_map_before, surface_map_after json, nullable
session_service_id int, nullable
changed_by_user_id int, nullable
changed_at int

دلیل وجودش: چارت سند پزشکی است. «چه کسی دندان ۱۶ را کشیده‌شده علامت زد» باید قابل جواب دادن باشد.


۴. هدف‌گیری دندان روی خدمت ویزیت

تغییر روی دامنهٔ موجود

روی SessionService سه ستون اختیاری اضافه می‌شود:

tooth_number   smallint  nullable
surfaces       json      nullable
target_code    string 10 nullable   کد فک یا ناحیه

چرا اینجا و نه در جدول دندانی جدا: این‌ها ویژگی همان ردیف خدمتِ فاکتورشده‌اند. جدا کردنشان یعنی برای هر ردیف فاکتور یک join اضافه، و امکان اینکه ردیف فاکتور بدون هدف بماند بدون اینکه کسی بفهمد. برخلاف ServiceItem که تنظیمات است و مشترک همهٔ حوزه‌هاست، SessionService سند یک ویزیت است و این سه ستون بخشی از همان سند.

اعتبارسنجی

در src/Dental/Service/ToothTargetValidator.php.

قاعده بر اساس target_scope پروفایل خدمت:

target_scope لازم ممنوع
none و mouth هر سه
tooth tooth_number surfaces, target_code
tooth_surface tooth_number و حداقل یک سطح target_code
quadrant target_code از ۱ تا ۴ tooth_number, surfaces
arch target_code برابر upper یا lower tooth_number, surfaces

قاعدهٔ دوم: tooth_scope خدمت با شمارهٔ دندان بخواند. خدمت permanent_only روی دندان ۵۱ خطا می‌دهد.

قاعدهٔ سوم: خدمتی که پروفایل دندانی ندارد، هیچ هدفی نمی‌پذیرد.

خطا با ERR_VALIDATION_002 و نام فیلد.

پروجکتور چارت

مسیر: src/Dental/Service/ToothChartProjector.php

بعد از ثبت یا ویرایش ردیف خدمت با هدف دندانی:

سرویس ترمیمی روی سطوح  → همان سطوح در surface_map مقدار filled می‌گیرند
سرویس کشیدن دندان      → condition برابر extracted
سرویس درمان ریشه       → condition برابر root_canal
سرویس روکش             → condition برابر crown
سرویس ایمپلنت          → condition برابر implant
بقیه                   → وضعیت دست نمی‌خورد، فقط لاگ ثبت می‌شود

نگاشت خدمت به اثر، در همان DentalPreset تعریف می‌شود با کلید chart_effect. دلیل: مدیر می‌تواند خدمت دلخواه بسازد و اثرش را انتخاب کند، بدون اینکه کد عوض شود.

حذف ردیف خدمت، وضعیت را به عقب برنمی‌گرداند. دلیل: دندان کشیده‌شده با حذف یک ردیف فاکتور برنمی‌گردد. به‌جایش یک لاگ با توضیح ثبت می‌شود و اصلاح دستی می‌ماند.


۵. API

docs/api/dental.md گسترش پیدا می‌کند.

GET   /api/v1/dental/chart/{patientRecordUuid}
      → { chart: {...}, teeth: [ { tooth_number, condition, surfaces, note } ] }

PUT   /api/v1/dental/chart/{patientRecordUuid}/tooth/{toothNumber}
      → ثبت یا اصلاح دستی وضعیت یک دندان

GET   /api/v1/dental/chart/{patientRecordUuid}/tooth/{toothNumber}/history
      → لاگ تغییرات همان دندان

دسترسی:

عملیات clinic doctor secretary staff
دیدن چارت بله بیماران خودش خواندنی نه
ویرایش دستی چارت نه بله نه نه
ثبت هدف دندانی در ویزیت نه بله نه نه

خطاها:

کد HTTP حالت
ERR_VALIDATION_002 422 شمارهٔ دندان نامعتبر یا هدف ناسازگار
ERR_NOT_FOUND_001 404 پرونده در این محیط نیست
ERR_FORBIDDEN_001 403 نقش مجاز نیست

اندپوینت ثبت خدمت ویزیت هم کلیدهای تازه می‌گیرد و docs/api/patient.md همان جلسه به‌روز می‌شود.


۶. پنل ادمین

تب تازه

فایل: assets/admin/pages/PatientDetailPage.tsx

  • کلید تب: dental، برچسب «چارت دندان».
  • فقط وقتی حوزهٔ محیط دندانپزشکی است رندر می‌شود.
  • بین «پرونده پزشکی» و «ضمیمه» می‌نشیند.

کامپوننت چارت

فایل: assets/admin/components/dental/ToothChart.tsx

این تنها جایی است که ساخت کامپوننت تازه موجه است، چون هیچ کامپوننت موجودی این کار را نمی‌کند.

قواعد:

  • SVG دست‌نویس، بدون کتابخانهٔ بیرونی.
  • هر دندان یک گروه قابل کلیک با شمارهٔ FDI.
  • هر سطح یک مسیر جدا، تا کلیک روی سطح جدا از کلیک روی دندان باشد.
  • رنگ‌ها فقط از توکن‌های styles.css. هیچ رنگ ثابتی در کد کامپوننت نیست.
  • چیدمان RTL و سازگار با تم تیره.
  • فک بالا در ردیف بالا، فک پایین در ردیف پایین، سمت راست بیمار در سمت راست تصویر. این قرارداد در بالای فایل به‌صورت کامنت نوشته شود چون خطای رایج همین است.
  • حالت شیری و مختلط: دندان‌های شیری در همان گرید، کوچکتر.
  • بدون تعامل هم باید خوانا باشد، چون در چاپ پرونده استفاده می‌شود.

فرم ثبت خدمت در ویزیت

فایل: assets/admin/pages/EditSessionPage.tsx

  • بعد از انتخاب خدمت، اگر پروفایل دندانی دارد، انتخابگر هدف نشان داده شود.
  • انتخاب دندان از روی همان ToothChart انجام شود، نه از یک select با ۳۲ گزینه.
  • انتخاب سطح فقط وقتی target_scope برابر tooth_surface است.

۷. تسک‌ها

کد تسک فایل‌های اصلی معیار پذیرش
DM2-01 ToothNumberValidator و ثابت‌های FDI src/Dental/Validator/ همهٔ شماره‌های معتبر و نامعتبر تست می‌شوند
DM2-02 موجودیت ToothChart src/Dental/Entity/ یکتایی پرونده در محیط
DM2-03 موجودیت ToothStatus با surface_map همان شکل json اعتبارسنجی می‌شود
DM2-04 موجودیت ToothStatusLog همان فقط افزودنی، بدون متد حذف
DM2-05 سه ستون هدف روی SessionService با migration src/Patient/Entity/SessionService.php ردیف بدون هدف مثل قبل کار می‌کند
DM2-06 ToothTargetValidator src/Dental/Service/ هر پنج حالت target_scope تست می‌شود
DM2-07 ToothChartProjector و نگاشت chart_effect src/Dental/Service/, src/Dental/Preset/ ثبت کشیدن دندان، وضعیت را عوض می‌کند و لاگ می‌زند
DM2-08 سه اندپوینت چارت src/Dental/Controller/DentalChartController.php موفق، بدون دسترسی، پروندهٔ محیط دیگر
DM2-09 گسترش ثبت خدمت ویزیت برای هدف دندانی src/Patient/Controller/PatientController.php هدف ناسازگار ۴۲۲ می‌دهد
DM2-10 کامپوننت ToothChart assets/admin/components/dental/ تست: کلیک دندان، کلیک سطح، حالت فقط‌خواندنی
DM2-11 تب چارت در پروندهٔ بیمار assets/admin/pages/PatientDetailPage.tsx برای حوزهٔ غیر دندانی رندر نمی‌شود
DM2-12 انتخابگر هدف در فرم ثبت خدمت assets/admin/pages/EditSessionPage.tsx خدمت بدون پروفایل، انتخابگر نشان نمی‌دهد
DM2-13 به‌روزرسانی docs/api/dental.md و docs/api/patient.md docs/api/ مسیرها با کد یکی است

۸. تست‌ها

  • ثبت خدمت روی دندان شیری با خدمت permanent_only: خطای ۴۲۲.
  • ثبت خدمت tooth_surface بدون سطح: خطای ۴۲۲.
  • ثبت خدمت arch با شمارهٔ دندان: خطای ۴۲۲.
  • ثبت کشیدن دندان: وضعیت extracted و یک ردیف لاگ.
  • ویرایش دستی وضعیت: منبع manual ثبت می‌شود.
  • خواندن چارت بیمار محیط دیگر: خطای ۴۰۴، نه ۴۰۳. دلیل: نباید وجود پرونده در محیط دیگر لو برود.
  • منشی چارت را می‌بیند ولی نمی‌تواند ویرایش کند.
  • چارت بیماری که هیچ درمانی نگرفته: ساخته می‌شود و همهٔ دندان‌ها healthy برمی‌گردند بدون اینکه ۳۲ ردیف در دیتابیس ساخته شود.

۹. ریسک‌ها

واگرایی چارت از فاکتور. اگر کاربر خدمت را ثبت کند ولی هدف را خالی بگذارد، چارت به‌روز نمی‌شود و کسی نمی‌فهمد. مهار: برای خدمتی که پروفایل دندانی دارد، هدف اجباری است و ردیف بدون هدف اصلاً ذخیره نمی‌شود.

تعداد ردیف وضعیت. اگر برای هر بیمار ۳۲ ردیف ساخته شود، جدول سریع بزرگ می‌شود. مهار: فقط دندان‌هایی که وضعیتشان از healthy فاصله گرفته ردیف می‌گیرند. بقیه در پاسخ API از پیش‌فرض ساخته می‌شوند.

سمت چپ و راست جابه‌جا. خطای رایج در چارت دندان و در سند پزشکی خطرناک است. مهار: قرارداد جهت در کامنت بالای کامپوننت، و یک تست که دندان ۱۱ را در جای درست ادعا می‌کند.