- 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.
14 KiB
فاز ۲ — چارت دندان و هدفگیری دندان روی خدمت ویزیت
پیشنیاز: فاز ۱. خروجی قابل تست: دندانپزشک وضعیت دندانهای بیمار را میبیند، ثبت خدمت روی دندان انجام میدهد و چارت خودکار بهروز میشود.
۱. هدف
سه چیز:
۱. هر بیمار در هر محیط یک چارت دندان داشته باشد. ۲. ثبت خدمت در ویزیت بتواند دندان و سطح را هدف بگیرد. ۳. چارت بعد از ثبت خدمت خودکار بهروز شود، و وضعیتهای قدیمی هم دستی قابل ثبت باشند.
۲. شمارهگذاری دندان
استاندارد FDI دو رقمی، همان ISO 3950.
دائمی : 11–18, 21–28, 31–38, 41–48
شیری : 51–55, 61–65, 71–75, 81–85
ذخیره بهصورت 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 از پیشفرض ساخته میشوند.
سمت چپ و راست جابهجا. خطای رایج در چارت دندان و در سند پزشکی خطرناک است. مهار: قرارداد جهت در کامنت بالای کامپوننت، و یک تست که دندان ۱۱ را در جای درست ادعا میکند.