التحليل الشامل لنظام إدارة عيادات النساء والتوليد
وخطة دمجه كموديول في منظومة Moon ERP
تحليل معماري وقاعدي كامل لنظام العيادات الحالي (OB/GYN Clinic System) أُجري على الكود المصدري الفعلي ومخطط قاعدة البيانات الكامل، بهدف استخراج نماذج البيانات (Models) وعلاقاتها وسير العمل الإكلينيكي، تمهيداً لبناء موديول العيادات الجديد داخل نظام تخطيط موارد الشركة.
الملخص التنفيذي (Executive Summary)
خلاصة ما توصّل إليه التحليل في صفحة واحدة — التفاصيل الكاملة في الأقسام الجانبية، قسم لكل موديول.
ما هو النظام؟
نظام متكامل لإدارة مراكز وعيادات أمراض النساء والتوليد والعقم، يعمل منذ ما يقارب عام 2015، ويغطي رحلة المريضة كاملة: التسجيل والحجز والطابور، ثم الشيتات الإكلينيكية المتخصصة (متابعة الحمل ANC، أمراض النساء، العقم وتأخر الإنجاب، الحقن المجهري IVF/ICSI/IUI مع شيت متابعة التنشيط، تحاليل الزوج والسائل المنوي)، مروراً بالموجات الصوتية والأشعة والمناظير والعمليات والولادات، وانتهاءً بالروشتات والتحاليل والماليات. ويُلحق به ثلاثة تطبيقات مساندة: صيدلية بمخزون وفواتير شراء وبيع، وبورد تعليمي لمناقشة الحالات بين الأطباء، وشاشة انتظار لعرض الطابور.
أهم الاستنتاجات
- قيمة إكلينيكية عالية جداً: النظام يحتوي معرفة طبية متخصصة متراكمة (بروتوكولات التنشيط، قياسات الأجنة، مفردات التشخيص المزروعة في ~190 جدول ترميز) تمثل أهم أصل يجب الحفاظ عليه عند النقل — وهي موثقة بالكامل في هذا التقرير.
- بنية تقنية منتهية العمر: framework مخصص ("aw framework") بدون Composer أو اختبارات أو إدارة إصدارات، مع قاعدة بيانات بلا أي مفاتيح أجنبية (Foreign Keys) — كل العلاقات ضمنية عبر تسمية الأعمدة، وقد استخرجها التحليل وأثبتها من كود الكنترولرات.
- نمط تصميم متكرر قابل للتوحيد: النظام يكرر نمط "شيت + جداول أدوية + جداول تحاليل" عشر مرات (10 جداول روشتات و8 جداول طلبات تحاليل متطابقة البنية) — يمكن دمجها في جدولين موحّدين فقط في الـ ERP.
- ديون تقنية وأمنية جوهرية: ثغرات حقن SQL في نقاط كتابة عامة، غياب CSRF، ملفات مرضى (3.2 جيجا) ونسخ قاعدة البيانات كاملة داخل مجلد الويب العام، وكلمات مرور بتشفير ضعيف — التفاصيل في قسم المعمارية، وكلها تُحل تلقائياً بالنقل إلى الـ ERP.
- جداول ميتة ومكررة: نحو 40 جدولاً مهجوراً أو مكرراً (منها 4 نسخ متطابقة لجدول السائل المنوي بأخطاء إملائية) حُدّدت بالاسم ولن تُنقل.
- تكامل قائم بالفعل مع الـ ERP: النظام يزامن المرضى والفواتير حالياً مع الـ ERP عبر cURL — عند الدمج يصبح هذا التكامل داخلياً مباشراً ويُلغى الازدواج.
التوصية
بناء موديول Modules/Obgy داخل Moon ERP (بنية Laravel Modules + واجهة Angular) بإجمالي ~85 جدولاً منظّماً بدلاً من 312، مع إعادة استخدام مكونات الـ ERP القائمة: ملف المريض الموحد، موديول المعامل LIS للتحاليل، المخزون للصيدلية، والحسابات للماليات. خطة التنفيذ المرحلية الكاملة وخريطة نقل كل جدول قديم إلى الموديل الجديد في قسم خطة النقل إلى ERP، وخريطة العلاقات الكاملة في قسم ERD.
كيف تقرأ هذا التقرير؟
- القائمة الجانبية تنقلك لأي موديول مباشرة — كل قسم مستقل وقابل للقراءة منفرداً.
- كل موديول يعرض: الغرض، الوظائف، جدولاً يوثّق كل جداول قاعدة البيانات التابعة له بحقولها وعلاقاتها، سير العمل الفعلي كما استُخرج من الكود، ثم توصيات النقل.
- الملحق الفني
obgy-erp-analysis.md(مرفق مع التقرير) يحتوي النسخة التقنية الكاملة بالإنجليزية — بنية كل جدول بكل أعمدته وقيم جداول الترميز المزروعة — وهو مُعدّ ليُغذّى مباشرة إلى Claude Code عند بدء تنفيذ الموديول.
تحديث (11 يونيو): اكتشاف النسخة الثانية
بعد إصدار هذا التقرير اكتُشفت نسخة ثانية عاملة من البرنامج لدى مستشفى Green Nature (السعودية) تبيّن أنها نسخة أحدث متشعبة (Fork) وليست مجرد إعدادات مختلفة: ~70 كنترولر إضافي و178 جدولاً جديداً تغطي الإقامة الداخلية وغرف العمليات ومعمل الأجنة والتجميد وقسم الأشعة وعيادة الذكورة وتعدد الفروع. التحليل الكامل في ملحق النسخة الثانية آخر التقرير، وتعديلات خطة النقل المترتبة عليه في قسم تعديلات الخطة.
المعمارية التقنية للنظام (Technical Architecture)
النظام مبني على إطار عمل PHP مخصص يُسمى "aw framework" (تطوير داخلي يعود لحوالي عام 2015)، بدون أي إطار عمل قياسي معروف. يتكون من أربعة تطبيقات فرعية تتشارك قاعدة بيانات MySQL واحدة (312 جدولًا) ومكتبات مشتركة في مجلد _library. طبقة العرض تعتمد على قوالب Smarty، وطبقة البيانات على RedBeanPHP، والتوجيه يتم بالوصول المباشر لملفات الكنترولر دون نقطة دخول موحدة. هذا القسم يشرح البنية وطريقة العمل والوضع الأمني والديون التقنية بصراحة مهنية لدعم قرار الترحيل إلى منظومة Laravel + Angular.
نظرة عامة على البنية
- المعمارية: تطبيق PHP تقليدي (Server-Side Rendering) بنمط شبيه بـ MVC لكن دون فصل حقيقي — كل شاشة عبارة عن ملف كنترولر مستقل يُستدعى مباشرة من المتصفح مثل
/obgy/core/controllers/patients.php?ac=search. - لا توجد نقطة دخول موحدة (Front Controller) ولا نظام Routing — ملف
.htaccessالرئيسي يضبط فقطDirectoryIndexوصفحات الأخطاء ويمنع تصفح المجلدات (Options -Indexes)، بينماRewriteEngine off. - المكونات المشتركة في
_library/: مكتبة قاعدة البيانات (RedBeanPHP)، نظام تسجيل الدخول (login_system)، مكتبة JWT (غير مستخدمة فعليًا)، قوالب Smarty، وإضافات (Breadcrumbs، رفع ملفات، PHPMailer). - الإعدادات في
_public/aw_config.php(نموذج عام) مع نسخة مكررة داخل كل تطبيق فرعي (core/public/aw_config.phpوما يقابلها) — جميعها تحمل نفس بيانات اتصال قاعدة البيانات مكتوبة نصًا صريحًا. - ملفات المرضى وصور/فيديوهات السونار تُخزن على نظام الملفات في مجلد
upload/(نحو 3.2 جيجابايت، منها 3.1 جيجابايت سونار) داخل مجلد الويب العام. - تكاملات خارجية: مزامنة العملاء والفواتير مع نظام ERP منفصل عبر cURL، وواجهة API خارجية للرسائل القصيرة على
http://api.gt4it.com(بدون تشفير HTTPS).
مكونات النظام الأربعة
| التطبيق | المسار | الغرض | الحجم التقريبي |
|---|---|---|---|
| العيادة الرئيسية (core) | obgy/core/ | قلب النظام: المرضى، الزيارات، الشيتات الإكلينيكية (حمل/نساء/عقم/حقن مجهري)، التقارير المالية، الإعدادات، النسخ الاحتياطي، وخدمات الموبايل mobileservices.php | 70 كنترولر / ~37,900 سطر |
| الصيدلية (pharmacy) | obgy/pharmacy/ | الأدوية، المشتريات، المخزن، الفواتير (receipt)، الموظفون | 6 كنترولرات |
| البورد التعليمي (board) | obgy/board/ | جلسات وطلبات البورد والموظفون | 4 كنترولرات |
| شاشة الانتظار (screen) | obgy/screen/ | شاشة عرض دور المرضى في الاستقبال — يعيد استخدام ملفات core مباشرة (require core/controllers/imp/) | كنترولر واحد |
- التطبيقات الأربعة تتشارك قاعدة بيانات واحدة (
amrtechogate_obgy) ونفس جداول المستخدمين والصلاحيات (awusers/awrole...) ونفس المكتبات. - كل تطبيق فرعي يكرر نفس بنية المجلدات (controllers / views / public / temp) ونفس ملف الإعدادات بنفس كلمة مرور قاعدة البيانات — أي تغيير في الإعدادات يجب تكراره يدويًا في 4-5 مواضع.
الـ Framework المخصص (aw framework) وطريقة عمله
- التوجيه (Routing): الملف
core/controllers/imp/_imp.php(23 سطرًا) هو "الموجّه" بالكامل: يقرأ?ac=من الرابط، ينشئ كائنًا من كلاسControllers، ويستدعي الدالة المطابقة لاسمacإن وُجدت وإلاindex(). لا يوجد تحقق من نوع الطلب (GET/POST) ولا قائمة سماح بالأكشنات — أي دالة public في الكلاس قابلة للاستدعاء من الرابط مباشرة. - نمط الكنترولر: كل ملف من الـ81 ملفًا يعرّف كلاسًا بنفس الاسم
Controllers(تعارض تسمية مقصود لأن كل ملف يعمل منفصلًا). الـ constructor يكرر في كل ملف نفس الكود التمهيدي (~60 سطرًا): تحميل الإعدادات والاتصال بقاعدة البيانات وتهيئة Smarty وBreadcrumbs وتضمين كلاسات_header/_sidebar/_leftsidebar/_footer. - ربط العرض (Views): قوالب Smarty 3.1.11 في مجلد
views/؛ كل أكشن يعرض الصفحة على أجزاء متتالية:header::headershow()ثمsidebar::sidebarshow()ثم القالب الخاص بالشاشة ($smarty->display('xxx.html')) ثم القائمة اليسرى والفوتر. تمرير البيانات عبر$smarty->assign(). - نموذج الصلاحيات (RBAC): نظام صلاحيات دقيق مبني على جداول:
awcontroll(الشاشات) وawcontrollprop(الأكشنات داخل كل شاشة) وawrole(الأدوار) وawrolecontrollprop(صلاحية كل دور على كل أكشن) إضافة إلىawmenu/awrolemenu(القوائم لكل دور) وawrolebtn(أزرار الواجهة). الدالةautho::checkauthoize()تتحقق عند كل أكشن من صلاحية دور المستخدم الحالي ($_SESSION['role_id']) وتعيد التوجيه لصفحة خطأ عند الرفض. - القائمة الديناميكية: القائمة الجانبية تُبنى من جدول
awmenuهرميًا حسب دور المستخدم وإعداد "النموذج المبسط/الكامل" فيprogramesetting. - نقطة ضعف جوهرية: تفعيل التحقق من الصلاحيات يعتمد على انضباط المطور — في عدة أكشنات نجد سطور التحقق معلّقة (commented out)، وأبرزها كنترولر خدمات الموبايل بالكامل.
طبقة البيانات
| العنصر | التفاصيل | الملاحظات |
|---|---|---|
| المكتبة (ORM) | RedBeanPHP إصدار 4.3 — ملف واحد _library/db_main/rb.php (12,380 سطرًا) | إصدار قديم (~2016)؛ الإصدار الحالي 5.x |
| قاعدة البيانات | MySQL — قاعدة amrtechogate_obgy بـ312 جدولًا (307 InnoDB، 5 MyISAM منها جدول المستخدمين awusers) | جدول المستخدمين MyISAM لا يدعم المعاملات |
| الترميز (Charset) | الاتصال يفرض SET NAMES latin1 بينما الجداول utf8 وتحوي بيانات عربية | اعتماد على "ازدواج ترميز" هش — أي ترحيل بيانات يتطلب معالجة ترميز دقيقة |
| وضع التشغيل | R::freeze(FALSE) — الوضع "السائل" (Fluid Mode) مفعّل في الإنتاج | المكتبة قادرة على تعديل بنية الجداول تلقائيًا أثناء التشغيل — مخاطرة على سلامة المخطط |
| أسلوب الاستعلام | خليط: ORM (R::find/load/store/trash) باستعلامات مُعاملة آمنة، بجانب SQL خام عبر R::getAll/getRow/exec كثير منه مبني بدمج نصوص مباشر | الجزء الخام هو مصدر ثغرات حقن SQL (انظر الأمان) |
| المعاملات (Transactions) | R::begin/commit/rollback تُستخدم في عمليات الإدخال المركبة | ممارسة جيدة، لكنها بلا أثر على الجداول الـMyISAM |
المصادقة وواجهات الـ API
- تسجيل الدخول: مبني على مكتبة php-login مفتوحة المصدر (
_library/login_system/classes/Login.php) تستخدم PDO باستعلامات مُعاملة (Prepared Statements) وجلسات PHP و"تذكرني" بكوكي، مع عدّاد محاولات فاشلة (user_failed_logins) للحد من التخمين. - تخزين كلمات المرور: ممتاز نسبيًا —
password_hash()بخوارزمية bcrypt بتكلفة 10 (مؤكد من عمودuser_password_hashبصيغة$2y$10$...في جدولawusers)، وكذلك كلمات مرور المرضى للموبايل. - API الموبايل:
core/controllers/mobileservices.php(671 سطرًا) يوفر تسجيل/تحديث بيانات المرضى وإرجاع JSON — لكن كل فحوصات الدخول والصلاحيات فيه معلّقة، ومفتوح للجميع معAccess-Control-Allow-Origin: *. - JWT: مكتبة
php-jwt-masterموجودة في_libraryلكن لا يوجد أي استدعاء لها في كود التطبيقات — تبعية ميتة، أي لا توجد مصادقة Token حقيقية للـ API. - إعدادات API خارجية:
_public/api_config.phpيضع مفاتيحapi_key/api_user/api_passwordكمتغيرات بيئة بقيم مكتوبة نصًا في الملف، ويفعّلdisplay_errors = on— ولا يوجد ملف داخل النظام يستدعيه (يُرجح استخدامه من خدمات خارجية مثل SMS/التحاليل). - تكامل ERP: استدعاءات cURL مباشرة من الكنترولرات إلى
/ERP/controllers/clientControllerAjax.phpلمزامنة العملاء والفواتير دون أي توقيع أو مفتاح مصادقة ظاهر.
الأمان — نقاط القوة
- تشفير كلمات المرور بـ bcrypt عبر
password_hash/password_verifyمع إعادة تجزئة تلقائية عند الحاجة. - نظام صلاحيات RBAC دقيق على مستوى الأكشن الواحد (جداول
awcontroll/awrole*) مطبق في معظم شاشات النظام الداخلية. - استخدام
filter_input()لقراءة المدخلات، واستعلامات مُعاملة في مكتبة الدخول وفي جزء كبير من استدعاءات ORM. display_errors = offفي الإعدادات الرئيسية، ومنع تصفح المجلدات في.htaccess، وحد لمحاولات الدخول الفاشلة.- نسخ احتياطي يومي تلقائي لقاعدة البيانات مع إمكانية إرساله بالبريد.
الأمان — نقاط الضعف (بصراحة مهنية)
| الثغرة | الدليل (مسار الملف) | الخطورة |
|---|---|---|
| حقن SQL — مدخلات المستخدم تُدمج نصيًا في الاستعلامات (شاشة بحث المرضى: الاسم/العنوان/الهاتف...، التقارير المالية، الزيارات، السونار) | core/controllers/patients.php (بناء $q1..$q8 بصيغة LIKE '%$input%')، financialreport.php (executeSql)، visits.php، sonar.php (R::exec('... WHERE id = ' . $id)) | حرجة — قاعدة البيانات تحوي بيانات طبية حساسة |
| API الموبايل بلا أي مصادقة + CORS مفتوح للجميع، يتيح إنشاء/تعديل سجلات مرضى وقراءة بياناتهم | core/controllers/mobileservices.php (فحوصات autho معلّقة، Access-Control-Allow-Origin: *) | حرجة |
| بيانات اعتماد مكتوبة نصًا داخل الكود: كلمة مرور قاعدة البيانات مكررة في 5 ملفات إعدادات، مفاتيح API خارجية، ومفتاح سري للكوكيز ثابت | _public/aw_config.php، _public/api_config.php، ونسخ core/pharmacy/board/screen/public/aw_config.php | عالية |
| النسخ الاحتياطية لقاعدة البيانات (ببيانات المرضى كاملة) مخزنة داخل مجلد الويب العام، وتُنشأ بأمر نظام يمرر كلمة المرور في سطر الأوامر | core/db_backups/ (1.6 جيجابايت، 39 نسخة)، _db/*.sql، الكود في core/controllers/index.php (دالة takeackup عبر system()) | عالية |
| لا توجد حماية CSRF في أي نموذج، ولا قائمة سماح للأكشنات القابلة للاستدعاء من الرابط | نمط imp/_imp.php العام في كل الكنترولرات | عالية |
أكشنات إدارية خطرة قابلة للاستدعاء بمجرد تسجيل الدخول دون فحص صلاحيات (مثل onesetup الذي يحذف قوائم وأدوارًا) | core/controllers/index.php (دالة onesetup — فحص الدخول فقط دون فحص الدور) | متوسطة إلى عالية |
display_errors = on في إعدادات الـ API (تسريب تفاصيل تقنية)، واتصال خارجي بخدمة SMS عبر HTTP غير مشفر | _public/api_config.php، $hosturlApi = 'http://api.gt4it.com' في aw_config.php | متوسطة |
| وضع ORM "السائل" مفعّل في الإنتاج (يسمح بتعديل بنية الجداول تلقائيًا) | R::freeze(FALSE) في _public/aw_config.php | متوسطة |
الديون التقنية (Tech Debt)
| البند | الوضع الحالي | الأثر |
|---|---|---|
| إصدار PHP | الخادم يعمل بـ PHP 5.6.40 — انتهى دعمه الأمني نهائيًا في ديسمبر 2018 | لا تصلح أمنية منذ 7+ سنوات؛ عائق أمام أي مكتبات حديثة |
| Smarty | الإصدار 3.1.11 (صدر 2012) | ثغرات معروفة في إصدارات Smarty القديمة، ولا هروب تلقائي للمخرجات افتراضيًا |
| RedBeanPHP | الإصدار 4.3 (~2016) كملف وحيد منسوخ يدويًا | لا إدارة تبعيات (لا Composer إطلاقًا في المشروع) |
| تكرار الكود | ~60 سطرًا من كود التهيئة منسوخة في كل كنترولر من الـ81؛ ملفات إعدادات مكررة بنفس كلمة المرور في كل تطبيق فرعي؛ كنترولرات عملاقة (patients.php = 2,259 سطرًا، visits.php = 1,946) | أي تعديل عرضي مكلف وعرضة للأخطاء؛ صعوبة الصيانة هي المحرك الأساسي لقرار الترحيل |
| ملفات الرفع | مجلد upload/ بحجم ~3.2 جيجابايت (السونار وحده 3.1) داخل مجلد الويب، يُقرأ من نظام الملفات مباشرة دون فهرسة كاملة في قاعدة البيانات | صعوبة النسخ الاحتياطي والترحيل؛ مخاطر وصول مباشر للملفات |
| استراتيجية النسخ الاحتياطي | تُنفذ داخل طلب الصفحة الرئيسية: أول زيارة يومية للصفحة الرئيسية تشغّل mysqldump بشكل متزامن وتكتب في core/db_backups/ (39 نسخة متراكمة، 1.6 جيجابايت) دون تدوير أو نقل خارج الخادم؛ نسخ Excel في core/excel_backups/ | بطء عشوائي للمستخدم الأول صباحًا؛ النسخ على نفس القرص = لا حماية من فقد الخادم |
| اتساق البيئة | توقيتان مختلفان في الإعدادات (لوس أنجلوس في aw_config مقابل القاهرة في الكود والـ API)؛ ترميز latin1/utf8 مزدوج؛ كود ميت (php-jwt، جداول مهجورة، كتل معلّقة كثيرة) | أخطاء تواريخ محتملة؛ تعقيد إضافي عند ترحيل البيانات |
| الاختبارات والتحكم بالإصدارات | لا توجد أي اختبارات آلية، ولا مستودع Git، وملفات error_log وملفات تجريبية متناثرة داخل مجلدات الكنترولرات | أي تعديل = مخاطرة غير مقيسة؛ يصعّب التطوير المتوازي |
الخلاصة الإدارية
- النظام مكتمل وظيفيًا وغني إكلينيكيًا، ونموذج الصلاحيات فيه جيد التصميم، لكن أساسه التقني (PHP 5.6 + إطار مخصص بلا صيانة + تكرار كود واسع) وصل لنهاية عمره الافتراضي.
- الثغرات الحرجة (حقن SQL في شاشات البحث والتقارير، وAPI الموبايل المفتوح، والنسخ الاحتياطية داخل مجلد الويب) تمس بيانات طبية حساسة وتستوجب معالجة عاجلة حتى مع المضي في خطة الترحيل.
- الترحيل إلى Laravel + Angular مبرر تقنيًا بقوة: يعالج جذريًا مشاكل الأمان (Eloquent/حماية CSRF/مصادقة API)، وإدارة التبعيات، وتكرار الكود، ويتيح فصل الواجهات وخدمات الموبايل عبر API موحد — مع التنبيه إلى أن أصعب جزء في الترحيل سيكون نقل 312 جدولًا بترميز مزدوج وملفات 3.2 جيجابايت دون فقد بيانات.
إدارة المرضى والتسجيل (Patients & Registration)
هذا الموديول هو قلب النظام بأكمله؛ فجدول patients هو المحور الذي ترتبط به جميع الموديولات الأخرى تقريبًا (الزيارات، الفحوصات، التاريخ المرضي، الشيتات الإكلينيكية، الفواتير) عبر العمود patientid. يتولى الموديول تسجيل بيانات المريضة الديموغرافية الكاملة (الزوجة) وبيانات الزوج في نفس السجل، مع رقم ملف تسلسلي للعيادة، وإدارة قوائم الترميز المساعدة (الوظائف، التعليم، فصائل الدم، الحالة الاجتماعية، الألقاب)، والبحث متعدد المعايير، والسجل الطبي السريع، وملفات المريضة المرفوعة، مع مزامنة فورية لبيانات المريضة كعميل في نظام ERP خارجي عبر cURL.
الوظائف الرئيسية
- تسجيل مريضة جديدة بنظام "المسودة": يُنشأ سجل فارغ بحالة
done=0لكل مستخدم ويُستكمل تدريجيًا ثم يُعتمد عبرaddfinishبحالةdone=1. - توليد رقم ملف تلقائي
statusno(أكبر رقم موجود + 1) مع إمكانية الإدخال اليدوي حسب إعدادprogramesetting.patientnoaut. - قراءة الرقم القومي المصري (14 رقمًا) بتعبير نمطي واستخراج تاريخ الميلاد منه وحساب العمر تلقائيًا (سنة/شهر/يوم) للزوجة والزوج.
- تسجيل بيانات الزوجة الكاملة: الاسم، اللقب، الميلاد، التعليم، الوظيفة، الحالة الاجتماعية، فصيلة الدم، الرقم القومي، العنوان، الهاتف، مدة الزواج، عدد الأبناء (ذكور/إناث)، ملاحظات الخطورة
risk/risktype. - تسجيل بيانات الزوج في نفس السجل: الاسم، اللقب، الميلاد، التعليم، الوظيفة، فصيلة الدم، الرقم القومي، العادات
husband_habbitsوملاحظاته. - تسجيل الزيجات السابقة للزوجة والزوج (جداول
previous_marriageوhus_previous_marriage). - فحص التكرار لحظيًا عبر AJAX: اسم الزوجة، رقم الملف، الرقم القومي للزوجة والزوج، رقم الهاتف.
- إنشاء زيارة استقبال (كشف) مع التسجيل مباشرة: نوع الكشف، قيمة نقدي/فيزا، خصم، دور الانتظار — تُكتب في جدول
visitsداخل نفس المعاملة. - بحث متعدد المعايير (اسم/رقم ملف، اسم الزوج، وظيفة الزوج أو الزوجة، العنوان، الهاتف، المحمول، العمر، الرقم القومي) وبحث بالقسم في وضع المستشفى عبر
visits.detectionid، مع توجيه المستخدم لآخر شاشة إكلينيكية من جدولlastvisit. - إدارة كاملة (إضافة/تعديل/حذف) لقوائم الترميز: ألقاب الزوجة والزوج، التعليم، الوظائف، الحالة الاجتماعية، فصائل الدم — كلها من شاشة المريض نفسها عبر AJAX.
- شريط بيانات المريضة الموحد
_patientdata.phpالذي يظهر أعلى كل شاشة إكلينيكية: البيانات الديموغرافية + الصيغة التوليدية (P / CS / AB / Ectopic / VM / SVD) محسوبة من جدولphobstetricمضافًا إليها أعمدة الرصيد الافتتاحي فيpatients، وملخص التاريخ المرضي والجراحي والنسائي والعائلي. - السجل الطبي السريع (
record.php): صفوف تشخيص/علاج بالتاريخ مع روشتات للزوجة أو الزوج من كتالوج الأدوية وطباعتها. - إدارة ملفات المريضة: رفع متعدد إلى مجلد
upload/patientfiles/{id}وعرض وتحميل الملفات (قراءة من نظام الملفات مباشرة). - إنهاء فترة المتابعة وتسجيل تقارير إنهاء الزيارات (
endvisitreports). - كلمة مرور للمريضة
patient_password_hash(مشفرة بـpassword_hash) لاستخدامها في خدمات الموبايل. - مزامنة المريضة كعميل في نظام ERP خارجي (إضافة/تحديث/حذف وفاتورة كشف) عبر cURL إلى
clientControllerAjax.php، مع زر ترحيل جميع المرضى دفعة واحدةaddAllPatientsToERP.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
patients | الجدول المحوري للنظام: سجل واحد لكل مريضة يضم بيانات الزوجة والزوج معًا، مع أرصدة افتتاحية للصيغة التوليدية وأعلام الحذف والاعتماد | id, statusno, wifename, wiftypeid, dateofbirth, wifeage, wifeeducation, wifejob, wifebl, wifenationalid, statuesid, mirragefrom, mirragefromdate, boyson, girlson, husdandname, husbandtypeid, husbanddateofbirth, husbandjob, husbandbl, husbandnationalid, husband_habbits, address, phone, mobile, risk, risktype, pno, ab, ectopic, vmodel, svd, cs, done, deleted, userid, doctorid, patient_password_hash | wifetypes عبر wiftypeid، wifestatus عبر statuesid، education عبر wifeeducation/husbandeducation، wifejobs عبر wifejob، husbandjobs عبر husbandjob، bloodtypes عبر wifebl/husbandbl، husbandtypes عبر husbandtypeid، risktype عبر risktype، awusers عبر userid/doctorid |
patients_updates | نسخة كاملة من بنية patients مضافًا إليها أعمدة تدقيق (userid_edit, date_edit, patientid_edit) — يبدو أنها سجل تاريخي لتعديلات بيانات المرضى، ولا يوجد كود فعّال يكتب فيها حاليًا (استنتاج) | نفس أعمدة patients + userid_edit, date_edit, patientid_edit | patients عبر patientid_edit (استنتاج)، awusers عبر userid_edit |
patients_tmp | جدول مؤقت مهجور (اسم فقط) لا يُستخدم في أي كنترولر — مخلفات تطوير | pit_id, pit_name | لا توجد |
patientfiles | مُعدّ لفهرسة ملفات المريضة المرفوعة، لكن الكود الحالي يقرأ الملفات من مجلد upload/patientfiles/{patientid} مباشرة دون استخدام الجدول (جدول غير مفعّل) | id, patientid, file | patients عبر patientid |
registeration | صفوف "حجز/تسجيل الولادة" المرتبطة بشيت متابعة الحمل: مكان الولادة، المنشأ، النوع، التكلفة — تُنشأ من شاشة ANC Sheet وتُقرأ في تقارير الولادات | id, ancsheetid, place2, origin, type, awifep, coast, rplace | ancsheet عبر ancsheetid، origin عبر origin |
records | السجل الطبي السريع: سطر تشخيص وعلاج نصي لكل تاريخ لكل مريضة (شاشة Record) مع حذف منطقي | id, patientid, date, diagnosis, ttt, del | patients عبر patientid، وترتبط وظيفيًا بـ recorddrugs عبر patientid + date |
origin | قائمة ترميز "منشأ/جهة الولادة" المستخدمة في صفوف registeration وتقارير الولادات | id, title, del | تُقرأ من registeration عبر origin |
education | قائمة ترميز المستوى التعليمي (تستخدم للزوجة والزوج معًا) وتُدار من شاشة المريض | id, title, del | patients عبر wifeeducation وhusbandeducation |
bloodtypes | قائمة ترميز فصائل الدم (للزوجة والزوج) | id, title, del | patients عبر wifebl وhusbandbl |
wifejobs | قائمة ترميز وظائف الزوجة، وتدخل في البحث المتقدم | id, title, del | patients عبر wifejob |
husbandjobs | قائمة ترميز وظائف الزوج، وتدخل في البحث المتقدم | id, title, del | patients عبر husbandjob |
wifestatus | قائمة الحالة الاجتماعية للزوجة — القيم المزروعة: آنسة، متزوجة، مطلقة، متزوجة للمرة الثانية، أرملة | id, title, del | patients عبر statuesid |
wifetypes | قائمة ألقاب/تصنيفات الزوجة، وتُطبع كلقب قبل الاسم في الروشتة | id, title, del | patients عبر wiftypeid |
husbandtypes | قائمة ألقاب/تصنيفات الزوج، وتُطبع كلقب قبل الاسم في روشتة الزوج | id, title, del | patients عبر husbandtypeid |
complaint | قائمة الشكاوى الرئيسية المستخدمة في شيتات أمراض النساء والعقم (gyna / gynasheet / infertilitysheet / ancsheet00) | id, name, conditions (علم حذف منطقي) | تُقرأ من شيتات gyna وinfertility (ربط بالقيمة المختارة) |
complaintant | قائمة الشكاوى الخاصة بزيارات متابعة الحمل (antenatal) — نسخة موازية لجدول complaint | id, name, conditions | تُقرأ من antenalvisit وcompletereport |
locations | قائمة أماكن (اسم + حذف منطقي) لا يوجد لها أي استخدام في الكنترولرات الحالية — جدول مهجور (استنتاج) | id, name, deleted | لا توجد علاقات مستخدمة |
سير العمل (Workflow)
- يفتح موظف الاستقبال شاشة التسجيل
patients.php?ac=index؛ يبحث النظام عن مسودة غير معتمدة (done=0) لنفس المستخدم فيستكملها، أو ينشئ سجلًا جديدًا فورًا في قاعدة البيانات برقم ملف تلقائيstatusno. - عند إدخال الرقم القومي يتحقق النظام من صحته بتعبير نمطي ويستخرج منه تاريخ الميلاد ويحسب العمر تلقائيًا؛ كما تُجرى فحوص تكرار فورية (الاسم، رقم الملف، الرقم القومي، الهاتف) عبر AJAX.
- تُحفظ الحقول حقلًا بحقل عبر AJAX (
updateajax) أثناء الإدخال، وتُملأ القوائم المنسدلة من جداول الترميز (الألقاب، التعليم، الوظائف، الحالة، فصائل الدم) مع إمكانية إضافة قيم جديدة لهذه القوائم من نفس الشاشة. - عند الضغط على "إنهاء" (
addfinish) يُعتمد السجل (done=1) وتُسجَّل بيانات الزوجة والزوج كاملة وتُشفَّر كلمة مرور المريضة، وإذا طُلبت زيارة تُنشأ في جدولvisits(نوع الكشف، نقدي/فيزا، خصم، ترتيب الدخول) داخل معاملة واحدة، ثم يُحوَّل المستخدم لشاشة تاريخ المريضة أو شاشة الاستقبال حسب صلاحيته. - تُزامَن بيانات المريضة تلقائيًا كعميل في قاعدة ERP الخارجية (إضافة أو تحديث عبر
curlAddClient/curlUpdateClient) إذا كانت قاعدة ERP معرّفة في الإعدادات. - البحث عن مريضة قائمة من شاشة البحث متعدد المعايير؛ النتائج محدودة بـ60 سجلًا، ويوجّه الرابط لآخر شاشة إكلينيكية زارتها المريضة من جدول
lastvisit، وفي وضع المستشفى يُبحث بالقسم عبرvisits.detectionidمع استبعاد من انتهت متابعتهم فيendvisitreports. - في كل شاشة إكلينيكية يُعرض شريط بيانات المريضة (
_patientdata.php) الذي يفك ترميز القوائم ويحسب الأعمار ومدة الزواج والصيغة التوليدية (P/CS/AB/Ectopic/VM/SVD) منphobstetric+ الأرصدة الافتتاحية، ويعرض ملخصات التاريخ الطبي والجراحي والنسائي والعائلي — وينشئ تلقائيًا سجل فحصexaminationفارغًا إن لم يوجد. - من شاشة السجل الطبي (
record.php) يضيف الطبيب صفوف تشخيص/علاج بالتاريخ، ويكتب روشتات للزوجة أو الزوج من كتالوج الأدوية (recorddrugs/drugs) ويطبعها بلقب واسم المريض من جداول الألقاب. - تُرفع ملفات وصور المريضة إلى مجلد
upload/patientfiles/{id}عبر إضافة الرفع المتعدد، وتُعرض وتُحمَّل من نظام الملفات مباشرة. - أثناء متابعة الحمل تُسجَّل بيانات حجز الولادة في صفوف
registerationالمرتبطة بشيتancsheet(المكان، المنشأ، النوع، التكلفة) وتُقرأ لاحقًا في تقارير الولادات. - عند انتهاء فترة العلاج/المتابعة يُسجَّل تقرير إنهاء في
endvisitreports، ويمكن حذف المريضة حذفًا منطقيًا (deleted=1) مع حذف العميل المقابل في ERP.
الارتباط بالموديولات الأخرى
- الزيارات والاستقبال (visits):
visits.patientid → patients.id؛ كما يُنشئ هذا الموديول زيارة الكشف الأولى بقيمها المالية، ويستخدمlastvisit.patientidوendvisitreports.patientid. - التاريخ المرضي (patient history): جداول
phmenstrual / phcontraception / phobstetric / phpastmedical / phpastsurgical / phpastgynecological / phpastart / phfamilyكلها عبرpatientidوتُعرض ملخصاتها في شريط بيانات المريضة. - الفحص الإكلينيكي (examination):
examination.patientid → patients.id— يُنشأ سجل فحص تلقائيًا من_patientdata.php. - الشيتات الإكلينيكية:
ancsheet / gynasheet / infertilitysheet / ivfsheetعبرpatientid، وجدولregisteration.ancsheetid → ancsheet.idيربط التسجيل بمتابعة الحمل، وتقارير الولادات (Deliveries.php) تقرأregisteration + origin. - زيارات المتابعة: قوائم الشكاوى
complaint(gyna/infertility) وcomplaintant(antenatal) تُستهلك فيantenalvisit.phpوgyna.phpوتقاريرcompletereport.php. - كتالوج الأدوية (drugs): روشتات السجل الطبي عبر
recorddrugs.drugid → drugs.idوrecorddrugs.patientid → patients.id. - درجات الخطورة:
patients.risktype → risktype.id(كنترولرrisktype.php). - المستخدمون والأطباء:
patients.userid / patients.doctorid → awusers.user_id، والأطباء هم المستخدمون ذووrole_id = 4. - صور الجهاز التناسلي:
gtimage.patientid → patients.idمع تفاصيل التعليقات فيgtdetail.gtid. - نظام ERP الخارجي:
client.obygyPatientId → patients.idفي قاعدة بيانات ERP منفصلة، بمزامنة عبر cURL (إضافة/تحديث/حذف عميل + فاتورة كشف).
ملاحظات فنية
- لا توجد مفاتيح أجنبية معلنة إطلاقًا؛ كل العلاقات ضمنية بأسماء الأعمدة، والفهرس الوحيد غير الأساسي على
patientsهوstatusno— أداء البحث بـLIKE '%..%'سيتدهور مع نمو البيانات. - ثغرات حقن SQL: استعلام البحث في
patients.php?ac=searchيبني الشروط بدمج نصوص مباشرة، و_patientdata.phpيُمررpatientidمن الـGET مباشرة في الاستعلام. - أخطاء إملائية متجذرة في أسماء الأعمدة يجب توحيدها عند الترحيل:
husdandname،wiftypeid،mirragefrom،spacialnotes،registeration،coast(المقصود cost). - معرّفات القوائم مخزنة في أعمدة
varchar(مثلwifeeducation،husbandjob،husbandbl) بينما نظيرتها للزوجةint— عدم اتساق في الأنواع، وخلط ترميزاتlatin1 / utf8mb4بين الجداول أدى لتلف عرض القيم العربية المزروعة. - ازدواجية البيانات: العمر (
wifeage) وتاريخ الميلاد يُخزنان معًا، ومدة الزواج تُخزن كنصmirragefromوكتاريخ محسوب عكسيًاmirragefromdate. - توليد رقم الملف بـ
MAX(statusno)+1بدون قفل — احتمال تضارب أرقام عند التسجيل المتزامن. - نمط "المسودة" ينشئ سجلات مرضى فارغة فعليًا في قاعدة البيانات قبل اكتمال الإدخال، وشريط بيانات المريضة يُنشئ سجل
examinationعند مجرد العرض (كتابة أثناء القراءة) — مصدر سجلات يتيمة. - جداول ميتة:
patients_tmpوlocationsبلا أي استخدام، وpatientfilesموجود لكن الملفات تُدار من نظام الملفات مباشرة بمسح المجلد، وpatients_updates(سجل التدقيق) لا يكتب فيه الكود الحالي. - جدولا
complaintوcomplaintantمتطابقان بنيويًا (تكرار لنفس المفهوم بسياقين). - تكامل ERP منفّذ بفتح اتصال مباشر بقاعدة بيانات ثانية + استدعاءات cURL متزامنة داخل دورة الحفظ — نقطة فشل وأداء حرجة.
- كلمات مرور المرضى مشفرة بـ
password_hash(جيد)، لكنها مخزنة داخل جدول البيانات الديموغرافية نفسه.
توصيات النقل إلى ERP
- إنشاء موديل
Patientرئيسي (جدولpatients) يقتصر على بيانات المريضة، وفصل بيانات الزوج في جدول/موديلSpouse(علاقة 1-1) بدلًا من 20+ عمودًا مزدوجًا في سجل واحد — مع الإبقاء على إمكانية الدمج في واجهة العرض. - توحيد قوائم الترميز: دمج
wifejobs + husbandjobsفي جدولjob_titles، وwifetypes + husbandtypesفيperson_titles، والإبقاء علىeducation_levels،blood_types(يفضَّل Enum)،marital_statuses— كلها بمفاتيح أجنبية حقيقية وأعمدةdeleted_at(SoftDeletes). - دمج
complaint + complaintantفي جدول واحدcomplaintsبعمود سياق (context: gyna | antenatal | infertility). - إسقاط الجداول الميتة نهائيًا:
patients_tmp،locations، والاستغناء عنpatientfilesلصالح إدارة مرفقات حقيقية (Spatie MediaLibrary أو جدولpatient_attachmentsمع ترحيل الملفات الموجودة على القرص). - استبدال
patients_updatesبحزمة تدقيق قياسية مثلowen-it/laravel-auditingلتسجيل كل تعديلات سجل المريض تلقائيًا. - إنشاء موديل
MedicalRecord(جدولrecords) مرتبطًا بـPatientوPrescription، وموديلDeliveryRegistration(جدولregisterationبعد تصحيح الاسم) بمفتاحين أجنبيين إلىanc_sheetsوoriginsوتحويلcoastإلىcost decimal. - تنقية البيانات عند الترحيل: تحويل الأعمدة النصية الحاملة لمعرّفات إلى
foreignId، توحيد التواريخ (إلغاء0000-00-00لصالحNULL)، حذف عمود العمر المخزن والاكتفاء بـ Accessor محسوب من تاريخ الميلاد، وتحويل أعمدة الصيغة التوليدية الافتتاحية (pno/ab/ectopic/vmodel/svd/cs) إلى أعداد صحيحة في جدولobstetric_baselines. - توليد رقم الملف عبر تسلسل آمن (قيد فريد + معاملة) بدل
MAX+1، وجعل الرقم القومي فريدًا مع خدمة تحقق مستقلة لاستخراج تاريخ الميلاد. - نقل حساب الزوجة/المريضة (كلمة المرور) إلى جدول مستخدمين منفصل أو Guard مستقل في Laravel بدل تخزينها في جدول الديموغرافيا.
- استبدال مزامنة cURL المتزامنة مع ERP بأحداث (Events) و Jobs في طوابير Laravel، أو إلغاؤها كليًا بما أن الوجهة هي نفس منظومة ERP المستهدفة (يصبح المريض هو العميل مباشرة عبر
patient_id). - بناء البحث على فهارس حقيقية (full-text أو Laravel Scout) بدلًا من
LIKEعلى أعمدة غير مفهرسة، مع واجهة Angular بنفس معايير البحث الحالية للحفاظ على عادات المستخدمين.
الزيارات والمواعيد (Visits & Appointments)
يُعد هذا الموديول العمود الفقري التشغيلي للعيادة؛ فهو يدير حجز الزيارات من الاستقبال ومن تطبيق الموبايل، وتنظيم طابور الانتظار اليومي للطبيب، وتقسيم اليوم إلى فترات زمنية بسعة محددة، كما يسجل في الجدول ذاته الحركة المالية للزيارة (قيمة الكشف نقدًا/فيزا، الخصم، المتبقي، سداد المتبقي، المرتجعات، الأقساط)، ويوجّه الطبيب تلقائيًا إلى آخر شيت إكلينيكي فتحه للمريضة، وينتهي بتقرير إنهاء العلاج.
الوظائف الرئيسية
- حجز زيارة جديدة من شاشة الاستقبال مع اختيار نوع الكشف (
detections) وتحديد القيمة نقدًا/فيزا والخصم والمتبقي كدين على المريضة. - حجز الزيارات من تطبيق الموبايل عبر
mobileservices.phpمع حد أقصى مُثبّت بالكود (10 زيارات تطبيق يوميًا) ومنع تكرار حجز نفس المريضة في نفس اليوم. - إدارة فترات الزيارة اليومية (
visit_periods) باسم الفترة وتوقيتها وحد أقصى لعدد المرضى لكل فترة، مع التحقق من السعة قبل الحجز (patPerPeriod). - طابور الانتظار اليومي في الشاشة الرئيسية: وضع "مستشفى" يفصل المنتظرين (
view=0) عن الداخلين (view=1)، ووضع "عيادة" يعرض زيارات اليوم مرتبة بترتيب الطابور والوقت التقريبي، مع إعادة ترتيب الطابور بالسحب (sortable). - عرض زيارات أمس مع زيارات اليوم خلال ساعات العمل الممتدة بعد منتصف الليل (إعداد
addshoursفيprogramesetting). - قائمة انتظار للحالات العاجلة المستقبلية (
urgent=1) مع إمكانية ترحيلها إلى اليوم أو إلغائها. - المعاملات المالية داخل جدول الزيارات نفسه: سداد متبقٍ (
detectionid=999)، مرتجع عملاء (detectionid=9999)، دفع قسط من رصيد المريضة (detectionid=-99) المرتبط بجدولtotalbalance. - مزامنة فورية مع نظام ERP خارجي عبر cURL: إنشاء/تعديل/حذف فاتورة بيع لكل زيارة مدفوعة، وتسجيل أنواع الكشف كمنتجات خدمية.
- توجيه الطبيب تلقائيًا من الطابور إلى آخر شيت إكلينيكي فتحه للمريضة (متابعة حمل، نساء، عقم، حقن صناعي) عبر جدول
lastvisit. - تسجيل زيارات المتابعة داخل شيت العقم (
newvisit) بتاريخ آخر دورة ووزن الجسم وحالة الرحم والمبايض والعلاج. - إنهاء فترة العلاج بتقرير نهاية زيارات (
endvisitreports) بالسبب والتاريخ والطبيب، مع إمكانية الإغلاق الجماعي لقسم كامل. - بحث في الزيارات باسم الزوجة أو الزوج أو فترة زمنية، وبحث سريع برقم ملف المريضة (
statusno).
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
visits | الجدول المركزي: الزيارة/الموعد + الحركة المالية المرتبطة بها (كشف، سداد متبقٍ، مرتجع، قسط) | patientid, visitdate, visittime, detectionid, totaldetectionvalue, discount, detectionvalue_cash, detectionvalue_visa, restdetectionvalue, visitorder, enterordered, view, visit_period, urgent, payedflag, mobileappvisit, approx_time, visitid, user_id, end, enddate, branch_id | patients عبر patientid، detections عبر detectionid، visit_periods عبر visit_period، awusers عبر user_id وenddoctorid، الزيارة الأصلية ذاتيًا عبر visitid |
visits_updates | نسخة ظل من جدول الزيارات بحقول تدقيق إضافية لتتبع التعديلات (غير مستخدم في أي كود تم العثور عليه — مهجور أو محجوز) (استنتاج) | نفس حقول visits + userid_edit, date_edit, patientid_edit, clinic_id | patients عبر patientid، awusers عبر userid_edit (استنتاج) |
visit_periods | تعريف فترات اليوم (صباحية/مسائية...) بسعة قصوى لكل فترة | name, timing, max_no, deleted | visits عبر visit_period |
newvisit | زيارات المتابعة الإكلينيكية داخل شيت العقم (تاريخ، آخر دورة، وزن، رحم، مبايض، علاج) | infertilitysheetid, newvisitcycles, date, lmp, bw, ut, ov, ttt | infertilitysheet عبر infertilitysheetid، newvisitcycles عبر newvisitcycles |
newvisitcycles | قاموس أنواع الدورات/السيكلات لزيارات متابعة العقم (لا توجد بيانات مزروعة في النسخة الاحتياطية) | title, del | newvisit عبر newvisitcycles، وكذلك newvisitg في شيت النساء |
lastvisit | مؤشر لكل مريضة يخزن اسم آخر كنترولر شيت إكلينيكي فُتح لها، لتوجيه الطبيب من الطابور مباشرة إلى الشيت الصحيح | patientid, control | patients عبر patientid؛ قيمة control تشير إلى كنترولر (antenalvisit / ancsheet / gynasheet / iui / infertilitysheet) |
old_visits | أرشيف للبنية القديمة لجدول الزيارات (قيمة كشف واحدة قبل فصل النقدي/الفيزا)، استُخدم مرة واحدة في سكربت ترحيل fixOldVisits() | patientid, visitdate, detectionid, detectionvalue, visitorder, enterordered, end, enddate | patients عبر patientid، detections عبر detectionid، يطابق visits.id بنفس id (استنتاج من سكربت الترحيل) |
endvisitreports | تقرير إنهاء فترة العلاج للمريضة (السبب، التاريخ، الملاحظات، الطبيب) | patientid, reason, enddate, notes, doctorid, status | patients عبر patientid، awusers عبر doctorid |
vacations | أيام إجازات العيادة بتاريخ وسبب وحقول تدقيق بنمط Laravel (غير مستخدم في أي كود تم العثور عليه) (استنتاج) | vacation_date, vacation_reason, created_at, updated_at, created_by, updated_by | awusers عبر created_by وupdated_by (استنتاج) |
سير العمل (Workflow)
- يبحث موظف الاستقبال عن المريضة برقم الملف (
statusno) أو بالاسم (بحث تلقائي بالإكمال)، ثم يفتح شاشة إضافة زيارة (visits.php?ac=index). - يختار نوع الكشف من قاموس
detections(الذي يحمل السعر)، ويحدد التاريخ والفترة الزمنية والقيمة المدفوعة نقدًا/فيزا والخصم والمتبقي والملاحظات والوقت التقريبي، ثم تُحفظ الزيارة بـpayedflag=1ويُحتسب ترتيب الدخولenterorderedتلقائيًا. - عند تفعيل نظام الفترات (
programesetting.visit_period=1) يتحقق النظام من عدد المحجوزين في الفترة مقابلmax_noقبل الحجز. - بديلًا، تحجز المريضة من تطبيق الموبايل (
mobileservices.php?ac=addVisit) فتُسجَّل الزيارة بـmobileappvisit=1وpayedflag=0، وعند الحضور والدفع يستدعي الاستقبالpayvisitفيتحول العلم إلى مدفوع وتُنشأ فاتورة بيع في الـ ERP الخارجي. - كل زيارة مدفوعة تُرسل فورًا عبر cURL إلى نظام ERP خارجي (
sellbillController.php?do=addObgyVisit) لإنشاء فاتورة بيع مرتبطة بالزيارة، ويُحدَّث/يُحذف معها عند تعديل أو حذف الزيارة. - تظهر زيارات اليوم في الشاشة الرئيسية (
index.php) كطابور انتظار؛ في وضع المستشفى ينقسم الطابور إلى منتظرين وداخلين، ويضغط المستخدم "دخول" فتُعلَّم الزيارةview=1وتنتقل لقائمة الداخلين، مع إمكانية إعادة الترتيب بالسحب. - من الطابور ينتقل الطبيب إلى الشيت الإكلينيكي؛ ويستخدم النظام جدول
lastvisitلمعرفة آخر شيت فُتح للمريضة (متابعة حمل/نساء/عقم/حقن مجهري) فيوجهها مباشرة، ويُحدَّث هذا السجل تلقائيًا عند فتح أي شيت. - داخل شيت العقم يضيف الطبيب صفوف زيارات متابعة (
newvisit) عبر حفظ خلوي فوري بالأجاكس، مع اختيار نوع السيكل من قاموسnewvisitcycles. - المعاملات المالية اللاحقة تُسجَّل كصفوف جديدة في
visitsمرتبطة بالزيارة الأصلية عبرvisitid: سداد متبقٍ (detectionid=999) أو مرتجع (detectionid=9999) بعد التحقق من أن المرتجع لا يتجاوز المدفوع، أو دفع قسط (detectionid=-99) يخصم من رصيدtotalbalance. - عند انتهاء خطة العلاج يُنشأ تقرير إنهاء (
endvisitreports) بالسبب والتاريخ واسم الطبيب من شاشة المريضة، أو إغلاق جماعي لكل مرضى قسم معين عبرemptydeptvisit. - الزيارات المستقبلية العاجلة (
urgent=1) تظهر في قائمة الانتظار (waitingList) ليُقرَّر ترحيلها إلى اليوم أو إلغاؤها.
الارتباط بالموديولات الأخرى
- موديول المرضى:
visits.patientidوlastvisit.patientidوendvisitreports.patientid→patients.id، والبحث برقم الملفpatients.statusno. - قاموس أنواع الكشف/الخدمات:
visits.detectionid→detections.id(الاسم والسعرdetectionval)، وتُدار شاشات إضافته من نفس كنترولر الزيارات. - الشيتات الإكلينيكية:
newvisit.infertilitysheetid→infertilitysheet.id، وقيمةlastvisit.controlتشير إلى كنترولرات الشيتات (antenalvisit، ancsheet، gynasheet، iui، infertilitysheet). - قاموس السيكلات المشترك:
newvisit.newvisitcyclesوnewvisitg.newvisitcycles(شيت النساء) →newvisitcycles.id. - المستخدمون والصلاحيات:
visits.user_idوendvisitreports.doctorid→awusers.user_id، وأزرار التعديل/الحذف محكومة بجدولawrolebtn. - الحسابات: أقساط
detectionid=-99تُخصم من جدولtotalbalanceعبرpatientid. - الإعدادات:
programesettingيتحكم في وضع العرض (visitsformمستشفى/عيادة)، وتفعيل الفترات (visit_period)، والساعات الإضافية (addshours)، واسم قاعدة الـ ERP (erpdb). - نظام ERP خارجي (قاعدة بيانات منفصلة):
sellbill.obygyVisitId→visits.id، وproduct.obygyDetectionId→detections.id، وclient.obygyPatientId→patients.idعبر استدعاءات cURL. - تطبيق الموبايل: حجز وتعديل وحذف الزيارات عبر
mobileservices.phpمع العلمmobileappvisit.
ملاحظات فنية
- جدول
visitsيخلط بين مفهومين: الموعد/الزيارة والمعاملة المالية (إيصال)، باستخدام قيم سحرية فيdetectionid(-99 قسط، 999 سداد متبقٍ، 9999 مرتجع) وربط ذاتي عبرvisitid— منطق مُثبّت بالكود يصعب صيانته. - لا توجد مفاتيح أجنبية معلنة إطلاقًا؛ جميع العلاقات ضمنية عبر أسماء الأعمدة واستعلامات JOIN.
- جدولا
visits_updatesوvacationsغير مستخدمين في أي كنترولر أو واجهة تم فحصها (موجودان في المخطط فقط) — على الأرجح بقايا تطوير غير مكتمل (استنتاج). old_visitsجدول ترحيل قديم، وسكربتfixOldVisits()الخاص بترحيله ما زال موجودًا في كود الإنتاج ويمكن استدعاؤه من المتصفح.- ثغرات حقن SQL واضحة: دوال البحث (
search,getnames,emptydeptvisit) تبني الاستعلامات بدمج نصي مباشر لمدخلات المستخدم. - دوال أجاكس عامة (
updateAjax,addNewRow,editselect) تستقبل اسم الجدول والعمود من العميل مباشرة — مخاطرة أمنية وبنيوية كبيرة. - حقول
newvisitكلها نصوصvarchar(191)حتى التواريخ والأوزان؛ ولا توجد بيانات مزروعة لقواميسvisit_periodsوnewvisitcyclesفي النسخة الاحتياطية. - حد حجوزات الموبايل (10 يوميًا) وقيم كثيرة أخرى مُثبّتة بالكود وليست إعدادات.
- الحذف منطقي بأعلام غير موحدة (
deletedفي الزيارات مقابلdelفي القواميس)، مع وجود حذف فعلي في دالةdelv. - تكرار في حقول الترتيب (
visitorder,visit_order,enterordered) داخل نفس الجدول.
توصيات النقل إلى ERP
- فصل جدول
visitsإلى ثلاثة نماذج Laravel:Appointment(الحجز: المريضة، الخدمة، التاريخ، الفترة، الحالة، المصدر، عاجل)، وEncounter(الدخول الفعلي وترتيب الطابور)، وPaymentTransaction(نوع المعاملة كـ enum: كشف/سداد متبقٍ/مرتجع/قسط بدلًا من القيم السحرية، معappointment_idبدل الربط الذاتيvisitid). - إنشاء نموذج
VisitPeriod(أوAppointmentSlot) من جدولvisit_periodsمع قيد سعةmax_noيُفحص بمعاملة قاعدة بيانات، وربطه بنموذجClinicClosureالمبني على جدولvacationsلمنع الحجز في الإجازات. - استبدال جدول
lastvisitبمنطق اشتقاقي (آخر شيت إكلينيكي بحسب تاريخ الإنشاء) أو عمودlast_sheet_typeعلى المريضة — لا حاجة لجدول مستقل. - نقل
newvisitوnewvisitcyclesإلى موديول العقم الإكلينيكي كنموذجيInfertilityFollowUpوCycleType، مع تحويل الحقول النصية إلى أنواع صحيحة (تاريخ، رقم عشري) وتوحيد القاموس المشترك مع شيت النساء. - تحويل
endvisitreportsإلى نموذجTreatmentClosureمرتبط بالمريضة والطبيب، أو دمجه كحالة (status) على مفهوم "حلقة علاجية" (Episode of Care) إن اعتُمد. - إسقاط جدولي
old_visitsوvisits_updatesبعد أرشفة بياناتهما، والاستعاضة عن التدقيق بحزمة Laravel Auditing أو جدولactivity_logموحد. - اعتماد مفاتيح أجنبية حقيقية وقيود NOT NULL، وتوحيد الحذف المنطقي عبر
SoftDeletes، ونقل الإعدادات المثبتة بالكود (حد الموبايل، الساعات الإضافية) إلى جدول إعدادات. - استبدال تكامل cURL مع الـ ERP بمعاملات داخلية مباشرة (الفوترة جزء من نفس النظام الجديد) أو بطبقة Events/Jobs غير متزامنة مع ضمان عدم فقد الفواتير.
- بناء واجهات Angular: شاشة حجز بتقويم وفترات وسعات، وشاشة طابور لحظية (WebSockets/Polling) بدل إعادة تحميل القوائم، ونقطة نهاية REST موثقة لتطبيق الموبايل بدل
mobileservices.phpالمفتوح بلا تحقق من الهوية.
متابعة الحمل (ANC) (Antenatal Care)
موديول متابعة الحمل هو المسؤول عن إدارة ملف الحمل الكامل للمريضة: حساب ميعاد الولادة المتوقع (EDD) من تاريخ آخر دورة (LMP)، تسجيل زيارات المتابعة الدورية (الوزن، الضغط، عمر الحمل بالأسابيع)، أشعة الموجات فوق الصوتية للحمل، صرف الأدوية وطلب التحاليل لكل زيارة، تسجيل تاريخ فقدان الحمل السابق (EPC)، وتقارير الولادات المتوقعة وحالات الخطورة. يحتوي النظام الحالي على مسارين متوازيين ومكررين لنفس الوظيفة: مسار "ANC Sheet" ومسار "Antenatal Visit".
الوظائف الرئيسية
- إنشاء ملف حمل تلقائيًا للمريضة عند فتح شاشة المتابعة (
ancsheetبحالةendpreg=0أوmainantenentalبحالةdone=0) بحيث يوجد حمل نشط واحد فقط لكل مريضة. - حساب ميعاد الولادة المتوقع تلقائيًا بقاعدة نيجيلي (LMP + 9 أشهر + 7 أيام) في الاتجاهين: إدخال LMP يحسب EDD والعكس، مع حساب تاريخ مرجعي للحقن المجهري (
ivf= LMP + 9 أشهر − 7 أيام). - حساب عمر الحمل تلقائيًا (أسابيع + أيام) لكل زيارة متابعة وكل أشعة بناءً على فرق التاريخ عن LMP.
- تسجيل زيارات المتابعة: التاريخ، وزن الأم، ضغط الدم، النبض، الشكوى، التشخيص (قوائم متعددة من
diagnosisantوcomplaintant)، الملاحظات والخطة العلاجية. - تسجيل نتائج الموجات فوق الصوتية للحمل (
mainantenentalus): GA، GS، CRL، FHR، BPD، FL، موضع المشيمة، السائل الأمنيوسي، الوزن المتوقع للجنين. - متابعة فحوصات الأشعة المرحلية في ملف ANC: فحص T-scan (الثلث الأول) وفحص TT-scan (مسح التشوهات) بتاريخ وأسبوع ونتيجة وتقرير لكل منهما.
- الحجز التلقائي في قائمة انتظار أشعة 4D (
op_4d_list) بمجرد إدخال EDD، وتحديث حالتها (t11/t21) عند تسجيل تواريخ T-scan وTT-scan. - كتابة روشتات أدوية لكل زيارة بتاريخ معين (للزوجة أو الزوج) مع طباعتها، من كتالوج الأدوية المركزي.
- طلب تحاليل واستقصاءات من كتالوج التحاليل المصنف (
investcats/invests) مع تسجيل النتائج وطباعة الطلبات. - تسجيل تاريخ فقدان الحمل السابق EPC (إجهاض مبكر EPL، إجهاض الثلث الأول/الثاني، حمل عنقودي كامل/جزئي، حمل خارج الرحم) مع طريقة العلاج (تحفظي/دوائي/جراحي) والطبيب المعالج ونتيجة الباثولوجي.
- إنهاء الحمل وأرشفته مع أخذ لقطة من بيانات G/P/EPC وقت الإنهاء، وتصفح أرشيف الأحمال السابقة لكل مريضة.
- حساب عدد مرات الحمل (Gravida) تلقائيًا من سجل الولادات والإجهاضات السابقة (
phobstetric+ عدادات جدول المرضى). - تقارير: الولادات المتوقعة اليوم أو في فترة (
eddوexpected)، حالات EPC بالتاريخ (epc)، المرضى حسب نوع الخطورة (risktype)، والحالات حسب نوع إنهاء الحمل (termination). - إضافة قيم جديدة لقوائم الاختيار (المشيمة، أنواع EPC، أطباء الولادة...) ديناميكيًا من داخل الشاشة دون شاشة إعدادات منفصلة.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
ancsheet | ملف الحمل الرئيسي للمريضة (مسار ANC Sheet): LMP/EDD، المشيمة، فحوصات T/TT-scan، لقطة G/P/EPC عند إنهاء الحمل | patientid, endpreg, sheetlmp, sheetedd, placenta, tscandate, ttscandate, obstgn, obstpn, obstepc, 4d_list_id | patients عبر patientid، op_4d_list عبر 4d_list_id |
ancnewvisit | زيارة متابعة داخل ملف ANC: التاريخ، عمر الحمل، الوزن، الضغط، بيانات أشعة مختصرة، الخطة | ancsheetid, newvisitdate, newvisitw, newvisitbw, newvisitbp, usn, usplace, usaf, usefw, usbiom, plan | ancsheet عبر ancsheetid |
ancsheetdrugs | أدوية/روشتات مرتبطة بملف ANC بتاريخ معين، للزوجة أو الزوج | patientid, ancsheetid, date, drugid, drugname, drugdos, forhusband, doctorid, recepittmpid, deleted | ancsheet عبر ancsheetid، drugs عبر drugid، awusers عبر doctorid |
ancsheetinvest | تحاليل واستقصاءات مطلوبة من ملف ANC مع النتيجة | patientid, ancsheetid, date, investid, investresult, forhusband, doctorid, deleted | ancsheet عبر ancsheetid، invests عبر investid |
mainantenental | ملف الحمل الرئيسي للمسار الموازي (Antenatal Visit): LMP/EDD/IVF date، عدد مرات الحمل G، الهيموجلوبين، جنس الجنين | patientid, doctorid, lmp, eed, ivf, g, done, hb, sex, sysdate | patients عبر patientid، awusers عبر doctorid |
antenalvisit | زيارة متابعة في المسار الموازي: شكوى، وزن، ضغط، نبض، تشخيصات وشكاوى متعددة (CSV) | patientid, mainantenentalid, antenaldate, complaint, wt, bp, pulse, diagnosisid, complaintid, conditions | mainantenental عبر mainantenentalid، diagnosisant/complaintant عبر قوائم CSV (استنتاج) |
mainantenentaldrugs | أدوية المسار الموازي (نسخة مكررة من ancsheetdrugs بنفس البنية) | patientid, mainantenatalid, date, drugid, drugname, drugdos, forhusband, doctorid, deleted | mainantenental عبر mainantenatalid، drugs عبر drugid |
mainantenentalinvest | تحاليل المسار الموازي (نسخة مكررة من ancsheetinvest) | patientid, mainantenatalid, date, investid, investresult, forhusband, doctorid, deleted | mainantenental عبر mainantenatalid، invests عبر investid |
mainantenentalus | سجل أشعة الموجات فوق الصوتية للحمل: قياسات الجنين والمشيمة والسائل الأمنيوسي | mainantenatalid, patientid, date, nga, gs, crl, fhr, bpd, fl, placenta, ai, fwt, doctorid | mainantenental عبر mainantenatalid، awusers عبر doctorid |
placenta | قائمة اختيار لمواضع المشيمة (ant, post high, fundal, ant low lying...) تُستخدم في حقل ancsheet.placenta | id, title, del | تُقرأ من شاشة ancsheet عبر data-celtable |
pla2cen | قائمة اختيار "مكان إجراء الحقن المجهري" تخص فعليًا موديول IVF وليس متابعة الحمل (حقل ivfsheet.pla2cen) | id, title (نوعه int خطأً), del | ivfsheet عبر pla2cen (موديول IVF) |
anprotocol | قائمة بروتوكولات التنشيط (long ag / antag / short ag) — جدول قديم؛ الكود الحالي يستخدم جدول icsiprotocol بدلًا منه | id, title, del | غير مستخدم فعليًا (استنتاج: مهجور لصالح icsiprotocol) |
antype | قائمة نوع العقم (1ry / 2ry / sex selection) — تخص موديول IVF (حقل ivfsheet.antype) | id, title, del | ivfsheet عبر antype (موديول IVF) |
antypes | قائمة نوع الدورة (fresh / frozen) — تخص موديول IVF (حقل ivfsheet.antypes) | id, title, del | ivfsheet عبر antypes (موديول IVF) |
wifeepc | سجل فقدان الحمل السابق EPC للمريضة: النوع، أسبوع الحمل، العلاج، الطبيب، الباثولوجي، التكلفة | infertilitysheetid, wifeepcdate, wifeepctype, wifeepcw, wifeepcttt, wifeepcobst, histopath, coast, wifeepcp, wifeepcepc | infertilitysheet عبر infertilitysheetid، قوائم wifeepctype/wifeepcttt/wifeepcobst |
wifeepctype | قائمة أنواع فقدان الحمل: EPL، A T1، A T2، C VM، P VM، EP (حمل خارج الرحم) | id, title, del | wifeepc عبر wifeepctype |
wifeepcttt | قائمة طرق علاج فقدان الحمل: conservative، medical (miso/MTX)، D&C، laparoscopy/laparotomy | id, title, del | wifeepc عبر wifeepcttt |
wifeepcobst | قائمة الأطباء/المراكز التي تعاملت مع حالة فقدان الحمل (أسماء أطباء بالعربية) | id, title, del | wifeepc عبر wifeepcobst |
wifeobst | قائمة الأطباء/المستشفيات التي أجرت الولادات السابقة لأطفال المريضة (اختيار متعدد) | id, title, del | awifep عبر wifeobst (قائمة CSV) |
wifemodeofd | قائمة طريقة الولادة: CS (قيصرية)، sVD، nVD (طبيعية) | id, title, del | awifep عبر wifemodeofd |
wifetypeofd | قائمة توقيت الولادة: FT (مكتملة) / PT (مبتسرة) | id, title, del | awifep عبر wifetypeofd |
سير العمل (Workflow)
- عند فتح شاشة ANC للمريضة (
ancsheet.php?ac=index) يبحث النظام عن ملف حمل نشط (endpreg=0)؛ إن لم يوجد يُنشأ تلقائيًا، ويُنشأ كذلك ملفinfertilitysheetإن لم يوجد، ويُسجل الدخول فيlastvisit. - يُدخل الطبيب تاريخ آخر دورة LMP فيحسب النظام EDD تلقائيًا (LMP + 9 أشهر + 7 أيام) عبر دالة
eedlmp()، وبمجرد وجود EDD يُضاف صف تلقائي في قائمة انتظار أشعة 4D (op_4d_list) ويُربط بالملف عبر4d_list_id. - تُسجل بيانات فحص الثلث الأول (T-scan) ومسح التشوهات (TT-scan)؛ إدخال التاريخ يُحدّث حالة الحجز في
op_4d_list(الأعمدة t11/t21). - في كل حضور يضيف الطبيب "New Visit" فيُنشأ صف
ancnewvisitبتاريخ اليوم ويحسب عمر الحمل بالأسابيع والأيام من LMP تلقائيًا، ثم تُملأ الحقول (وزن، ضغط، ملاحظات، خطة، بيانات أشعة) بحفظ فوري حقلًا بحقل عبر AJAX. - من نفس الشاشة تُكتب روشتة اليوم (
ancsheetdrugs) من كتالوج الأدوية، للزوجة أو الزوج، مع إمكانية الطباعة وعرض روشتات التواريخ السابقة وتعديلها. - تُطلب التحاليل بتحديد بنود من كتالوج التحاليل المصنف فتُحفظ دفعة واحدة في
ancsheetinvestوتُطبع، وتُسجل النتائج لاحقًا في نفس الصفوف. - تُعرض في الملف أيضًا بيانات التاريخ التوليدي من موديول العقم: الأطفال السابقون (
awifepمع قوائم طريقة/توقيت/مكان الولادة) وحالات فقدان الحمل (wifeepcمع قوائم النوع/العلاج/الطبيب)، وتُحرر من هنا مباشرة. - عند انتهاء الحمل يضغط المستخدم "End Pregnancy" فيتحول
endpreg=1وتُلتقط قيم G/P/EPC من ملف العقم وتُحفظ في الملف، ويصبح الملف أرشيفًا يُستعرض من شاشةarchive/historys. - بالتوازي، شاشة
antenalvisit.phpتدير نفس الحمل بجداول أخرى: تُنشئ/تحمّلmainantenental(مع حساب G تلقائيًا منphobstetricوعدادات المريضة)، وتسجل زياراتantenalvisitوأشعةmainantenentalusوأدوية وتحاليل خاصة بها، وتُنهى بـdone=1ويُستعرض أرشيفها برقم الحملg. - التقارير:
edd.phpيعرض من ولادتهن المتوقعة اليوم أو في مدى تاريخي منancsheet.sheetedd، وexpected.phpيعرض نفس التقرير منmainantenental.eed، وepc.phpيعرض حالات فقدان الحمل بالتاريخ، وrisktype.phpيصنف المرضى حسبpatients.risktype، وtermination.phpيعرض الحالات حسب نوع إنهاء الحمل منphobstetric.
الارتباط بالموديولات الأخرى
- موديول المرضى: كل الجداول الرئيسية ترتبط بجدول
patientsعبرpatientid، وتقرير الخطورة يقرأpatients.risktypeوpatients.risk. - موديول المستخدمين/الأطباء: حقول
doctoridفي الزيارات والأدوية والتحاليل والأشعة ترتبط بـawusers.user_id. - كتالوج الأدوية والمخزون:
ancsheetdrugs.drugidوmainantenentaldrugs.drugidيرتبطان بجدولdrugs، مع ربط بالإيصالات عبرrecepittmpid/recepitdrugid. - كتالوج التحاليل:
ancsheetinvest.investidوmainantenentalinvest.investidيرتبطان بـinvests(المصنفة فيinvestcats). - موديول العقم (Infertility):
wifeepc.infertilitysheetidيرتبط بـinfertilitysheet، وقوائمwifeobst/wifemodeofd/wifetypeofdيستهلكها جدول الأطفالawifepالتابع لملف العقم، وإنهاء الحمل ينسخ G/P/EPC من ملف العقم. - موديول العمليات/أشعة 4D:
ancsheet.4d_list_idيرتبط بـop_4d_list(حجز وتتبع فحوصات 4D). - موديول التاريخ المرضي: حساب Gravida وتقرير إنهاء الحمل يعتمدان على
phobstetricوقوائمphobstericterminate/phobstericterplace. - موديول الحجز/الاستقبال: ملف ANC يعرض حجوزات
registerationالمرتبطة بالملف عبرancsheetid، ويسجل آخر شاشة زارها المريض فيlastvisit. - موديول IVF: جداول
antypeوantypesوpla2cen(وanprotocolالمهجور) تُستخدم فعليًا منivfsheetوليس من شاشات متابعة الحمل.
ملاحظات فنية
- ازدواجية كاملة: يوجد مساران متوازيان لمتابعة الحمل (
ancsheet/ancnewvisitمقابلmainantenental/antenalvisit) بجداول أدوية وتحاليل مكررة بنفس البنية، ما يشتت بيانات الحمل الواحد بين مصدرين. ancsheet00.phpنسخة قديمة مكررة منancsheet.phpما زالت موجودة في الكود (Dead/Legacy code).- أخطاء إملائية متجذرة في المخطط:
mainantenental(الصحيح antenatal) وعمود الربط مكتوبmainantenatalidبإملاء مختلف عن اسم الجدول، وantenalvisitبدون حرف t. - التواريخ مخزنة كنصوص
varcharبصيغة Y/m/d في جداول أساسية (ancsheet,ancnewvisit,wifeepc) ما يجعل المقارنات والفرز عرضة للأخطاء، بينما جداول أخرى تستخدمdate. mainantenental.patientidمن نوعvarcharبينما باقي الجداول تستخدمintلنفس المفتاح.- لا توجد مفاتيح أجنبية معلنة إطلاقًا؛ كل العلاقات مستنتجة من أسماء الأعمدة وأكواد الكنترولر.
- أعلام الحذف غير موحدة:
delوdeletedوconditionsوendpreg/doneكلها تؤدي نفس الغرض بأسماء مختلفة. - ثغرات SQL Injection مؤكدة:
risktype.phpوtermination.phpيلصقان مدخلات POST مباشرة في جمل SQL، ودوالgetselectajax/Addتسمح للعميل بتمرير اسم الجدول والعمود (Table/Mass-assignment injection). - جداول
anprotocolوantypeوantypesوpla2cenمصنفة ضمن هذا الموديول لكنها تخص IVF؛anprotocolمهجور (الكود يستخدمicsiprotocol)، وعمودpla2cen.titleمعرف كـintخطأً، وpla2cenبلا بيانات أولية. - بيانات قوائم الاختيار ملوثة: جدول
placentaيحوي صفوف NULL وقيم نصية حرة مكررة، وقوائمwifeobst/wifeepcobstتخلط أسماء أطباء وأماكن ودول في حقل واحد. diagnosisidوcomplaintidوwifeobstتُخزن كقوائم CSV داخل عمود نصي بدلًا من جداول وسيطة.- قاعدة حساب EDD مثبتة في الكود (+9 أشهر +7 أيام) ومكررة في أكثر من كنترولر، وعمر الحمل يُعاد حسابه ويُحفظ في قاعدة البيانات عند كل عرض للصفحة (كتابة عند القراءة).
توصيات النقل إلى ERP
- توحيد المسارين في نموذج واحد: جدول
pregnancies(موديلPregnancy) يدمجancsheet+mainantenentalبحقول:patient_id,lmp,edd,gravida,status(active/ended),hb,placenta_site_id, مع ترحيل بيانات المسارين بمطابقة المريضة والتواريخ. - جدول
antenatal_visits(موديلAntenatalVisit) يدمجancnewvisit+antenalvisit:pregnancy_id,visit_date,weight,bp,pulse,notes,plan، مع جداول وسيطةantenatal_visit_diagnosisوantenatal_visit_complaintsبدل قوائم CSV، وحساب عمر الحمل كـ Accessor محسوب وليس عمودًا مخزنًا. - جدول
antenatal_ultrasounds(موديلAntenatalUltrasound) منmainantenentalusمع ضم حقول T-scan/TT-scan منancsheetكأنواع فحص (scan_type: routine / first_trimester / anomaly / 4d) بدلًا من أعمدة ثابتة. - توحيد الروشتات والتحاليل عبر النظام كله:
prescriptions/prescription_itemsوinvestigation_requests/investigation_resultsبعلاقة Polymorphic أو بـpregnancy_id، لتحل محل الجداول الأربعة المكررة (ancsheetdrugs,mainantenentaldrugs,ancsheetinvest,mainantenentalinvest). - جدول
pregnancy_losses(موديلPregnancyLoss) منwifeepcمربوط مباشرة بـpatient_idبدل المرور على ملف العقم، بحقول:loss_type_id,gestational_weeks,treatment_id,provider_id,histopathology,cost,dateمن نوعdate. - تحويل القوائم الصغيرة إلى Enums أو جداول مرجعية موحدة:
delivery_modes(CS/SVD/NVD)،delivery_terms(full_term/preterm)،pregnancy_loss_types،pregnancy_loss_treatments،placenta_sites(بعد تنقية بياناتplacenta)، ودمجwifeobst+wifeepcobstفي جدولexternal_providersواحد بحقل نوع (طبيب/مستشفى/خارجي). - نقل
antypeوantypesوpla2cenإلى موديول IVF عند ترحيله، وإسقاطanprotocolبعد التأكد من خلوه من بيانات مرتبطة (الكود يستخدمicsiprotocol). - أثناء الترحيل: تحويل كل التواريخ النصية إلى
DATEمع معالجة القيم 0000-00-00 والفارغة، توحيد الحذف الناعم علىdeleted_at(SoftDeletes)، وإضافة مفاتيح أجنبية وقيود فعلية، ونقل منطق EDD إلى Service واحد (EddCalculator) قابل للاختبار. - إعادة بناء التقارير (EDD المتوقعة، EPC، الخطورة، الإنهاء) كاستعلامات Eloquent/API endpoints محمية بـ Validation وParameter binding لإغلاق ثغرات SQL Injection الحالية.
أمراض النساء (Gynecology)
يُغطي هذا الموديول العيادة النسائية الكاملة: تسجيل زيارات المريضة (الشكوى، التشخيص، تاريخ آخر دورة)، صرف الروشتات وطلب الفحوصات للزوجة أو الزوج، سونار النساء مع قياسات الرحم والمبيضين والحويصلات، بالإضافة إلى «شيت النساء» الملخّص الذي يجمع التاريخ الحيضي والفحص الموضعي وزيارات المتابعة، وملف مبدئي لتقييم تأخر الإنجاب (Infertility) داخل شاشة النساء نفسها.
الوظائف الرئيسية
- تسجيل زيارات أمراض النساء لكل مريضة (جدول
gyna) بتاريخ الزيارة، الشكوى الحرة والشكاوى المختارة من قائمة، التشخيصات المتعددة، الملاحظات، وتاريخ آخر دورة (LMP)، مع إمكانية إضافة شكوى/تشخيص جديد للقاموس أثناء العمل. - ملاحظات وخطة علاجية عامة أعلى شاشة النساء لكل مريضة (جدول
maingyna) تُنشأ تلقائياً عند أول دخول للشاشة. - كتابة روشتات الأدوية بتاريخ اليوم للزوجة أو الزوج (
gynadrugs/gynasheetdrugs) مع اختيار متسلسل (تصنيف ← اسم ← شكل ← جرعة) من كتالوج الأدوية، وعرض الروشتات السابقة وتعديلها وطباعتها مع التشخيص الأخير اختيارياً. - طلب الفحوصات والتحاليل عبر نافذة اختيار مجمّعة حسب تصنيفات الفحوصات (
gynainvestigation/gynasheetinvest) للزوجة أو الزوج، مع طباعة طلب الفحص وتسجيل النتائج لاحقاً. - سونار النساء (
gynaus): تسجيل يوم الدورة، سُمك بطانة الرحم، قياسات المبيض الأيمن والأيسر (طول/عرض/حجم/عدد الحويصلات)، قياسات الرحم وعنق الرحم، بنموذج مبسّط أو كامل حسب إعدادات البرنامج، مع طباعة التقرير. - تفصيل الحويصلات لكل مبيض (
gynausficils): قياس اسم وطول وعرض وحجم كل حويصلة على حدة، وتحديث عدد الحويصلات في سجل السونار ضمن معاملة واحدة (Transaction). - ملف تأخر الإنجاب المختصر داخل شاشة النساء (
gynainfertility): نوع العقم ومدته وفترة المعاشرة ونتائج الهرمونات (FSH/LH/TSH/PRL/AMH) والسائل المنوي وأشعة الصبغة، مع خطط علاجية متعددة (gynainfertilityplan) وأنواع عقم قابلة للإضافة (gynainfertilitytype). - «شيت النساء» (
gynasheet): صفحة ملخّص واحدة لكل مريضة تتضمن «بيانات حرجة» (importantnote) تُعرض أعلى الشيت، والتاريخ الحيضي (انتظام/كمية/عسر الطمث من قوائمmenstrualreg،menstrualamount،menstrualdysm) والفحص الموضعي (الفرج/المهبل/عنق الرحم من قوائمlocalvulva،localvagina،localcx). - زيارات متابعة داخل الشيت (
newvisitg): التاريخ، الدورة، LMP، وزن الجسم، الرحم والمبيض، نوع الفحص بالموجات (US / TVS / 3D TVS)، الشكوى (C/O) والتشخيص من قوائم قابلة للإضافة (newvisitgco،newvisitgdiag)، وزر TTT لفتح روشتة الشيت مباشرة. - سجل فحص نسائي ضمن موديول العقم (
infertilitygyna): المهبل، الفحص، السبر (Sounding)، الملحقات (Adnexae) لكل ملف عقم. - التحرير الموضعي (inline editing) لكل الحقول عبر AJAX يحفظ كل حقل فور تعديله (id / table / column / value)، مع حذف منطقي (soft delete) للسجلات.
- تسجيل آخر شاشة دخلتها المريضة في جدول
lastvisitلتسهيل الرجوع إليها من شاشة الاستقبال. - كنترولر
ultrasoundgyna.phpيوفر سير عمل أخصائي السونار: إنشاء تقرير سونار نسائي رسمي (جدولultrasoundgynaالتابع لموديول السونار)، تعبئته ثم اعتماده بالطباعة (done=1).
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
gyna | سجل زيارة أمراض النساء: الشكوى والتشخيص والملاحظات وLMP، مع حقول ملخّص العقم (inf_*) | patientid, gynadate, complaint, complaintid (CSV), diagnosisid (CSV), diagnosistxt, notes, gynalmp, conditions, doctorid, inf_type, inf_fsh...inf_hsg, inf_note | patients عبر patientid، awusers عبر doctorid، diagnosis/complaint عبر CSV في diagnosisid/complaintid |
gynadrugs | أدوية الروشتة في شاشة النساء (للزوجة أو الزوج) بتاريخ محدد | patientid, date, drugid, drugname, drugtype, drugdos, forhusband, deleted, doctorid, recepittmpid, recepitdrugid | patients عبر patientid، drugs عبر drugid، awusers عبر doctorid |
gynainvestigation | طلبات الفحوصات من شاشة النساء ونتائجها | patientid, date, investid, investresult, forhusband, deleted, doctorid | patients عبر patientid، invests عبر investid |
gynasheet | رأس «شيت النساء»: سجل واحد لكل مريضة يحمل البيانات الحرجة | patientid, importantnote, usvsdtv | patients عبر patientid، تتبعه زيارات newvisitg |
gynasheetdrugs | أدوية روشتة «شيت النساء» (بنية مطابقة تماماً لـ gynadrugs) | patientid, date, drugid, drugname, drugtype, drugdos, forhusband, deleted, doctorid | patients عبر patientid، drugs عبر drugid |
gynasheetinvest | فحوصات «شيت النساء» (بنية مطابقة لـ gynainvestigation) | patientid, date, investid, investresult, forhusband, deleted, doctorid | patients عبر patientid، invests عبر investid |
gynaus | سونار زيارات النساء: يوم الدورة، البطانة، قياسات المبيضين والرحم وعنق الرحم وعدد الحويصلات | patientid, date, day, endo, ovrayll/lw/lv/lno/lsize, ovrayrl/rw/rv/rno/rsize, uterusl/w/v, cervixl/w/v, lfolliclesno, rfolliclesno, notes, doctorid, deleted, mainantenatalid | patients عبر patientid، awusers عبر doctorid، mainantenatal عبر mainantenatalid (استنتاج) |
gynausficils | تفاصيل قياس كل حويصلة (طول/عرض/حجم) لكل جهة في سونار معيّن | gynausid, name, length, width, volume, type (0=أيسر،1=أيمن), sysdate | gynaus عبر gynausid |
gynainfertility | ملخّص تقييم العقم: سجل واحد لكل مريضة (نوع، مدد، هرمونات، سائل منوي، HSG) | patientid, date, type, since_y/m, stay_y/m, stay_hus, abortion, semen, fsh, lh, tsh, prl, amh, hsg, note | patients عبر patientid، gynainfertilitytype عبر type |
gynainfertilityplan | سطور خطة علاج العقم المتعددة لكل مريضة | patientid, plan, itr, deleted | patients عبر patientid |
gynainfertilitytype | قاموس أنواع العقم (Primary/Secondary...) قابل للإضافة من الشاشة | name, deleted | تُشير إليه gynainfertility.type |
infertilitygyna | سجل الفحص النسائي داخل ملف موديول العقم (Vagina / Exam / Sounding / Adnexae) | infertid, date, vagina, exam, sounding, adenxae | infertility عبر infertid |
maingyna | ملاحظات وخطة عامة أعلى شاشة النساء؛ سجل واحد لكل مريضة يُنشأ تلقائياً | patientid, create_date, notes, plan | patients عبر patientid |
newvisitg | زيارات المتابعة داخل «شيت النساء» (دورة، LMP، وزن، رحم/مبيض، نوع الموجات، شكوى وتشخيص) | gynasheetid, date (varchar), newvisitcycles, lmp, bw, ut, ov, newvisitgco (CSV), newvisitgdiag (CSV), usvsdtv, noteg, plan | gynasheet عبر gynasheetid، newvisitgco/newvisitgdiag عبر CSV |
newvisitgco | قاموس شكاوى (C/O) زيارات الشيت — يضيفه المستخدم أثناء العمل | title, del | تُشير إليه newvisitg.newvisitgco (CSV) |
newvisitgdiag | قاموس تشخيصات زيارات الشيت | title, del | تُشير إليه newvisitg.newvisitgdiag (CSV) |
menstrualamount | قاموس كمية الدورة الشهرية (التاريخ الحيضي) | title, del | تُشير إليه infertilitysheet.menstrualamount |
menstrualdysm | قاموس عسر الطمث (Dysmenorrhea) | title, del | تُشير إليه infertilitysheet.menstrualdysm |
menstrualreg | قاموس انتظام الدورة الشهرية | title, del | تُشير إليه infertilitysheet.menstrualreg |
localcx | قاموس نتائج فحص عنق الرحم في الفحص الموضعي | title, del | تُشير إليه infertilitysheet.localcx (CSV) |
localvagina | قاموس نتائج فحص المهبل في الفحص الموضعي | title, del | تُشير إليه infertilitysheet.localvagina (CSV) |
localvulva | قاموس نتائج فحص الفرج في الفحص الموضعي | title, del | تُشير إليه infertilitysheet.localvulva (CSV) |
سير العمل (Workflow)
- يفتح الطبيب شاشة «Gyna» للمريضة (
gyna.php?patientid=) فيُسجَّل الدخول فيlastvisitويُنشأ تلقائياً سجلmaingyna(ملاحظات/خطة) إن لم يوجد، وتُعرض كل الزيارات السابقة مرتبة تنازلياً. - يضيف الطبيب زيارة جديدة (AJAX
newrow) فتُنشأ صفّاً فارغاً بتاريخ اليوم فيgyna، ثم يُحرَّر كل حقل (الشكوى، التشخيصات المتعددة، LMP، الملاحظات) فورياً عبرupdateالذي يحفظ عموداً واحداً في كل نداء. - تُختار الشكاوى والتشخيصات من قاموسَي
complaintوdiagnosisالمشتركَين وتُخزَّن كسلسلة معرّفات مفصولة بفواصل؛ ويمكن إضافة مصطلح جديد للقاموس مباشرة (adddiagnosis). - للروشتة: يفتح الطبيب نافذة الأدوية فتُنشأ صفوف
gynadrugsبتاريخ اليوم (للزوجةforhusband=0أو الزوجforhusband=1) ويختار الدواء بتسلسل تصنيف/اسم/شكل/جرعة، ثم يطبع الروشتة (مع التشخيص الأخير إذا فُعّلprint_diagفي الإعدادات). - للفحوصات: نافذة Checkbox مجمّعة حسب
investcatsتحفظ صفوفgynainvestigationوتطبع طلب الفحص؛ وتُسجَّل النتائج لاحقاً فيinvestresult. - للسونار: زر إضافة يُنشئ صفّاً في
gynaus(نموذج مبسّط أو كامل حسبprogramesetting.ultrasound)، وتفتح نافذة الحويصلات لكل مبيض لتحفظ القياسات فيgynausficilsوتحدّثlfolliclesno/rfolliclesnoداخل معاملة واحدة، مع إمكانية طباعة تقارير سونار مختارة. - نافذة العقم (
getInfdata): تُنشأ تلقائياً سجلgynainfertilityوسطر خطةgynainfertilityplanإن لم يوجدا، وتُعبّأ بيانات النوع والمدد والهرمونات، مع إضافة أنواع جديدة إلىgynainfertilitytype. - شاشة «شيت النساء» (
gynasheet.php): تُنشأ تلقائياً سجلاgynasheetوinfertilitysheetللمريضة؛ يدوَّن التاريخ الحيضي والفحص الموضعي عبر قوائم منسدلة تُحفظ في أعمدةinfertilitysheet، وتُضاف زيارات متابعةnewvisitg(إجراءappend) بشكواها وتشخيصها وروشتتها (gynasheetdrugs) وفحوصاتها (gynasheetinvest). - القوائم المنسدلة (الحيضية والموضعية وC/O والتشخيص) قابلة للإثراء أثناء العمل:
getselectajaxيضيف عنواناً جديداً للجدول المرجعي، وgetdataselect/deldataselectيديران حذف القيم منطقياً. gynasheet00.phpنسخة قديمة بديلة تعرض الشيت مدموجاً مع زياراتgynaوسونارgynausفي صفحة واحدة (منطق مكرر).- في موديول العقم، عند إنشاء ملف
infertilityتُنشأ معه تلقائياً صفوف فحص نسائيinfertilitygynaضمن مجموعة جداول الملف، وتُحرَّر حقولها (Vagina/Exam/Sounding/Adnexae) موضعياً. - أخصائي السونار يستخدم
ultrasoundgyna.phpلإنشاء تقرير سونار نسائي رسمي مسوّدة (done=0) ثم اعتماده بالطباعة (done=1) — في جدولultrasoundgynaالتابع لموديول السونار.
الارتباط بالموديولات الأخرى
- المرضى (Patients): كل الجداول التشغيلية تقريباً ترتبط بـ
patientsعبرpatientid، وتُقرأ أسماء الزوجة/الزوج وألقابهما (wifetypes/husbandtypes) للطباعة. - المستخدمون/الأطباء:
doctoridفي gyna وgynadrugs وgynainvestigation وgynaus يشير إلىawusers.user_id، وقائمة أخصائيي السونار تُجلب بشرطpositionid = 4. - كتالوج الأدوية:
gynadrugs.drugidوgynasheetdrugs.drugidيشيران إلىdrugs.idمع نسخ اسم الدواء denormalized. - كتالوج الفحوصات:
gynainvestigation.investidوgynasheetinvest.investidيشيران إلىinvests.idالمجمّعة فيinvestcats. - قاموسا الشكاوى والتشخيصات المشتركان:
gyna.complaintid←complaint.idوgyna.diagnosisid←diagnosis.id(CSV). - موديول العقم:
infertilitygyna.infertid←infertility.id، وشاشة الشيت تنشئ وتعرضinfertilitysheetالذي تُخزَّن فيه قيم قوائم الحيض والفحص الموضعي. - موديول متابعة الحمل:
gynaus.mainantenatalidيربط سونار النساء بسجلmainantenatal(استنتاج من اسم العمود). - موديول السونار: كنترولر
ultrasoundgyna.phpيدير جدولultrasoundgyna(تقرير أخصائي السونار) المرتبط بالمريضة عبرpatientid. - التاريخ المرضي الحالي: شاشة النساء تكتب في
gynaphالمرتبط بقاموسَيpresenthistoryquestions/presenthistoryanswers. - تتبع الزيارات: كل دخول للشاشة يُحدِّث
lastvisit(patientid + اسم الكنترولر). - الإعدادات العامة:
programesettingتتحكم في شكل نموذج السونار (مبسّط/كامل) وطباعة التشخيص مع الروشتة وغيرها.
ملاحظات فنية
- لا توجد مفاتيح أجنبية (Foreign Keys) أو فهارس غير المفتاح الأساسي في أي جدول؛ كل العلاقات ضمنية في كود الكنترولرات.
- تعدد أنماط الحذف المنطقي بشكل غير متسق:
conditionsفيgyna، وdeletedفي جداول الأدوية والفحوصات والسونار، وdelفي جداول القواميس. - كود
infertility.phpيستعلم بشرطdel = 0علىinfertilitygynaبينما العمود غير موجود في تعريف الجدول بالـ dump — يضيفه RedBeanPHP في الوضع المرن وقت التشغيل (استنتاج). - حقول متعددة القيم مخزّنة كسلاسل CSV:
gyna.diagnosisidوgyna.complaintidوnewvisitg.newvisitgcoوnewvisitg.newvisitgdiagوأعمدة الحيض والفحص الموضعي علىinfertilitysheet— يستحيل معها الاستعلام والتقارير بكفاءة. - ازدواج كامل في الجداول:
gynadrugs≡gynasheetdrugsوgynainvestigation≡gynasheetinvest(نفس البنية حرفياً لشاشتين مختلفتين)، كما تتكرر بيانات العقم بينgynainfertilityوحقولgyna.inf_*. gynasheet00.phpنسخة قديمة مكررة من منطقgyna.php+gynasheet.phpمعاً (Legacy duplicate).newvisitg.dateوnewvisitg.lmpمن نوع varchar وليست تواريخ، والقياسات الطبية فيgynaus/gynausficilsمخزّنة varchar(50).- القوائم المرجعية (الحيض، الفحص الموضعي، C/O، التشخيص، أنواع العقم) فارغة في نسخة قاعدة البيانات؛ المفردات تُبنى من المستخدمين وقت التشغيل عبر
getselectajax. - نقاط نهاية التحديث العامة تستقبل اسم الجدول والعمود من العميل مباشرة (
update/Add/append/deleterow) — مخاطرة أمنية تسمح بالكتابة في أي جدول، إضافة إلى بناء SQL بسلاسل نصية في بحث الأدوية (search). - عمليات كتابة أثناء القراءة: دالة العرض
indexتدمجdiagnosistxtداخلcomplaintوتحفظ السجل أثناء عرض الصفحة (ترحيل بيانات خفي). - اسم الدواء يُنسخ denormalized في
drugnameداخل جداول الروشتات، وحقلinvestresultنصي حر بلا وحدات أو مدى مرجعي.
توصيات النقل إلى ERP
- إنشاء موديل
GynaVisit(من جدولgyna) مع جدولي ربط Pivot:gyna_visit_complaintsوgyna_visit_diagnosesبدلاً من حقول CSV، وحذفdiagnosistxtبعد ترحيل محتواه (الدمج يتم أصلاً في الكود الحالي). - توحيد روشتات الموديول في جدول واحد
gyna_prescriptions+gyna_prescription_itemsبدمجgynadrugsوgynasheetdrugsمع عمودcontext(visit / sheet)، واستبدالforhusbandبعمودsubject(wife/husband)، وربطdrug_idبمفتاح أجنبي حقيقي. - توحيد الفحوصات في
gyna_investigation_requestsبدمجgynainvestigationوgynasheetinvestبنفس أسلوب الدمج، مع فصل النتيجة في جدول/أعمدة منظّمة (قيمة، وحدة، تاريخ النتيجة). - موديل
GynaUltrasound(منgynaus) مع تحويل كل القياسات إلىdecimal، وموديل تابعGynaUltrasoundFollicle(منgynausficils) بعلاقة hasMany وعمودside(enum: left/right) بدلtypeالرقمي؛ وإلغاء عمودي العدّlfolliclesno/rfolliclesnoوالاكتفاء بالعد من العلاقة. - موديل
GynaSheet+GynaSheetVisit(منnewvisitg) مع تحويلdateوlmpإلى نوعdateفعلي، وتحويلusvsdtvإلى enum (US/TVS/3D_TVS)، وجداول Pivot للشكاوى والتشخيصات بدل CSV. - دمج كل القواميس البسيطة (
menstrualreg،menstrualamount،menstrualdysm،localcx،localvagina،localvulva،newvisitgco،newvisitgdiag،gynainfertilitytype) في جدول مرجعي موحّدlookups(type, title, is_active) أو Enums مزروعة بقيم معتمدة طبياً، لأنها جميعاً بنفس البنية (id/title/del) وفارغة في النسخة الحالية. - توحيد ملف العقم: دمج
gynainfertilityوحقولgyna.inf_*في موديل واحدInfertilityProfileمرتبط بالمريضة، معInfertilityPlan(منgynainfertilityplan)، ونقلinfertilitygynaإلى ترحيل موديول العقم كموديلInfertilityGynaExamمرتبط بـinfertility_id. - تحويل
maingynaإلى حقليnotesوplanضمن ملف المريضة النسائي (GynaProfile) بدلاً من جدول مستقل. - اعتماد الحذف المنطقي الموحّد بـ
deleted_at(SoftDeletes في Laravel) بدلconditions/deleted/del، وإضافةcreated_at/updated_atومُعرّف الطبيب الموحّدdoctor_idبمفاتيح أجنبية. - إغلاق الثغرة المعمارية: استبدال نقاط النهاية العامة (table/column من العميل) بـ API Resources وFormRequests محدّدة لكل موديل مع Validation صارم وصلاحيات.
- إهمال
gynasheet00.phpنهائياً عند النقل (شاشة قديمة مكررة) والاكتفاء بشاشة شيت واحدة في واجهة Angular.
العقم وتأخر الإنجاب (Infertility)
موديول متكامل لمتابعة حالات العقم وتأخر الإنجاب على مستوى الزوجين معاً (الزوجة والزوج)، ويشمل ملف العقم السريع القديم، و«شيت العقم» الشامل الحديث الذي يوثّق التاريخ المرضي والجراحي والإنجابي والدورة الشهرية وتشخيص عامل الزوج والزوجة والعلاجات السابقة واستجابتها، مع إصدار روشتات وطلبات تحاليل منفصلة لكل من الزوج والزوجة، وحساب الصيغة التوليدية (Gravida/Para) آلياً من سجل الحمول السابقة.
الوظائف الرئيسية
- إنشاء ملف عقم تلقائي لكل مريضة عند أول دخول للشاشة (سجل رئيسي + صفوف أولية للتشخيص وآخر دورة والفحص والتحاليل والملاحظات).
- توثيق تاريخ الزواج والدورة والعمليات والتاريخ الجنسي وعلامات سريرية (الثدي، الشعرانية، السمنة) في الملف السريع القديم.
- «شيت العقم» الشامل: نوع العقم (أولي/ثانوي)، مدة العقم، التاريخ المرضي والجراحي والعائلي، تفاصيل الدورة الشهرية (الانتظام، الكمية، عسر الطمث، آخر دورة)، الفحص العام والموضعي للزوجة.
- تشخيص عامل الزوج عبر ثلاث قوائم تشخيص متعددة الاختيار (
husbndiagnosis1/2/3) وقوائم أسباب منسوبة للزوج والزوجة (sheethusband,sheetwife). - تسجيل العلاجات السابقة واستجابتها: منشطات/محفزات (
tttda)، ميتفورمين (tttmetformin)، نوع العلاج (ttttype)، الاستجابة (tttresponse) وعدد المحاولات ونتيجتها. - سجل تفصيلي للحمول السابقة للزوجة (
awifep): نوع المولود، تاريخ الولادة، طريقة الولادة ونوعها (مكتمل/مبتسر)، الوزن، حي/متوفى، وسيلة منع الحمل بعده ومدتها — مع حساب عمر الطفل آلياً. - حساب الصيغة التوليدية آلياً (G/P/FT/PT/EPC/Living) من سجل الحمول السابقة والإجهاضات مع إضافة الحمل الجاري من شيت متابعة الحمل النشط.
- روشتات أدوية منفصلة للزوج والزوجة بتاريخ الزيارة مع الطباعة والتعديل وعرض السجل التاريخي (
forhusband= 0/1). - طلب تحاليل واستقصاءات من كتالوج التحاليل المصنّف، منفصلة للزوج والزوجة، مع تسجيل النتائج والطباعة.
- إضافة قيم جديدة لقوائم الاختيار السريرية أثناء العمل (إثراء المعجم السريري ديناميكياً من شاشة الطبيب).
- تسجيل زيجات سابقة للزوجة والزوج (
previous_marriage,hus_previous_marriage) من ملف المريضة وعرضها في ترويسة بيانات المريضة. - تسجيل آخر شاشة دخلتها المريضة (
lastvisit) لتسهيل استئناف العمل.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
infertility | الملف السريع القديم للعقم (سجل واحد لكل مريضة) | patientid, marriage, menstr, operations, sexualhistory, breast, hirsuitism, obesity | patients عبر patientid |
infertilitydiagnosis | تشخيصات مؤرخة للزوجة والزوج داخل الملف القديم | infertid, date, diagnosiswife, diagnosishusband, del | infertility عبر infertid |
infertilitylmp | سجل تواريخ آخر دورة شهرية | infertid, date | infertility عبر infertid |
infertilityinvest | نتائج استقصاءات العقم (سائل منوي، أشعة بالصبغة، هرمونات، منظار) | infertid, date, semen, peg, hsg, pct, us, prolactin, thyr, fsh, lh, laparoscopy | infertility عبر infertid |
infertilitynotes | ملاحظات مؤرخة على ملف العقم | infertid, date, note, del | infertility عبر infertid |
infertilitydrugs | روشتات الملف القديم (دواء لكل صف، زوج أو زوجة) | patientid, date, drugid, drugdos, forhusband, doctorid, deleted | patients عبر patientid، drugs عبر drugid، awusers عبر doctorid |
infertilitysheet | شيت العقم الشامل الحديث (سجل واحد لكل مريضة، ~64 حقلاً) | patientid, sheettype, historyduration, husbndiagnosis1..3, tttda, tttmetformin, ttttype, tttresponse, obstg/obstp/obstft/obstpt/obstepc/obstliving, menstrualreg, wmenstruallmp, sheethusband, sheetwife, sheetlocation | patients عبر patientid، وقوائم typeinf / sheetlocation / husbndiagnosis1-3 / ttt* / sheethusband / sheetwife عبر معرفات مخزنة نصياً |
infertilitysheetdrugs | روشتات شيت العقم (منفصلة للزوج والزوجة بالتاريخ) | patientid, date, drugid, drugname, drugdos, forhusband, doctorid, deleted | patients عبر patientid، drugs عبر drugid، awusers عبر doctorid |
infertilitysheetinvest | طلبات التحاليل ونتائجها من شيت العقم | patientid, date, investid, investresult, forhusband, doctorid, deleted | patients عبر patientid، invests عبر investid، awusers عبر doctorid |
typeinf | قائمة نوع العقم (أولي/ثانوي) (استنتاج) لحقل sheettype | title, del | infertilitysheet عبر sheettype |
type | قائمة عامة مرتبطة فعلياً بجدول تسجيل شيت الحمل (registeration.type) وليست خاصة بالعقم | title, del | registeration (موديول متابعة الحمل) عبر type |
sheethusband | قائمة أسباب/عوامل العقم المنسوبة للزوج (اختيار متعدد) | title, del | infertilitysheet عبر sheethusband (قائمة معرفات بفواصل) |
sheetwife | قائمة أسباب/عوامل العقم المنسوبة للزوجة (اختيار متعدد) | title, del | infertilitysheet عبر sheetwife (قائمة معرفات بفواصل) |
sheetlocation | قائمة مكان/جهة الفحص أو المتابعة في الشيت | title, del | infertilitysheet عبر sheetlocation |
previous_marriage | الزيجات السابقة للزوجة (المدة وعدد الذكور والإناث وسن آخر طفل) | patientid, period, males, females, last_age, deleted | patients عبر patientid |
hus_previous_marriage | الزيجات السابقة للزوج (نفس البنية) | patientid, period, males, females, last_age, deleted | patients عبر patientid |
husbndiagnosis1 | قائمة تشخيص الزوج — المستوى الأول (تحليل السائل المنوي غالباً) (استنتاج) | title, del | infertilitysheet عبر husbndiagnosis1 |
husbndiagnosis2 | قائمة تشخيص الزوج — المستوى الثاني | title, del | infertilitysheet عبر husbndiagnosis2 |
husbndiagnosis3 | قائمة تشخيص الزوج — المستوى الثالث | title, del | infertilitysheet عبر husbndiagnosis3 |
wifep | سجل الحمول السابقة للزوجة — نسخة قديمة مهجورة جزئياً (لا تزال تُقرأ في شاشة تاريخ الحقن المجهري) | infertilitysheetid, wifesex, wifemodeofd, wifetypeofd, wifepmethod, awifepmethod, name, date, duration, wifel | infertilitysheet عبر infertilitysheetid، wifesex/wifepmethod/awifepmethod عبر المعرفات |
wifepmethod | قائمة وسيلة منع الحمل بعد الولادة — النسخة القديمة المرتبطة بـwifep | title, del | wifep عبر wifepmethod |
awifep | سجل الحمول السابقة للزوجة — النسخة الفعّالة المستخدمة في شيت العقم وشيت الحقن المجهري (صف لكل حمل/ولادة) | infertilitysheetid, wifesex, wifemodeofd, wifetypeofd, wifew (الوزن), wifel (حي), date, awifepmethod, duration, stopped, comment, wifeage | infertilitysheet عبر infertilitysheetid، wifesex عبر wifesex، awifepmethod عبر awifepmethod، wifemodeofd/wifetypeofd (قوائم خارج النطاق) |
awifepmethod | قائمة وسيلة منع الحمل بعد الولادة — النسخة الفعّالة (اختيار متعدد في صف الحمل) | title, del | awifep عبر awifepmethod (قائمة معرفات بفواصل) |
wifesex | قائمة نوع المولود (ذكر/أنثى) (استنتاج) | title, del | awifep و wifep عبر wifesex |
tttda | قائمة علاجات سابقة — محفزات الدوبامين/منشطات التبويض (استنتاج من الاسم D.A.) | title, del | infertilitysheet عبر tttda |
tttmetformin | قائمة استخدام الميتفورمين في العلاج السابق | title, del | infertilitysheet عبر tttmetformin |
tttresponse | قائمة الاستجابة للعلاج السابق | title, del | infertilitysheet عبر tttresponse |
ttttype | قائمة نوع العلاج/التنشيط السابق (اختيار متعدد) | title, del | infertilitysheet عبر ttttype (قائمة معرفات بفواصل) |
سير العمل (Workflow)
- تُختار المريضة من شاشة البحث، ثم يفتح الطبيب شاشة «شيت العقم» (
infertilitysheet.php?patientid=N)؛ إذا لم يوجد شيت يُنشأ سجل فارغ تلقائياً فيinfertilitysheet، ويُنشأ كذلكgynasheetمرافق، ويُسجَّل الدخول فيlastvisit. - يملأ الطبيب بنود الشيت حقلاً حقلاً؛ كل حقل يُحفظ فوراً عبر AJAX (دالة
Add/updateتستقبل اسم الجدول والعمود والقيمة وتحفظ مباشرة). - القوائم السريرية (نوع العقم، تشخيصات الزوج، العلاجات ttt*، عوامل الزوج/الزوجة، المكان...) تُحمَّل عبر
getselectمن جداول القوائم، ويمكن للطبيب إضافة قيمة جديدة فورياً عبرgetselectajaxأو حذفها عبرdeldataselect. - يضيف الطبيب صفوف التاريخ الإنجابي عبر
appendالذي يُدرج صفاً جديداً فيawifepمرتبطاً بـinfertilitysheetid، ثم يكمل بياناته (نوع المولود، تاريخ وطريقة الولادة، الوزن، حي/متوفى، وسيلة منع الحمل بعده). - عند الضغط على زر الصيغة التوليدية تُنفَّذ دالة
obstetric()فتعدّ الولادات المكتملة والمبتسرة منawifepوالإجهاضات منwifeepcوالحمل الجاري منancsheetالنشط، وتحفظ النتائج في حقولobst*بالشيت. - تُكتب روشتة لكل من الزوجة (
forhusband=0) والزوج (forhusband=1) فيinfertilitysheetdrugsمن كتالوجdrugs، مع إمكانية عرض الروشتات السابقة بالتاريخ وتعديلها وطباعتها (قالب طباعة مشترك مع موديول النساء). - تُطلب التحاليل من كتالوج
investsالمصنّف بـinvestcatsوتُحفظ فيinfertilitysheetinvestلكل من الزوجين، وتُسجَّل النتائج لاحقاً في حقلinvestresultوتُطبع. - تكمل المتابعة في جداول الفحوصات المتقدمة المرتبطة بالشيت نفسه (سائل منوي، هرمونات، موجات صوتية، مناظير، متابعة تبويض، حقن مجهري) — وهي ضمن موديولات أخرى لكنها كلها تُفتح بمفتاح
infertilitysheetid. - الشاشة القديمة (
infertility.php) ما زالت متاحة كملف سريع: تُنشئ سجلinfertilityمع صفوف أولية للتشخيص وآخر دورة والفحص والتحاليل والملاحظات، وتدار صفوفها بنفس أسلوب الإضافة/التعديل/الحذف الناعم. - الزيجات السابقة للزوجين تُسجَّل من شاشة بيانات المريضة (موديول المرضى) وتظهر في ترويسة كل الشاشات حسب إعداد
programesetting.previous_marriage.
الارتباط بالموديولات الأخرى
- المرضى (patients): جميع الجداول الرئيسية مرتبطة عبر
patientid، وأسماء الزوج/الزوجة وألقابهما (wifetypes,husbandtypes) تُستخدم في الطباعة. - كتالوج الأدوية (drugs):
infertilitydrugs.drugidوinfertilitysheetdrugs.drugidيشيران إلىdrugs.id. - كتالوج التحاليل (invests / investcats):
infertilitysheetinvest.investidيشير إلىinvests.idوالتصنيف عبرinvests.investcatid. - متابعة الحمل (ancsheet): دالة
obstetric()تقرأ الشيت النشط (endpreg=0) لإضافة الحمل الجاري إلى Gravida؛ كما أن قائمةtypeمستخدمة فعلياً في جدولregisterationالخاص بشيت الحمل. - النساء (gynasheet): يُنشأ سجل
gynasheetتلقائياً من شاشة شيت العقم، وقوالب طباعة الروشتة والتحاليل مشتركة (gyna/print.html). - الحقن المجهري (ivfsheet): يقرأ
infertilitysheetوawifepوwifepوwifeepcبمفتاحinfertilitysheetidلعرض التاريخ الإنجابي. - الفحوصات المتقدمة المرتبطة بالشيت: جداول
semeninfertility,hormonalprofile,tvs,hsginfertility,laparoscopyinfertility,icsi,folliculom,newvisit,wifeepc(موديولات أخرى) كلها بمفتاحinfertilitysheetid. - المستخدمون (awusers):
doctoridفي جداول الروشتات والتحاليل يشير إلىuser_idمن الجلسة. - إعدادات البرنامج (programesetting): شعارات الطباعة وتفعيل خاصية الزيجات السابقة.
- آخر زيارة (lastvisit): تسجيل دخول المريضة لشاشة شيت العقم.
ملاحظات فنية
- يوجد جيلان متوازيان للموديول: الملف السريع القديم (
infertilityوفروعه) وشيت العقم الحديث (infertilitysheetوفروعه)؛ ولا يوجد ترابط بينهما سوىpatientid. wifepجدول قديم حلّ محلهawifep(الذي أضاف الوزن وحقل التوقف والعمر)، لكنه ما زال يُقرأ في شاشة تاريخ الحقن المجهري (ivfsheet.phpسطر 378) — ازدواجية بيانات محتملة. وبالمثلwifepmethodقديمة وawifepmethodهي الفعّالة.infertilitysheet00.phpنسخة كنترولر قديمة مكررة منinfertilitysheet.php(تستخدمgynadrugsللروشتات بدلاً منinfertilitysheetdrugs) — كود ميت يجب استبعاده.- ثغرة أمنية جوهرية: دوال
Add/update/append/getselect/deleterowتستقبل اسم الجدول والعمود من طلب POST مباشرة دون قائمة سماح، ما يتيح الكتابة أو الحذف في أي جدول بقاعدة البيانات. - القيم متعددة الاختيار (تشخيصات الزوج، ttttype، sheethusband/sheetwife، awifepmethod) تُخزَّن كمعرفات مفصولة بفواصل داخل أعمدة
varchar— غير معيارية ولا يمكن الاستعلام عنها مباشرة. - التواريخ في
infertilitysheetوawifepمخزنة كنصوصvarcharبصيغ مختلطة (Y/m/dوd-m-Y)، بينما الجداول القديمة تستخدمdateفعلياً. - جميع جداول القوائم (typeinf، ttt*، sheethusband...) فارغة في نسخة قاعدة البيانات المرفقة — المعجم السريري يُبنى أثناء التشغيل من شاشة الطبيب ولا توجد قيم مرجعية معتمدة.
- عدم اتساق الحذف الناعم:
delفي بعض الجداول وdeletedفي أخرى، وقيمdel IS NULLتعني «نشط» في جداول القوائم. - جدولا
previous_marriageوhus_previous_marriageبترميزlatin1رغم احتوائهما نصوصاً عربية محتملة، وهما متطابقا البنية (تكرار هيكلي). - الصيغة التوليدية تُخزَّن كأرقام مجمّعة في الشيت وتُعاد حسابتها يدوياً بزر — قابلة لعدم الاتساق مع بيانات
awifepالفعلية. - قائمة
typeليست خاصة بالعقم فعلياً؛ تُستخدم في جدولregisterationبموديول متابعة الحمل (تصنيف مكان التسجيل) — تصنيفها هنا تاريخي فقط.
توصيات النقل إلى ERP
- إنشاء موديل رئيسي
InfertilityFile(يدمجinfertility+infertilitysheetفي ملف واحد لكل مريضة) مع جداول فرعية مهيكلة بدلاً من 64 عموداً مسطحاً:infertility_history،infertility_examination،infertility_menstrual_history. - موديل
ObstetricHistoryموحّد يحل محلwifepوawifepمعاً (مع ترحيل بيانات الجدولين وإزالة التكرار)، بعلاقات FK حقيقية إلى قوائمbaby_sexوdelivery_modeوdelivery_typeوcontraception_method. - توحيد قوائم الاختيار في جدول واحد
lookups(أو جداول Enum مهيكلة) بحقلgroupبدلاً من 15 جدولاً منفصلاً متطابق البنية (typeinf، sheethusband، sheetwife، sheetlocation، husbndiagnosis1-3، ttt*، wifesex، wifepmethod، awifepmethod)، مع جداول pivot للعلاقات متعددة الاختيار بدلاً من النصوص المفصولة بفواصل. - توحيد الروشتات: استبدال
infertilitydrugsوinfertilitysheetdrugs(وأشباههما في باقي الموديولات) بموديلPrescription+PrescriptionItemمركزي بحقلmoduleوfor_spouse، وكذلكLabOrder+LabOrderItemبدلاً منinfertilitysheetinvest. - تحويل الصيغة التوليدية (G/P/FT/PT/EPC/Living) إلى Accessor محسوب آنياً في Laravel من سجلات
ObstetricHistoryوالإجهاضات والحمل النشط بدلاً من تخزينها يدوياً. - نقل
previous_marriageوhus_previous_marriageإلى جدول واحدprevious_marriagesبحقلspouse(wife/husband) ضمن موديول المرضى، مع تحويل الترميز إلىutf8mb4. - تحويل كل أعمدة التواريخ النصية إلى نوع
dateمع سكربت ترحيل يعالج الصيغ المختلطة، وتوحيد الحذف الناعم عبرSoftDeletesالقياسية. - إغلاق ثغرة الكتابة العامة: استبدال نقاط AJAX العامة بـ Form Requests وValidation صريحة لكل موديل، مع سياسات صلاحيات (Policies) لكل عملية.
- إسقاط
infertilitysheet00.phpنهائياً، ومراجعة بياناتwifepقبل الترحيل لدمج ما هو غير مكرر معawifep. - نقل قائمة
typeإلى نطاق موديول متابعة الحمل (ANC) عند الترحيل لأنها مرتبطة بجدولregisterationوليس بالعقم.
الحقن المجهري وأطفال الأنابيب (IVF/ICSI/IUI) (IVF / ICSI / IUI & Cycle Monitoring)
يغطي هذا الموديول الرحلة العلاجية الكاملة لمحاولات الإخصاب المساعد: ورقة الـ IVF/ICSI النشطة لكل مريضة (بروتوكول التنشيط، متابعة التحفيز اليومي للمبايض، سحب البويضات OPU، تحليل السائل المنوي، نقل الأجنة الطازج والمجمد، تحضير بطانة الرحم للأجنة المجمدة، والنتيجة النهائية)، إضافة إلى «ورقة المتابعة» (Monitoring Sheet) المستقلة لمتابعة دورات التنشيط بالزيارات اليومية (HMG، سمك البطانة، حويصلات المبيضين، E2)، مع وصفات وتحاليل خاصة بالزوجة والزوج، وأرشفة المحاولات السابقة، وتقارير إحصائية لنتائج الـ IVF وتقرير يومي لحالات الـ IUI.
الوظائف الرئيسية
- فتح ورقة IVF/ICSI نشطة واحدة لكل مريضة تلقائياً (
ivfsheetحيثendpreg = 0) مع إنشاء أوراق العقم والنساء (infertilitysheetوgynasheet) تلقائياً إن لم توجد. - تسجيل بيانات التقييم قبل التنشيط: نوع العقم ومدته، AMH، عدد الحويصلات الأولية (AFC)، البروتوكول، العلاج، الملاحظات.
- شبكة متابعة تنشيط المبايض (
ovst): صف لكل زيارة يحوي يوم الدورة، التاريخ، Agonist/Antagonist، جرعة HMG، عدّ الحويصلات حسب القطر (10–20 مم) لكل مبيض، سمك البطانة، قيمة E2، وملاحظات، مع حساب التاريخ آلياً من LMP ويوم الدورة. - تسجيل تفجير التبويض (TOO)، وسحب البويضات (OPU: العدد، MII، MI، GV)، وبيانات السائل المنوي، ونسب الإخصاب (F/E D2)، ونقل الأجنة الطازج (العدد، الدرجة، الإلغاء) والتجميد.
- دورات النقل المجمد: تحضير بطانة الرحم (
eprep) بنظام دعم أصفري (epreplps)، متابعة سمك البطانة والمبيضين، الإذابة (Thawing) والنقل والنتيجة. - إنهاء المحاولة وأرشفتها (fresh أو frozen) مع نسخ BMI من آخر فحص سريري، وتوليد سطر ملخص تاريخي في جدول
icsiمرتبط بورقة العقم — بما في ذلك صفوف النقل الإضافية من جدولsefo. - استعراض أرشيف محاولات IVF السابقة لكل مريضة وفتح أي محاولة للقراءة (
ac=archiveوac=historys). - ورقة متابعة دورة تنشيط مستقلة (
mointoringsheet) برقم محاولة، إجراء (IVF/ICSI/IUI...)، بروتوكول، مصدر الحيوانات المنوية (Ejaculate/PESA/TESE/Cryo)، أدوية تحفيز (HMG/Agonist/HCG) — جميعها قوائم منسدلة قابلة للإضافة الفورية من الشاشة. - زيارات متابعة يومية داخل ورقة المتابعة (
mointoringsheetvisits): يوم الدورة محسوب آلياً، جرعة HMG، سمك البطانة، حويصلات المبيض الأيمن والأيسر، E2. - كتابة وصفات دوائية للزوجة أو الزوج من كتالوج الأدوية مع الطباعة وسجل تاريخي بالتواريخ (
mointoringsheetdrugs). - طلب تحاليل واستقصاءات للزوجة أو الزوج من كتالوج التحاليل مع تسجيل النتائج والطباعة (
mointoringsheetinvestigation). - تسجيل نتيجة الدورة في ورقة المتابعة (بويضات، أجنة منقولة، تجميد، P4، Outcome) ثم أرشفتها (
status = 1) واستعراض المحاولات السابقة بتفاصيلها. - متابعة الإباضة البسيطة (Folliculometry) ضمن ورقة العقم (
folliculom): LMP، العلاج المنشط، يوم الدورة، قياس المبيضين والبطانة، التفجير والنتيجة. - تقرير إحصائي لنتائج الـ IVF (
Ivfstatistics): بحث بالفترة أو بالمريضة على الدورات الطازجة والمجمدة مع حساب عمر الزوجة وقت المحاولة وعرض البروتوكول والسائل المنوي وأول/آخر متابعة تنشيط وعدد دورات تحضير البطانة، مع الطباعة. - تقرير يومي وبحث بفترة لحالات الـ IUI (
iui.php) اعتماداً على تاريخ ونتيجة ورقة العقم (infertilitysheet.sheetdate / sheetresult) مع الطباعة.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
ivfsheet | الورقة الرئيسية لمحاولة IVF/ICSI النشطة: تقييم، TOO، OPU، سائل منوي، إخصاب، نقل طازج ومجمد، نتائج (حمل كيميائي/كيس حمل/ولادة) | patientid, endpreg, anamh, annn, anprotocol, lmpfresh, lmpfrozen, toocd, opun, opumll, fefn, ettn, frren, etn, outcomehsgn, frozenor, bmi, historytoday | patients عبر patientid، icsiprotocol عبر anprotocol، icsisemen عبر sseemmen، pla2cen عبر pla2cen، antype عبر antype |
ovst | شبكة متابعة تنشيط المبايض: صف لكل زيارة بقيم الحويصلات حسب القطر (10–20 مم) والبطانة وE2 | ivfsheetid, ovstcdfh, ovstdate, ovstag, ovsthmg, ovstfr…ovstffffff (أعمدة الحويصلات), eovst, eeovst, noteovst | ivfsheet عبر ivfsheetid |
eprep | تحضير بطانة الرحم لدورات النقل المجمد: LMP، العلاج، سمك البطانة، الإذابة والنقل | ivfsheetid, epreplps, eprepcd, lmpfrozen, eprepttt, eprepe, eprepro, epreplo, thawingdate, thawingstn, thawingen, eprepcancel | ivfsheet عبر ivfsheetid، epreplps عبر epreplps |
epreplps | قائمة منسدلة لأنظمة الدعم الأصفري (LPS) في تحضير البطانة — تُدار من الشاشة (فارغة في النسخة الاحتياطية) | title, del | تُرجع من eprep عبر epreplps |
icsi | السجل التاريخي الملخّص لمحاولات ICSI المنتهية (يُولَّد آلياً عند الأرشفة) ويُعرض في ورقة العقم — قيم نصية منسوخة وليست مفاتيح | infertilitysheetid, date, icsiprotocol, icsiplace, icsisemen, opu, fert, et, fr, refr, icsiss, icsiresult, vd, e2d2 | infertilitysheet عبر infertilitysheetid، sefo عبر sefoid (استنتاج) |
icsiplace | قائمة منسدلة لأماكن إجراء الـ ICSI (مراكز/معامل) | title, del | تُستخدم نصاً في icsi وتُعرض في تقارير ورقة العقم |
icsiprotocol | قائمة منسدلة لبروتوكولات التنشيط (Long/Short/Antagonist…) | title, del | ivfsheet عبر anprotocol |
icsiresult | قائمة منسدلة لنتائج محاولة الـ ICSI | title, del | تُستخدم نصاً في icsi.icsiresult |
icsisemen | قائمة منسدلة لمصدر/حالة العينة المنوية المستخدمة | title, del | ivfsheet عبر sseemmen |
icsiss | قائمة منسدلة مساندة لبيانات اختبار الحمل/متابعة ما بعد النقل (تُخزَّن قيمتها في icsi.icsiss) | title, del | تُستخدم نصاً في icsi.icsiss |
mointoringsheet | رأس ورقة متابعة دورة التنشيط: المحاولة، الإجراء، البروتوكول، مصدر العينة، أدوية التحفيز، نتائج OPU/ET/Cryo والمحصلة | patientid, doctorid, monitordate, lmp, attempno, procedure, protocol, ejac, pesa, tese, sryo, hmg, agonist, hcg, oocytestotal, ettotal, cyroday, p4, outcome, status | patients عبر patientid، awusers عبر doctorid، وجداول القوائم التسعة عبر أعمدتها |
mointoringsheetvisits | الزيارات اليومية داخل ورقة المتابعة: يوم الدورة، HMG، البطانة، حويصلات يمين/يسار، E2 | mointoringsheetid, visitdate, cycleday, hmg, endo, follicright, follicleft, e2 | mointoringsheet عبر mointoringsheetid |
mointoringsheetdrugs | الوصفات الدوائية داخل المتابعة للزوجة أو الزوج مع ربط اختياري بإيصالات الصيدلية | patientid, date, drugid, drugdos, forhusband, doctorid, recepittmpid, recepitdrugid, mointoringsheetid | patients عبر patientid، drugs عبر drugid، mointoringsheet عبر mointoringsheetid |
mointoringsheetinvestigation | التحاليل المطلوبة داخل المتابعة للزوجة أو الزوج مع النتيجة | patientid, date, investid, investresult, forhusband, doctorid, mointoringsheetid | invests عبر investid، patients عبر patientid، mointoringsheet عبر mointoringsheetid |
mointoringsheetprocedure | قائمة منسدلة لنوع الإجراء (IVF/ICSI/IUI…) | name, deleted | mointoringsheet عبر procedure |
mointoringsheetprotocol | قائمة منسدلة لبروتوكول التنشيط في ورقة المتابعة | name, deleted | mointoringsheet عبر protocol |
mointoringsheetejac | قائمة منسدلة لحالة العينة بالقذف (Ejaculate) | name, deleted | mointoringsheet عبر ejac |
mointoringsheetpesa | قائمة منسدلة لخيارات سحب الحيوانات المنوية PESA | name, deleted | mointoringsheet عبر pesa |
mointoringsheettese | قائمة منسدلة لخيارات استخراج الحيوانات المنوية TESE | name, deleted | mointoringsheet عبر tese |
mointoringsheetsryo | قائمة منسدلة لخيارات العينات المجمدة (Cryo — مكتوبة sryo) | name, deleted | mointoringsheet عبر sryo |
mointoringsheethmg | قائمة منسدلة لأدوية الـ HMG (الجونادوتروبين) | name, deleted | mointoringsheet عبر hmg |
mointoringsheetagonist | قائمة منسدلة لأدوية الـ Agonist/Antagonist | name, deleted | mointoringsheet عبر agonist |
mointoringsheethcg | قائمة منسدلة لأدوية إبرة التفجير HCG | name, deleted | mointoringsheet عبر hcg |
folliculom | متابعة التبويض البسيطة (Folliculometry) داخل ورقة العقم: قياس الحويصلات والبطانة والتفجير والنتيجة | infertilitysheetid, lmp, ttt, cd, date, ro, lo, endo, pelvis, too, result | infertilitysheet عبر infertilitysheetid |
سير العمل (Workflow)
- يدخل الطبيب على المريضة من شاشة المرضى ويفتح «IVF Sheet» (
ivfsheet.php?ac=index&patientid=…)؛ يبحث النظام عن ورقة نشطة (endpreg = 0) وإن لم توجد ينشئها فوراً، وينشئ معهاinfertilitysheetوgynasheetإن لم تكونا موجودتين، ويسجل الدخول فيlastvisit. - تُحفظ كل خانة في الشاشة لحظياً عبر AJAX (دالة
Add()تستقبل اسم الجدول والعمود والقيمة وتحدّث مباشرة) — لا يوجد زر حفظ مركزي. - يضيف الطبيب صفوف متابعة التنشيط بالزر «append» الذي ينشئ سجل
ovstمرتبطاً بالورقة، ثم يُدخل يوم الدورة فيحسب النظام التاريخ آلياً منlmpfresh(دالتاovstcdfhوnewcd)، ويُسجل Ag/HMG وعدّ الحويصلات حسب القطر والبطانة وE2. - عند النضج تُسجل بيانات التفجير (TOO) ثم سحب البويضات (OPU) وبيانات السائل المنوي والإخصاب، ثم نقل الأجنة الطازج (وصفوف نقل إضافية في جدول
sefo) أو التجميد. - في دورات النقل المجمد تُضاف صفوف
eprepلتحضير البطانة (LMP المجمد، العلاج، السمك، نظام LPS من قائمةepreplps) ثم بيانات الإذابة والنقل والنتيجة. - عند انتهاء المحاولة يضغط الطبيب «إنهاء» محدداً النوع (fresh/frozen)؛ فتُؤرشف الورقة (
endpreg = 1،frozenor،historytoday، نسخbmiمن آخرexamination) ويُولَّد سطر/أسطر ملخصة فيicsiبقيم نصية منسوخة من القوائم (البروتوكول، المكان، السائل المنوي) مرتبطة بـinfertilitysheetidلتظهر في تاريخ ورقة العقم. - يمكن استعراض المحاولات المؤرشفة من
ac=archiveوفتح أي محاولة للقراءة منac=historys. - بالتوازي توجد شاشة «Monitoring Sheet» (
monitoring.php): تُفتح ورقة متابعة مفتوحة واحدة لكل مريضة (status = 0) وتُنشأ تلقائياً، ويُختار الإجراء والبروتوكول ومصدر العينة وأدوية التحفيز من قوائم قابلة للإضافة الفورية (addNewItem) والتعديل (editselect). - كل زيارة متابعة تُضاف بصف جديد (
addNewVisit) بيوم دورة محسوب آلياً منmonitordate، وتُحدَّث خاناته (HMG/Endo/حويصلات يمين-يسار/E2) لحظياً عبرupdate(). - من نفس الشاشة تُكتب وصفات للزوجة أو الزوج (
mointoringsheetdrugsمن كتالوجdrugs) وتُطلب تحاليل (mointoringsheetinvestigationمن كتالوجinvests) مع شاشات عرض وطباعة بالتواريخ. - بعد تسجيل نتائج OPU والأجنة والتجميد والمحصلة تُؤرشف الورقة (
trigSheet⇒status = 1)، وتُستعرض المحاولات السابقة منtrialsوتفاصيل كل محاولة منtrialdetailعبر استعلام JOIN مع جداول القوائم التسعة. - تقرير «IVF Statistics» يبحث في
ivfsheetبفترة LMP (طازج أو مجمد) أو بالمريضة، ويحسب عمر الزوجة وقت المحاولة منpatients.dateofbirth، ويعرض أول وآخر صف تنشيط وعدد دورات تحضير البطانة؛ وتقرير «IUI» يعرض حالات اليوم ويبحث بفترة علىinfertilitysheet.sheetdateوsheetresultمع الطباعة.
الارتباط بالموديولات الأخرى
- موديول المرضى:
ivfsheet.patientidوmointoringsheet.patientidوmointoringsheetdrugs.patientidوmointoringsheetinvestigation.patientid←patients.id(وبيانات الزوج تُقرأ من نفس سجل المريضة:husdandname,husbandtypeid). - موديول العقم (Infertility):
icsi.infertilitysheetidوfolliculom.infertilitysheetid←infertilitysheet.id؛ وشاشة IVF تنشئ وتعرض ورقة العقم وجداولها (awifep,wifeepc)، وتقرير IUI يعتمد كلياً علىinfertilitysheet.sheetdate/sheetresult. - موديول النساء (Gyna): شاشة IVF تنشئ/تعرض
gynasheetللمريضة، وشاشات طباعة المتابعة تستخدم قوالبgyna/print.htmlوgyna/printinv.html. - كتالوج الأدوية:
mointoringsheetdrugs.drugid←drugs.idمع حقلي ربط بإيصالات الصيدليةrecepittmpidوrecepitdrugid(استنتاج). - كتالوج التحاليل:
mointoringsheetinvestigation.investid←invests.idوتُعرض مجموعات التحاليل منinvestcats. - موديول الفحص السريري: عند أرشفة المحاولة يُنسخ
examination.bmiإلىivfsheet.bmi. - المستخدمون والصلاحيات:
mointoringsheet.doctoridوdoctoridفي الوصفات والتحاليل ←awusers(من الجلسةuser_id)، والتحقق عبرawrole. - قوائم مشتركة من موديولات أخرى:
ivfsheet.antype/antypes← جدولاantype/antypes، وivfsheet.pla2cen←pla2cen(أماكن)، وivfsheet.sseemen←sseemen. - تتبع آخر زيارة: شاشتا IVF وIUI تسجلان في
lastvisit؛ وتقاريرCompletesreportوshوpatienthistoryتقرأicsiوfolliculomوeprepضمن الملف الشامل للمريضة.
ملاحظات فنية
- خطأ إملائي ثابت في أسماء عشرة جداول: «mointoring» بدلاً من «monitoring»، و«sryo» بدلاً من «cryo»، و«folliculom» بدلاً من «folliculometry» — يجب توحيدها عند النقل.
- ازدواجية كاملة بين
ivfsheet.phpوivfsheet00.php(نسخة أقدم لا تدعم جدولsefoولا نسخ BMI) — كود ميت يجب إسقاطه. - جدول
ovstيستخدم أسماء أعمدة مشفّرة غير قابلة للصيانة (ovstfr,ovstfrrrr,ovstdffffff…) تمثل خلايا شبكة عدّ الحويصلات حسب القطر 10–20 مم؛ المعنى محفوظ فقط في ترتيب أعمدة قالب Smarty. - جدول
icsiيخزن قيم القوائم كنصوص منسوخة (denormalized) بينماivfsheetيخزنها كمعرّفات — ازدواجية تمثيل لنفس البيانات. - جدول
sefo(صفوف نقل أجنة إضافية) مستخدم في الكود لكنه غير موجود في ملف الـ SQL — يُنشأ آلياً بوضع RedBeanPHP الـ fluid، وهي مخاطرة تشغيلية. - جميع جداول القوائم المنسدلة (15 جدولاً) فارغة في النسخة الاحتياطية؛ المفردات السريرية تُدخل وتُدار من الشاشات مباشرة (
addNewItem/getselectajax). - كل التواريخ في
ivfsheetوovstوeprepوfolliculomمخزنة كـvarcharبصيغةY/m/dوليست أعمدة تاريخ — يستحيل الفرز والاستعلام الزمني الموثوق. - ثغرات أمنية جوهرية: دوال
Add()وupdate()وdel()تستقبل اسم الجدول والعمود من الـ POST مباشرة (كتابة عشوائية في أي جدول)، ودالةnewcd()وبحثiui.phpيبنيان SQL بالتجميع النصي (SQL Injection). - خطأ منطقي في بحث
Ivfstatistics: شرطORبدون أقواس في الفرع غير المقيد بالمريضة، ودالةshowprintفيه تستعلم منancsheet(خطأ نسخ-لصق من تقرير الحمل) فالطباعة لا تعكس نتائج البحث. - ورقة المتابعة تفترض ورقة مفتوحة واحدة لكل مريضة دون قيد فريد في قاعدة البيانات، والحذف في كل الجداول منطقي (
deleted/del) بدون توحيد (بعضهاdel is nullوبعضهاdeleted = 0).
توصيات النقل إلى ERP
- توحيد المسارين المزدوجين (ورقة IVF وورقة المتابعة) في كيان واحد: نموذج
IvfCycle(Laravel) يمثل المحاولة برقمها ونوعها (Fresh/Frozen/IUI/Monitoring) وحالتها (Active/Archived) بدلاً منivfsheet+mointoringsheetالمنفصلين. - إنشاء نموذج
IvfCycleVisitموحّد يدمجovstوmointoringsheetvisitsوfolliculom: زيارة متابعة بتاريخ ويوم دورة وجرعات وE2 وسمك بطانة، مع جدول فرعيfollicle_measurements(جانب المبيض، القطر، العدد) بدلاً من الأعمدة المشفّرة الـ 26 فيovst. - نمذجة مراحل الدورة كجداول فرعية واضحة:
OpuRecord(البويضات: total/MII/MI/GV)،SemenSample(المصدر: Ejaculate/PESA/TESE/Cryo)،EmbryoTransfer(يشمل صفوفsefoالإضافية)،Cryopreservation،EndometrialPrep(يستوعبeprepمع الإذابة)، وCycleOutcome(HCG/كيس حمل/ولادة). - الاستغناء عن جدول
icsiالملخّص نهائياً: هو نسخة denormalized تُولَّد عند الأرشفة، ويُستبدل بـ View أو API endpoint يجمع تاريخ المحاولات من الكيانات الأصلية. - دمج جداول القوائم الـ 15 (
icsiprotocol,icsiplace,icsisemen,icsiss,icsiresult,epreplps, وجداولmointoringsheet*التسعة) في جدول مرجعي واحدlookupsبنمطtype + name + is_activeأو Enum حيث تكون القيم سريرية ثابتة (البروتوكولات، مصادر العينة)، مع ترحيل القيم الحية من قاعدة الإنتاج لأنها فارغة في النسخة الاحتياطية. - تحويل جميع أعمدة التواريخ النصية إلى
date/datetimeأثناء الترحيل مع سكربت تنظيف لصيغةY/m/dوالقيم0000-00-00، وتحويل الأعداد (بويضات، أجنة، E2) إلى أنواع رقمية مع التحقق. - ربط الوصفات والتحاليل بنظام الوصفات/المعمل الموحد في الـ ERP:
mointoringsheetdrugs⇒prescriptionsالعامة (مع علاقة بالدورة وبالشريك)، وmointoringsheetinvestigation⇒lab_orders، مع خاصيةfor_partnerبدلforhusband. - فرض قيود قاعدة البيانات الغائبة: مفاتيح أجنبية فعلية، وقيد فريد «دورة نشطة واحدة لكل مريضة»، وحذف ناعم موحّد (
deleted_at)، وإلغاء كل نقاط الـ AJAX العامة (table/column من العميل) لصالح Form Requests وPolicies في Laravel. - إعادة بناء تقرير إحصائيات الـ IVF كاستعلامات Eloquent/SQL مفهرسة على الكيانات الجديدة (نِسب الحمل لكل بروتوكول/فئة عمرية/نوع دورة) بدل الحلقات N+1 الحالية، وتصحيح تقرير الطباعة المعطوب، وبناء تقرير IUI على كيان الدورة بدلاً من ورقة العقم.
تحاليل الزوج والسائل المنوي (Andrology & Semen Analysis)
يغطي هذا الموديول الجانب الذكوري من تقييم العقم في العيادة: تسجيل تحاليل السائل المنوي (العدد، الحركة، الأشكال الطبيعية، الحيوية... إلخ)، والفحوصات الأندرولوجية المتقدمة (الموجات فوق الصوتية على كيس الصفن، الخريطة الكروموسومية Karyotyping، حذف كروموسوم Y الدقيق، تفتت الحمض النووي للحيوانات المنوية SDF، عينة الخصية TESE)، إضافة إلى ملفات الهرمونات للزوج والزوجة. تُسجَّل البيانات من مسارين متوازيين: شاشة الفحوصات العامة للمريض (جدولا semen وhormon) وشيت العقم المفصّل (جداول semeninfertility وsemen2 وhormonalprofile/hormonalprofile2).
الوظائف الرئيسية
- تسجيل تحليل سائل منوي سريع للمريض من شاشة الفحوصات (Investigations) مع الحقول: العدد
count، الحركة التقدميةmotilitya/motilityab، الأشكال الطبيعيةnormal، خلايا الصديدpuscell، مع أعلام تصنيفية (Oligo / Astheno / Terato / Normal) كمربعات اختيار. - تسجيل صفوف متعددة لتحاليل السائل المنوي داخل شيت العقم مع مكان التحليل ونوعه (قوائم منسدلة قابلة للإضافة أثناء العمل) والقيم:
nc(العدد)،prm(الحركة التقدمية)،tm(الحركة الكلية)،af(الأشكال غير الطبيعية)،vit(الحيوية)،vol(الحجم)،tzi،sdi. - تسجيل الفحوصات الأندرولوجية المتقدمة (قسم "Other Inv" في شيت العقم): سونار كيس الصفن، فحص TRUE، الخريطة الكروموسومية Karyotype، حذف Y الدقيق Yq Microdeletion، تفتت DNA الحيوانات المنوية SDF، فحص Semen Fr، وعينة الخصية TESE — لكل فحص تاريخ ومكان ونتيجة.
- نتائج الفحوصات تُختار من قوائم مرجعية يديرها المستخدم (سبعة جداول lookup) مع إمكانية إضافة قيمة جديدة من داخل الشاشة عبر AJAX دون مغادرة الشيت، ونتيجة السونار تقبل اختيارات متعددة.
- تسجيل ملف هرموني للزوج داخل شيت العقم (FSH، LH، Testosterone الكلي، Prolactin، E2، Inhibin B + خانتان حرتان) بصيغة تاريخ/نتيجة لكل هرمون، وملف هرموني ثانٍ (
hormonalprofile2) يضم AMH وTSH وP4 (للزوجة — استنتاج). - تسجيل لوحة هرمونات معملية شاملة للمريض من شاشة الفحوصات (جدول
hormon): LH، FSH، PRL، E2، AMH، Free/Total Testosterone، P4، TSH، T3، T4، DHT، BhCG، Inhibin B، DHEAS، إضافة إلى دلالات أورام (CA125، CEA، LDH). - إدخال خصائص السائل المنوي المستخدم في دورة الحقن المجهري/أطفال الأنابيب (أربع قوائم منسدلة تحت عمود "Semen" في جدول الدورة بشيت IVF) تُخزَّن في أعمدة
ssemen/sseemen/sseemmen/sseemmeenبجدولivfsheet. - عرض كل بيانات الموديول في تقرير المراجعة الشامل (كنترولر
sh.php) مع فك ترميز القوائم المرجعية وطباعة الشيت. - حذف منطقي (soft delete) لسجلات
semenوhormonعبر العمودdel، وحذف فعلي لصفوف شيت العقم.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
semen | تحليل سائل منوي سريع لكل مريض من شاشة الفحوصات، مع تصنيف الحالة (Oligo/Astheno/Terato/Normal) | sdate, patientid, count, motilitya, motilityab, normal, puscell, normaltype, oligo, astheno, tetrato, doctorid, del | patients عبر patientid، awusers عبر doctorid |
semeninfertility | صفوف تحاليل السائل المنوي داخل شيت العقم (معايير WHO) | infertilitysheetid, semenplace, sementype, date, nc, prm, tm, af, vit, vol, tzi, sdi | infertilitysheet عبر infertilitysheetid، semenplace عبر semenplace، sementype عبر sementype |
semen2 | الفحوصات الأندرولوجية المتقدمة لكل شيت عقم: سونار الصفن، TRUE، Karyotype، Yq Micro، SDF، Semen Fr، TESE — تاريخ ومكان ونتيجة لكل فحص (جدول عريض) | infertilitysheetid, detescrotal/placescrotal/semen2resultscrotal, detekaryo/semen2resultkaryo, deteyqmicro/semen2resultyqmicro, detesdf/semen2resultsdf, detetese/semen2placetese/resulttese, detesemenfr/semen2placesemenfr/resultsemenfraf/resultsemenfrm/resultsemenfrc, deteother/placeother/resultother | infertilitysheet عبر infertilitysheetid، وسبعة جداول lookup عبر أعمدة semen2result* وsemen2place* (نتيجة السونار قيم متعددة مفصولة بفواصل) |
semenplace | قائمة مرجعية: أماكن/معامل إجراء تحليل السائل المنوي (تُملأ من المستخدم — فارغة في النسخة) | id, title, del | تُقرأ من semeninfertility.semenplace |
sementype | قائمة مرجعية: أنواع تحليل السائل المنوي | id, title, del | تُقرأ من semeninfertility.sementype |
semen2placesemenfr | قائمة مرجعية: مكان إجراء فحص Semen Fr | id, title, del | تُقرأ من semen2.semen2placesemenfr |
semen2placetese | قائمة مرجعية: مكان إجراء عينة الخصية TESE | id, title, del | تُقرأ من semen2.semen2placetese |
semen2resultkaryo | قائمة مرجعية: نتائج الخريطة الكروموسومية Karyotyping | id, title, del | تُقرأ من semen2.semen2resultkaryo |
semen2resultscrotal | قائمة مرجعية: نتائج سونار كيس الصفن (اختيار متعدد) | id, title, del | تُقرأ من semen2.semen2resultscrotal (CSV) |
semen2resultsdf | قائمة مرجعية: نتائج فحص تفتت DNA الحيوانات المنوية SDF | id, title, del | تُقرأ من semen2.semen2resultsdf |
semen2resulttrue | قائمة مرجعية: نتائج فحص TRUE (استنتاج: TRUS سونار عبر المستقيم) | id, title, del | تُقرأ من semen2.semen2resulttrue |
semen2resultyqmicro | قائمة مرجعية: نتائج فحص حذف كروموسوم Y الدقيق | id, title, del | تُقرأ من semen2.semen2resultyqmicro |
ssemen | قائمة مرجعية لأول قائمة منسدلة بعمود "Semen" في جدول دورة IVF (اسم جدول مشوّه إملائيًا) | id, title, del | تُقرأ من ivfsheet.ssemen |
sseemen | قائمة مرجعية للقائمة الثانية بعمود "Semen" في شيت IVF | id, title, del | تُقرأ من ivfsheet.sseemen |
sseemmen | جدول يتيم غير مستخدم: العمود ivfsheet.sseemmen يقرأ خياراته فعليًا من جدول icsisemen وليس من هذا الجدول | id, title, del | لا توجد قراءة من الكود (مرشّح للحذف) |
sseemmeen | قائمة مرجعية للقائمة الرابعة بعمود "Semen" في شيت IVF | id, title, del | تُقرأ من ivfsheet.sseemmeen |
hormon | لوحة هرمونات معملية شاملة لكل مريض من شاشة الفحوصات، تشمل هرمونات الخصوبة ودلالات الأورام | sdate, patientid, lh, fsh, prl, etwo, amh, freet, totalt, pfour, tsh, tthree, tfour, dht, bhcg, inhibinb, asd, dheas, ca125, cea, ldh, doctorid, del | patients عبر patientid، awusers عبر doctorid |
hormonalprofile | الملف الهرموني للزوج داخل شيت العقم: FSH، LH، TT، PRL، E2، Inhibin + خانتان إضافيتان (تاريخ/نتيجة لكل هرمون) | infertilitysheetid, datefsh/resultfsh, datelh/resultlh, datett/resulttt, dateprl/resultprl, datee2/resulte2, dateinhibin/resultinhibin, dateother/resultother | infertilitysheet عبر infertilitysheetid |
hormonalprofile2 | الملف الهرموني الثاني بشيت العقم ويضم AMH وTSH وP4 (للزوجة — استنتاج) | infertilitysheetid, date, dateamh/resultamh, datetsh/resulttsh, datefsh/resultfsh, datelh/resultlh, datee2/resulte2, datep4/resultp4, dateprl/resultprl, dateother/resultother | infertilitysheet عبر infertilitysheetid |
سير العمل (Workflow)
- يفتح الطبيب شاشة الفحوصات (
investigation.php) لمريض محدد؛ إذا لم يوجد سجل سائل منوي، يُنشئ النظام تلقائيًا صفًا فارغًا فيsemenبتاريخ اليوم ومعرّف الطبيب الحالي. - تُحرَّر القيم خانةً بخانة عبر AJAX (دالة
updateالعامة التي تستقبل اسم الجدول والعمود والقيمة)، وتُضاف صفوف جديدة بزر "Add" (دالةaddRowالعامة لجداولsemenوhormonوغيرها)، ويتم الحذف منطقيًا بوضعdel = 1. - في مسار العقم، يفتح الطبيب شيت العقم (
infertilitysheet.php) فيُنشأinfertilitysheetتلقائيًا للمريض إن لم يوجد، وتُحمَّل صفوفsemeninfertilityوsemen2وhormonalprofileوhormonalprofile2المرتبطة به. - يضيف الطبيب صف تحليل سائل منوي أو فحص أندرولوجي أو ملف هرموني بالنقر على رابط الإضافة (دالة
appendالعامة التي تُنشئ صفًا بربطinfertilitysheetid)، ثم يملأ الخلايا التي تُحفظ فورًا حقلًا بحقل. - عند اختيار مكان التحليل أو نتيجته، تُحمَّل الخيارات من جداول الـ lookup عبر AJAX، ويمكن للطبيب إضافة قيمة جديدة فورًا (دالة
getselectajaxتُدخل سطرًا جديدًا في جدول الـ lookup المعني)؛ نتيجة سونار الصفن تُحفظ كقائمة معرّفات مفصولة بفواصل. - في شيت أطفال الأنابيب (
ivfsheet.php) يسجّل الطبيب خصائص العينة المنوية المستخدمة في الدورة من أربع قوائم منسدلة تُخزَّن قيمها في أعمدةssemen/sseemen/sseemmen/sseemmeenبجدولivfsheet. - عند المراجعة أو الطباعة، يعرض كنترولر
sh.phpالشيت كاملًا للقراءة: يجلب صفوف السائل المنوي والفحوصات الأندرولوجية والملفات الهرمونية ويفك ترميز كل القوائم المرجعية إلى نصوصها، ويسجّل آخر زيارة للمريض فيlastvisit. - تظهر بيانات الموديول أيضًا في التقارير المجمعة (
completereport.phpوfullreport.phpوغيرها) ضمن التقرير الشامل للمريضة.
الارتباط بالموديولات الأخرى
- المرضى (Patients): عبر
semen.patientidوhormon.patientidوكذلكinfertilitysheet.patientidالذي تتفرع منه بقية الجداول. - شيت العقم (Infertility): الجداول
semeninfertilityوsemen2وhormonalprofileوhormonalprofile2كلها أبناء لـinfertilitysheetعبرinfertilitysheetid. - أطفال الأنابيب (IVF): أعمدة
ivfsheet.ssemenوsseemenوsseemmenوsseemmeenتشير إلى جداول الـ lookup الخاصة بهذا الموديول إضافة إلى جدولicsisemenالتابع لموديول IVF. - المستخدمون/الأطباء (Users): عبر
semen.doctoridوhormon.doctoridإلىawusers.user_id(يُعرض اسم الطبيب مع كل سجل). - الفحوصات العامة (Investigations): جدولا
semenوhormonيُعرضان في نفس شاشة الفحوصات مع HSG والباثولوجي والفحوصات الأخرى، ويتحكم إعدادprogramesetting.investshowفي شكل الشاشة. - الأدوية (Drugs): كنترولر
drugsex.phpالمرتبط بالموديول هو في الواقع إدارة كتالوج الأدوية (drugs) المستخدم في الروشتات، وليس له علاقة مباشرة بجداول السائل المنوي. - الزيارات (Visits): كنترولر
sh.phpيسجّل فتح الشيت في جدولlastvisit.
ملاحظات فنية
- لا توجد أي مفاتيح أجنبية معلنة؛ كل العلاقات ضمنية عبر أعمدة معرّفات، و
semen.patientidمعرّف نصيvarchar(191)بينما معرف المريض رقمي. - جميع القيم الرقمية والتواريخ في جداول الشيت مخزنة كـ
varchar(191)(حتى تواريخ الفحوصات ونتائج الهرمونات)، ما يمنع أي تحقق أو حسابات أو فرز زمني سليم. - الجداول الأربعة المشوّهة إملائيًا
ssemen/sseemen/sseemmen/sseemmeenليست نسخًا مكررة من بعضها: ثلاثة منها قوائم مرجعية مستخدمة فعليًا لأعمدة "Semen" بشيت IVF، بينماsseemmenجدول يتيم لا يقرأه الكود إطلاقًا (القائمة المقابلة تقرأ منicsisemen). - نتيجة سونار الصفن تُخزَّن كسلسلة معرّفات مفصولة بفواصل داخل عمود نصي، وتُستعلم بتركيب نصي مباشر
"id in (0$ids)"— نمط هش وقابل لحقن SQL. - دوال عامة مثل
updateوappendوgetselectajaxتستقبل اسم الجدول والعمود من طلب POST مباشرة دون قائمة سماح — ثغرة Mass Assignment/كتابة في أي جدول. - الكنترولر القديم
infertilitysheet00.phpيستعلم جدولsemenبشرطinfertilitysheetid = ?رغم أن الجدول لا يحتوي هذا العمود أصلًا — كود قديم ميت يعكس تغيّر التصميم. - فتح شاشة الفحوصات يُنشئ تلقائيًا سجل
semenفارغًا إذا لم يوجد، ما يولّد سجلات فارغة غير ذات معنى في قاعدة البيانات. - جدول
hormonيخلط هرمونات الخصوبة بدلالات الأورام (CA125، CEA، LDH) في صف واحد عريض. - جداول الـ lookup كلها فارغة في نسخة قاعدة البيانات (لا بيانات seed)؛ المصطلحات السريرية تُبنى من إدخالات المستخدمين أثناء التشغيل.
drugsex.phpاسم مضلِّل (إدارة كتالوج الأدوية)، ويحتوي استعلامات DataTables مبنية بدمج نصوص معLIKE '%...%'مباشرة من المدخلات — قابلية حقن SQL.- جدول
semen2"عريض" (wide table): لكل فحص ثلاث أو أربع أعمدة (تاريخ/مكان/نتيجة) بدلًا من نمذجة الفحوصات كصفوف.
توصيات النقل إلى ERP
- إنشاء موديل
SemenAnalysisموحّد يدمجsemenوsemeninfertilityفي جدول واحد بأعمدة رقمية مُنمَّطة (volume، concentration، progressive_motility، total_motility، normal_forms، vitality، tzi، sdi، pus_cells) معpatient_idإلزامي وinfertility_sheet_idاختياري، وأعلام التصنيف (oligo/astheno/terato) كحقول boolean أو يُستغنى عنها بالحساب من القيم. - تطبيع جدول
semen2العريض إلى موديلAndrologyInvestigationبصيغة طولية: صف لكل فحص بأعمدةtype(scrotal_us, trus, karyotype, y_microdeletion, sdf, semen_fr, tese, other) وperformed_atوplaceوresult، مع جدول pivot لنتائج السونار متعددة القيم بدل السلاسل المفصولة بفواصل. - دمج جداول الـ lookup السبعة (
semen2result*وsemen2place*) في جدولين مرجعيين عامين:andrology_result_optionsوlab_placesمع عمود تمييزinvestigation_type، ودمجsemenplace/sementypeفي نفس البنية. - تطبيع الهرمونات: استبدال
hormonوhormonalprofileوhormonalprofile2بموديلHormoneResultطولي (patient_id،infertility_sheet_idاختياري،hormone_code،value،sampled_at) مع جدول مرجعيhormonesيشمل المدى الطبيعي والوحدة، وربطه بموديول المعمل في الـ ERP بدل تكرار البيانات؛ مع فصل دلالات الأورام عن هرمونات الخصوبة. - حذف الجدول اليتيم
sseemmenنهائيًا، وإعادة تسميةssemen/sseemen/sseemmeenإلى قوائم مرجعية بأسماء واضحة بعد التحقق من دلالتها السريرية مع العيادة (استنتاج: مصدر العينة وطريقة التحضير وحالتها)، وربطها بموديول IVF كحقول منمّطة في دورة الحقن. - تحويل كل التواريخ إلى نوع
DATEوالقيم الرقمية إلىDECIMALمع تنظيف البيانات أثناء الترحيل (قيم نصية حرة متوقعة)، واعتمادdeleted_at(SoftDeletes) بدل عمودdel. - إعلان مفاتيح أجنبية فعلية (
patient_id،doctor_id،infertility_sheet_id) واستبدال نقاط النهاية العامة (تحديث أي جدول/عمود من POST) بـ Form Requests وValidation وWhitelisting في Laravel وواجهات Angular مخصصة لكل نموذج. - إلغاء إنشاء السجلات الفارغة تلقائيًا عند فتح الشاشات، وتصفية السجلات الفارغة الموروثة أثناء الترحيل.
الموجات الصوتية والأشعة (Ultrasound & Imaging)
يغطي هذا الموديول كافة أنشطة التصوير التشخيصي بالعيادة: تقارير الموجات الصوتية للحمل (مسح تشريحي وقياسات حيوية لكل جنين على حدة)، وتقارير الموجات الصوتية النسائية، والموجات المهبلية (TVS) والدوبلر و(SIS) داخل ملف العقم، وأشعة الصبغة على الرحم (HSG)، ونتائج الرنين المغناطيسي والأشعة المقطعية، وقوائم حجز فحص الـ 4D المرتبطة بملف متابعة الحمل، إضافة إلى أرشيف الصور والفيديوهات المرفوعة لكل مريضة، وأداة الرسم التوضيحي التفاعلي (GT Image) لوضع علامات على مخطط تشريحي.
الوظائف الرئيسية
- إنشاء تقرير موجات صوتية للحمل متعدد الأجنة: سجل رئيسي للفحص وصف تفصيلي مستقل لكل جنين (مسح تشريحي كامل: الرأس، القلب، البطن، الكلى، العمود الفقري، الأطراف، النوع) مع قياسات حيوية (BPD, HC, AC, FL, CRL, NT) وتقدير عمر الحمل.
- الحفظ الفوري حقلاً بحقل عبر AJAX دون زر حفظ (نمط
update(table, column, value)عام في جميع شاشات الموديول). - إضافة جنين جديد أو حذفه مع تحديث عدد الأجنة
babynoتلقائياً، واعتماد التقرير نهائياً عند الطباعة (done = 1). - تقرير موجات صوتية نسائي شامل (وضع الرحم، سمك بطانة الرحم، المبيضان، كتل الحوض، شرايين الدوبلر، الاستنتاج) في سجل واحد مسطح.
- تسجيل فحوص TVS والدوبلر المهبلي وSIS وHSG داخل ملف العقم باختيارات متعددة من قوائم مفردات إكلينيكية (رحم، مبيض أيمن/أيسر، عنق الرحم، الحوض، الأنابيب).
- تسجيل نتائج HSG وUS-TV وMRI/CT كنصوص حرة (الرحم، الزائدتان، الحوض، الأنابيب) من شاشة الفحوصات الموحدة مع اسم الطبيب والتاريخ.
- حجز ومتابعة فحوص 4D: إنشاء تلقائي لسجل الحجز عند إدخال تاريخ الولادة المتوقع في ملف متابعة الحمل، واختيار الخدمات والمكان، وتتبع تنفيذ الفحص الأول والثاني والتأكيد.
- رفع صور الموجات (متعددة دفعة واحدة) وفيديوهات الفحص مع ملاحظات وتاريخ، وطباعة مجموعة صور مختارة بترويسة العيادة، وتنزيل الفيديو باسمه الأصلي.
- أداة GT Image: سحب وإفلات علامات مرقمة على صورة تشريحية أساسية مع تعليق لكل علامة وحفظ إحداثياتها (x, y, عرض, ارتفاع).
- عرض حقول الموجات (السائل الأمنيوسي، موضع المشيمة، الملاحظات) داخل زيارات متابعة الحمل عبر قوائم
usn / usaf / usplace.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
ultrasound | رأس تقرير الموجات الصوتية للحمل (النسخة القديمة) | patientid, edate, stype, based, babyno, sid, indication, gage, done, del | patients عبر patientid، awusers (فني الموجات) عبر sid |
ultrasounddetail | تفاصيل كل جنين في التقرير القديم (مسح تشريحي + قياسات) | ultrasoundid, heart, spine, kidney, gender, diameterm/p, headcm/p, abdominalm/p, lengthm/p, conclusion, weeks | ultrasound عبر ultrasoundid |
ultrasoundobst | رأس تقرير الموجات الصوتية للحمل (النسخة الأحدث) | patientid, edate, stype, babyno, sid, indication, limit, done | patients عبر patientid، awusers عبر sid |
ultrasoundobstdetail | تفاصيل كل جنين (يشمل قياسات الثلث الأول CRL وNT) | ultrasoundobstid, crownm/mc, nuchalm/c, diameterm/c, headcm/cc, flengthm/c, anomaly, gaestimatew/d, gender | ultrasoundobst عبر ultrasoundobstid |
ultrasoundgyna | تقرير الموجات الصوتية النسائي (سجل مسطح واحد) | patientid, edate, etype, position, thickness, rtsize, ltsize, rtfolicles, pmass, rtarteries, conclusion, done | patients عبر patientid، awusers عبر sid |
sonar | أرشيف صور وفيديوهات الموجات المرفوعة (الملفات على القرص) | patientid, sonardate, imagename, vediourl, originalname, notes, type (0 صورة / 1 فيديو), tempdelete | patients عبر patientid؛ ملفات في upload/sonar وupload/sonarvedio/1 |
tvs | فحص TVS داخل ملف العقم (اختيارات متعددة كنص CSV) | infertilitysheetid, tvsut, tvsro, tvslo, tvscx, tvspelvis, dtvsplace, comment, date | infertilitysheet عبر infertilitysheetid؛ قوائم tvs* عبر معرفات CSV |
tvscx | قائمة مفردات: نتائج عنق الرحم في TVS | title, del | tvs عبر tvscx (CSV) |
tvslo | قائمة مفردات: نتائج المبيض الأيسر في TVS | title, del | tvs عبر tvslo (CSV) |
tvspelvis | قائمة مفردات: نتائج الحوض في TVS | title, del | tvs عبر tvspelvis (CSV) |
tvsro | قائمة مفردات: نتائج المبيض الأيمن في TVS | title, del | tvs عبر tvsro (CSV) |
tvsut | قائمة مفردات: نتائج الرحم في TVS | title, del | tvs عبر tvsut (CSV) |
dtvs | فحص الدوبلر المهبلي داخل ملف العقم | infertilitysheetid, dtvsresult (CSV), date | infertilitysheet عبر infertilitysheetid؛ dtvsresult عبر CSV |
dtvsplace | قائمة مفردات: موضع الدوبلر المهبلي | title, del | tvs عبر dtvsplace (CSV) |
dtvsresult | قائمة مفردات: نتيجة الدوبلر المهبلي | title, del | dtvs عبر dtvsresult (CSV) |
ustv | سجل نتائج الموجات المهبلية من شاشة الفحوصات (نص حر) | patientid (varchar!), sdate, uterus, radnexa, ladnexa, pelvis, notes, doctorid | patients عبر patientid، awusers عبر doctorid |
usn | قائمة مفردات: ملاحظة الموجات في زيارة متابعة الحمل (استنتاج) | title, del | ancnewvisit عبر usn |
usaf | قائمة مفردات: السائل الأمنيوسي بالموجات (استنتاج) | title, del | ancnewvisit عبر usaf |
usplace | قائمة مفردات: موضع المشيمة بالموجات (استنتاج) | title, del | ancnewvisit عبر usplace |
four_d | قائمة مفردات: بنود خدمة فحص 4D | title, name, del | op_4d_list عبر four_d (CSV) |
op_4d_list | قائمة حجز ومتابعة تنفيذ فحوص 4D | patientid, ancsheetid, opdate, four_d (CSV), place, t1/t11/t12/t2/t21/t22, done, confirm, t1_userid, t2_userid | patients عبر patientid، ancsheet عبر ancsheetid، place عبر place، awusers عبر user_id |
gtimage | جلسة الرسم التوضيحي التفاعلي (صورة الأساس + التعليق) | gdate, patientid, doctorid, pic, comment, programview, del | patients عبر patientid، awusers عبر doctorid |
gtdetail | العلامات الموضوعة على الرسم (إحداثيات + تعليق) | gtid, posx, posy, width, height, imgno, comment, del | gtimage عبر gtid |
mrict | سجل نتائج الرنين المغناطيسي / الأشعة المقطعية (نص حر) | patientid (varchar!), sdate, uterus, radnexa, ladnexa, pelvis, notes, doctorid | patients عبر patientid، awusers عبر doctorid |
sis | فحص SIS (موجات بمحلول ملحي) داخل ملف العقم | infertilitysheetid, sisresult (CSV), date | infertilitysheet عبر infertilitysheetid؛ قائمة sisresult (موديول العقم) عبر CSV |
hsg | سجل نتائج أشعة الصبغة من شاشة الفحوصات (نص حر) | patientid (varchar!), sdate, uterus, rtube, ltube, smear, notes, doctorid | patients عبر patientid، awusers عبر doctorid |
hsginfertility | فحص HSG داخل ملف العقم (اختيارات من قوائم) | infertilitysheetid, hsgut, hsgplace, hsgrt (CSV), hsglt (CSV), hsgpelvis, date | infertilitysheet عبر infertilitysheetid؛ قوائم hsg* |
hsglt | قائمة مفردات: الأنبوب الأيسر في HSG | title, del | hsginfertility عبر hsglt (CSV) |
hsgpelvis | قائمة مفردات: الحوض في HSG | title, del | hsginfertility عبر hsgpelvis |
hsgplace | قائمة مفردات: مكان إجراء HSG | title, del | hsginfertility عبر hsgplace |
hsgrt | قائمة مفردات: الأنبوب الأيمن في HSG | title, del | hsginfertility عبر hsgrt (CSV) |
hsgut | قائمة مفردات: الرحم في HSG | title, del | hsginfertility عبر hsgut |
سير العمل (Workflow)
- يفتح الطبيب أو فني الموجات شاشة التقرير من ملف المريضة؛ إذا لم يوجد تقرير مفتوح يُنشأ تلقائياً سجل رأس جديد (
ultrasoundأوultrasoundobstأوultrasoundgyna) بتاريخ اليوم مع سطر تفاصيل افتراضي لجنين واحد. - تُملأ بيانات الفحص حقلاً بحقل (نوع الفحص، دواعي الإجراء، فني الموجات من مستخدمي النظام ذوي الوظيفة 4) ويُحفظ كل حقل فور تعديله عبر AJAX.
- في حالة الحمل المتعدد يضيف المستخدم سطر تفاصيل لكل جنين، ويستكمل المسح التشريحي (أكواد عددية) والقياسات الحيوية، وعند حذف جنين يُخفض عداد
babyno. - عند الطباعة يُعتمد التقرير نهائياً (
done = 1) ويظهر بعدها في قائمة التقارير المنجزة للمريضة، مع إمكانية الحذف المنطقي (del = 1). - من شاشة الفحوصات (
investigation.php) تُنشأ تلقائياً سجلات فارغة لـhsgوustvوmrictعند أول فتح، وتُسجل النتائج نصياً مع تاريخ الفحص واسم الطبيب. - داخل ملف العقم تُسجل فحوص TVS والدوبلر وSIS وHSG كصفوف مرتبطة بـ
infertilitysheetid، وتُختار النتائج من قوائم المفردات وتُخزن كمعرفات مفصولة بفواصل، وتظهر مجمعة في التقارير الشاملة (sh.php،Completesreport.php). - عند إدخال تاريخ الولادة المتوقع في ملف متابعة الحمل يُنشأ تلقائياً حجز 4D في
op_4d_listويُربط بالملف عبرancsheet.4d_list_id؛ ويدير قسم العمليات قائمة الحجوزات (الخدمات، المكان، علامات تنفيذ الفحص الأول والثاني والتأكيد). - تُرفع صور الفحص دفعة واحدة إلى
upload/sonarبأسماء عشوائية (md5) والفيديوهات إلىupload/sonarvedio/1مع حفظ الاسم الأصلي، وتُعرض في معرض زمني لكل مريضة مع الطباعة والتنزيل، والحذف منطقي فقط (tempdelete). - في أداة GT Image يُنشأ سجل جلسة جديد عند كل دخول، ويسحب المستخدم علامات مرقمة على الصورة التشريحية وتُحفظ إحداثياتها وتعليقاتها في
gtdetail.
الارتباط بالموديولات الأخرى
- موديول المرضى: جميع جداول الفحوص ترتبط بـ
patientsعبرpatientid. - موديول المستخدمين والصلاحيات: فني الموجات عبر
sidوالطبيب عبرdoctoridومنفذو فحص 4D عبرt1_userid / t2_useridإلىawusers.user_id(الفنيون هم المستخدمون ذووpositionid = 4). - موديول متابعة الحمل (ANC): حجوزات 4D عبر
op_4d_list.ancsheetid → ancsheet.idوالمؤشر العكسيancsheet.4d_list_id، وقوائمusn / usaf / usplaceتُستهلك من جدول زيارات المتابعةancnewvisit. - موديول العقم: فحوص
tvs / dtvs / sis / hsginfertilityمرتبطة بـinfertilitysheetعبرinfertilitysheetid، وقائمةsisresultتتبع موديول العقم. - موديول الفحوصات والمعامل: سجلات
hsg / ustv / mrictتُدار من شاشة الفحوصات الموحدةinvestigation.phpجنباً إلى جنب مع المعمل والمناظير. - موديول العمليات: قائمة 4D تُدار من
operations.phpوترتبط بقائمة الأماكنplaceعبرop_4d_list.place. - إعدادات النظام: صورة الأساس لأداة GT Image ووضع العرض من
programesetting. - التقارير المجمعة:
sh.phpوCompletesreport.phpوfullreport.phpتقرأ جداول الموديول لبناء التقرير الشامل للمريضة.
ملاحظات فنية
- ازدواجية واضحة:
ultrasound/ultrasounddetailوultrasoundobst/ultrasoundobstdetailنسختان متداخلتان (نحو 80% من الحقول مشتركة) وكلتاهما نشطتان في الكود؛ كما تتكرر بيانات HSG في ثلاثة مواضع (hsgنص حر،hsginfertilityقوائم، وحقول داخل ملفات أخرى). - الاختيارات المتعددة مخزنة كمعرفات مفصولة بفواصل في حقول varchar (مثل
tvs.tvsutوop_4d_list.four_d) وتُحل بالنمطid in (0$csv)— لا تكامل مرجعي ولا إمكانية استعلام فعالة. - لا توجد مفاتيح خارجية معلنة إطلاقاً؛ وكل العلاقات استُنتجت من أسماء الأعمدة وكود الكنترولرات.
- أخطاء أنواع بيانات:
patientidمن النوع varchar فيhsgوustvوmrict، وتواريخ مخزنة كـ varchar فيtvs / dtvs / sis / hsginfertility، وكل القياسات الرقمية (BPD وHC وغيرها) مخزنة كنصوص. - جدول
sonarهو الوحيد بمحرك MyISAM (بقية الجداول InnoDB)، والملفات تُخزن على القرص بأسماء md5 دون تحقق من النوع، ويُحذف الملف فعلياً عند الاستبدال بينما الحذف من الشاشة منطقي فقط (تظل الملفات على القرص). - ثغرات أمنية: بناء استعلامات SQL بدمج النصوص مباشرة (
patientidفيsonar.phpمثلاً)، ونقطة AJAX عامة تسمح بالكتابة في أي جدول/عمود يمرر من المتصفح (update(tableName, colName, value)). - خلل وظيفي:
gtimage.php?ac=indexيدرج سجل جلسة جديداً عند كل زيارة للصفحة مما يولد سجلات فارغة يتيمة؛ وكذلكinvestigation.phpيدرج صفوفhsg/ustv/mrictفارغة تلقائياً. - نسخة قاعدة البيانات (12-7-2024) لا تحتوي على أي بيانات أولية لقوائم المفردات (tvs*/hsg*/us*/four_d)؛ المفردات الفعلية موجودة فقط في قاعدة بيانات التشغيل ويجب تصديرها منها قبل الترحيل.
- دلالات أعلام
t1/t11/t12/t2/t21/t22في حجوزات 4D غير موثقة؛ المؤكد من الكود أن إدخالtscandate/ttscandateفي ملف المتابعة يرفعt11/t21(استنتاج: مراحل حجز/تنفيذ/سداد الفحصين الأول والثاني).
توصيات النقل إلى ERP
- إنشاء موديل موحد
ImagingStudy(نوع الدراسة: OBST_US, GYNA_US, TVS, DOPPLER_TVS, SIS, HSG, MRI, CT, 4D) يحل محل رؤوسultrasound / ultrasoundobst / ultrasoundgyna / ustv / mrict / hsgوصفوف فحوص ملف العقم، مع حالة (مسودة/معتمد) بدل العلمdone. - دمج
ultrasounddetailوultrasoundobstdetailفي موديل واحدFetalScanFinding(سجل لكل جنين) يضم الحقول المشتركة وحقول الثلث الأول، مع تخزين المسح التشريحي كـ JSON أو جدول قيم مرجعي بدلاً من 35+ عموداً مرمزاً. - توحيد 16 جدول مفردات صغيراً (
tvs*,hsg*,usn/usaf/usplace,dtvs*,four_d) في جدول واحدimaging_finding_optionsبعمودdomain، مع تصدير القيم من قاعدة التشغيل لا من النسخة الاحتياطية. - استبدال جميع حقول CSV بجداول وسيطة (Pivot) بعلاقات Many-to-Many حقيقية ومفاتيح خارجية مفروضة.
- ترحيل
sonarإلى نظام مرفقات قياسي (Spatie MediaLibrary أو تخزين S3) مع روابط موقعة بدلreadfile()، ونقل ملفاتupload/sonarوupload/sonarvedio/1مع الاحتفاظ بالاسم الأصلي وتاريخ الالتقاط والملاحظات. - تحويل
op_4d_listإلى موديلFourDScanBookingبحالة صريحة (Enum) بدل أعلام البتات، وعلاقة hasOne من سجل متابعة الحمل بدل المؤشر العكسي4d_list_id. - تحويل
gtimage / gtdetailإلىAnnotatedDiagram / DiagramMarkerبإحداثيات نسبية (%) وإصلاح إنشاء الجلسات الفارغة، أو إعادة بنائها كمكون Angular Canvas. - أثناء الـ ETL: تحويل
patientidالنصي إلى مفاتيح رقمية، وتحويل التواريخ والقياسات النصية إلى أنواع DATE وDECIMAL، وتوحيد أعلام الحذف (del / tempdelete / deleted) في SoftDeletes، ووسم كل سجل بجدول المصدر لتتبع الازدواجية بين النسختين القديمة والحديثة. - إلغاء نقطة التحديث العامة واستبدالها بـ FormRequests مخصصة لكل مورد مع تحقق من المدخلات وصلاحيات على مستوى السجل.
المناظير (لاباروسكوبي/هيستيروسكوبي) (Laparoscopy & Hysteroscopy)
موديول توثيق عمليات المناظير النسائية: منظار البطن (Laparoscopy) لفحص الرحم والأنابيب والمبايض والحوض، ومنظار الرحم (Hysteroscopy) لفحص عنق الرحم وتجويف الرحم وفتحتي الأنابيب. يعمل الموديول بنمطين متوازيين: نمط حر نصّي داخل شاشة الفحوصات (Investigations) لأي مريضة، ونمط منظّم بقوائم اختيار قابلة للتوسيع داخل شيت العقم (Infertility Sheet) يسجّل النتائج لكل عضو على حدة مع التدخل الجراحي والتكلفة، وتُستخدم البيانات في تقارير العمليات والتقارير الشاملة للمريضة.
الوظائف الرئيسية
- تسجيل تقرير منظار بطن نصّي حر لكل مريضة (الرحم، الزائدة اليمنى، الزائدة اليسرى، الحوض، ملاحظات) من تبويب LAPAROSCOPY في شاشة الفحوصات، مع إنشاء سجل فارغ تلقائيًا بتاريخ اليوم عند أول فتح للشاشة.
- تسجيل تقرير منظار رحم نصّي حر (عنق الرحم، التجويف الرحمي، الفتحة اليمنى، الفتحة اليسرى، ملاحظات) بنفس الآلية من تبويب HYSTEROSCOPY.
- تسجيل منظار بطن منظّم داخل شيت العقم: صف للنتائج لكل عضو (مكان الإجراء، الرحم UT، الأنبوب الأيمن RT، الأنبوب الأيسر LT، المبيض الأيمن RO، المبيض الأيسر LO، الحوض) وصف ثانٍ للتدخل الجراحي/الإدارة العلاجية لكل عضو (laparm*) مع نص التدخل والتكلفة.
- تسجيل منظار رحم منظّم داخل شيت العقم: التوسيع (Dil)، إدخال المنظار (Introd)، عنق الرحم (CX)، التجويف والقاع (Cavity-Fundus)، الفتحتان اليمنى واليسرى، ثم صف الإدارة العلاجية (copym*) مع نص التدخل والتكلفة.
- إضافة صفوف مناظير غير محدودة لكل شيت عقم عبر AJAX (أكشن
append)، وحفظ كل حقل لحظيًا عند التعديل (أكشنupdateالعام). - إثراء قوائم المصطلحات السريرية أثناء العمل: الطبيب يضيف مصطلحًا جديدًا لأي قائمة (lapar*/copy*) مباشرة من الشاشة عبر
getselectajaxدون الرجوع لشاشة إعدادات. - دعم الاختيار المتعدد للنتائج: تُخزَّن معرّفات القيم المختارة كسلسلة مفصولة بفواصل (CSV) في حقل واحد وتُفكّ عند العرض بـ
id in (...). - تقرير عمليات اليوم/فترة بحث: شاشة Operations تعرض عمليات المناظير (من جداول العقم) مع بيانات المريضة ومكان الإجراء، بالربط مع شيت العقم.
- إدراج نتائج المناظير في التقرير الشامل للمريضة (Complete Report) والتقرير الكامل (Full Report) مع اسم الطبيب المعالج، وفي تقارير الطباعة (sh.php وCompletesreport.php).
- إدارة قوائم نوع الشق الجراحي (
jncision: midline/transverse/paramedian/Pfannenstiel) والنوع الفرعي التابع له (midlinejncision: upper/lower...) كقائمتين متسلسلتين تُستخدمان في تفاصيل العمليات (Operative Details). - تتبّع آخر زيارة للمريضة (جدول
lastvisit) عند فتح شاشة العمليات باسم الكنترولر.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
laparoscopy | تقرير منظار بطن نصّي حر لكل مريضة (شاشة الفحوصات) | sdate, patientid, uterus, radnexa, ladnexa, pelvis, notes, doctorid, del | patients عبر patientid، awusers عبر doctorid |
hysteroscopy | تقرير منظار رحم نصّي حر لكل مريضة (شاشة الفحوصات) | sdate, patientid, cervix, uterine, rostium, lostium, notes, doctorid, del | patients عبر patientid، awusers عبر doctorid |
laparoscopyinfertility | سجل منظار بطن منظّم داخل شيت العقم: نتائج وتدخل لكل عضو + التكلفة | infertilitysheetid, date, laparplace, laparul, laparrt, laparlt, laparro, laparlo, laparpelvis, laparmut, laparmrt, laparmlt, laparmro, laparmlo, laparmpelvis, lapintervention, coast | infertilitysheet عبر infertilitysheetid، وجداول lapar* عبر معرّفات CSV |
hysteroscopyinfertility | سجل منظار رحم منظّم داخل شيت العقم: نتائج وإدارة علاجية + التكلفة | infertilitysheetid, date, copyplace, copydil, copyintrod, copycx, copycavity, copyrostium, copylostium, copymcx, copymcavity, copymrostium, copymlostium, hysintervention, coast | infertilitysheet عبر infertilitysheetid، وجداول copy* عبر معرّفات CSV |
laparplace | قائمة أماكن إجراء منظار البطن (مستشفى/مركز) | id, title, del | تُرجَع من laparoscopyinfertility.laparplace |
laparul | قائمة نتائج الرحم (UT) في منظار البطن | id, title, del | تُرجَع من laparoscopyinfertility.laparul (CSV) |
laparrt | قائمة نتائج الأنبوب الأيمن (RT) | id, title, del | تُرجَع من laparoscopyinfertility.laparrt (CSV) |
laparlt | قائمة نتائج الأنبوب الأيسر (LT) | id, title, del | تُرجَع من laparoscopyinfertility.laparlt (CSV) |
laparro | قائمة نتائج المبيض الأيمن (RO) | id, title, del | تُرجَع من laparoscopyinfertility.laparro (CSV) |
laparlo | قائمة نتائج المبيض الأيسر (LO) | id, title, del | تُرجَع من laparoscopyinfertility.laparlo (CSV) |
laparpelvis | قائمة نتائج الحوض في منظار البطن | id, title, del | تُرجَع من laparoscopyinfertility.laparpelvis (CSV) |
laparmut | قائمة التدخلات/الإدارة العلاجية للرحم (Management UT) | id, title, del | تُرجَع من laparoscopyinfertility.laparmut (CSV) |
laparmrt | قائمة تدخلات الأنبوب الأيمن (Management RT) | id, title, del | تُرجَع من laparoscopyinfertility.laparmrt (CSV) |
laparmlt | قائمة تدخلات الأنبوب الأيسر (Management LT) | id, title, del | تُرجَع من laparoscopyinfertility.laparmlt (CSV) |
laparmro | قائمة تدخلات المبيض الأيمن (Management RO) | id, title, del | تُرجَع من laparoscopyinfertility.laparmro (CSV) |
laparmlo | قائمة تدخلات المبيض الأيسر (Management LO) | id, title, del | تُرجَع من laparoscopyinfertility.laparmlo (CSV) |
laparmpelvis | قائمة تدخلات الحوض (Management Pelvis) | id, title, del | تُرجَع من laparoscopyinfertility.laparmpelvis (CSV) |
copyplace | قائمة أماكن إجراء منظار الرحم | id, title, del | تُرجَع من hysteroscopyinfertility.copyplace |
copydil | قائمة نتائج توسيع عنق الرحم (Dilatation) | id, title, del | تُرجَع من hysteroscopyinfertility.copydil |
copyintrod | قائمة نتائج إدخال المنظار (Introduction) | id, title, del | تُرجَع من hysteroscopyinfertility.copyintrod |
copycx | قائمة نتائج عنق الرحم (Cervix) في منظار الرحم | id, title, del | تُرجَع من hysteroscopyinfertility.copycx (CSV) |
copycavity | قائمة نتائج التجويف الرحمي والقاع (Cavity-Fundus) | id, title, del | تُرجَع من hysteroscopyinfertility.copycavity (CSV) |
copyrostium | قائمة نتائج فتحة الأنبوب اليمنى (R-Ostium) | id, title, del | تُرجَع من hysteroscopyinfertility.copyrostium |
copylostium | قائمة نتائج فتحة الأنبوب اليسرى (L-Ostium) | id, title, del | تُرجَع من hysteroscopyinfertility.copylostium |
copymcx | قائمة الإدارة العلاجية لعنق الرحم (Management Cervix) | id, title, del | تُرجَع من hysteroscopyinfertility.copymcx (CSV) |
copymcavity | قائمة الإدارة العلاجية للتجويف الرحمي | id, title, del | تُرجَع من hysteroscopyinfertility.copymcavity (CSV) |
copymrostium | قائمة الإدارة العلاجية للفتحة اليمنى | id, title, del | تُرجَع من hysteroscopyinfertility.copymrostium (CSV) |
copymlostium | قائمة الإدارة العلاجية للفتحة اليسرى | id, title, del | تُرجَع من hysteroscopyinfertility.copymlostium (CSV) |
jncision | قائمة أنواع الشق الجراحي (midline / transverse / paramedian / Pfannenstiel) | id, name, del | أب لـ midlinejncision؛ تُستخدم في operativedetails عبر jncisionid |
midlinejncision | قائمة الأنواع الفرعية للشق التابعة لكل نوع رئيسي (upper / lower / joel cohen...) | id, name, jncisionid, del | jncision عبر jncisionid؛ operativedetails عبر midlineid |
سير العمل (Workflow)
- المسار الأول (شاشة الفحوصات –
investigation.php): عند فتح ملف فحوصات المريضة، إن لم يوجد سجل منظار سابق يُنشأ تلقائيًا سجل فارغ فيlaparoscopyوآخر فيhysteroscopyبتاريخ اليوم ومعرّف الطبيب الحالي. - يدوّن الطبيب النتائج نصيًا في تبويبي LAPAROSCOPY وHYSTEROSCOPY، ويُحفظ كل حقل فور تعديله عبر AJAX (
updateElement→ أكشنupdate)، مع إمكانية إضافة سجلات بتواريخ جديدة أو حذف سجل (حذف منطقيdel=1). - المسار الثاني (شيت العقم –
infertilitysheet.php): من قسم Investigations في الشيت يضغط الطبيب «Hysteroscopy» أو «Laparoscopy» فيُنشأ صف جديد عبر أكشنappendمربوط بـinfertilitysheetidوبتاريخ اليوم. - يختار الطبيب النتائج لكل عضو من قوائم منسدلة (بعضها متعدد الاختيار)، وتُحمَّل القوائم من جداول
lapar*/copy*عبرgetselect، ويمكنه إضافة مصطلح جديد للقائمة فورًا عبرgetselectajaxأو حذف مصطلح عبرdeldataselect. - في الصف الثاني لكل منظار يسجّل الطبيب التدخل الجراحي النصّي (
lapintervention/hysintervention) والإدارة العلاجية لكل عضو (قوائمlaparm*/copym*) والتكلفة (coast). - شاشة العمليات (
operations.php) تعرض مناظير اليوم أو نتائج بحث بفترة/مريضة، بالربط بينlaparoscopyinfertility/hysteroscopyinfertilityوجدولinfertilitysheetلجلب بيانات المريضة، وتسجّل آخر زيارة فيlastvisit. - عند الطباعة أو التقارير:
sh.phpوCompletesreport.phpيفكّان معرّفات CSV إلى نصوصها من جداول القوائم، وcompletereport.phpيضم سجلات المناظير الحرة (غير الفارغة فقط) مع اسم الطبيب منawusers، وfullreport.phpيفحص وجود مناظير في الفترة المطلوبة. - في موديول تفاصيل العمليات (
operativedetails.php) تُستخدم قائمتاjncisionوmidlinejncisionكقائمتين متسلسلتين (اختيار نوع الشق يحمّل أنواعه الفرعية عبرloadjncision)، مع إمكانية إضافة أنواع جديدة من الشاشة نفسها.
الارتباط بالموديولات الأخرى
- موديول المرضى (patients): عبر
laparoscopy.patientidوhysteroscopy.patientid. - موديول المستخدمين/الأطباء (awusers): عبر
doctorid→awusers.user_idلعرض اسم الطبيب في التقارير. - موديول شيت العقم (infertilitysheet): عبر
laparoscopyinfertility.infertilitysheetidوhysteroscopyinfertility.infertilitysheetid، وتُعرض البيانات أيضًا داخل شيت النساء (gynasheet) للمريضة نفسها. - موديول الفحوصات (investigation): تبويبا المناظير جزء من شاشة الفحوصات إلى جوار HSG وUS-TV وMRI/CT.
- موديول العمليات وتقاريرها (operations / operativedetails): شاشة Operations تجمع المناظير مع العمليات الأخرى، وقائمتا
jncision/midlinejncisionتُستخدمان في تفاصيل العمليات عبرoperativedetails.jncisionidوoperativedetails.midlineid. - موديول التقارير (completereport / Completesreport / fullreport / sh): إدراج نتائج المناظير في التقارير المطبوعة والشاملة.
- تتبّع الزيارات (lastvisit): تسجيل آخر شاشة فتحت لملف المريضة عبر
lastvisit.patientid.
ملاحظات فنية
- ازدواجية تمثيل البيانات: نفس الإجراء السريري يُسجَّل بنمطين منفصلين تمامًا (جدولا
laparoscopy/hysteroscopyالنصّيان مقابلlaparoscopyinfertility/hysteroscopyinfertilityالمنظّمين) دون أي ربط بينهما. - الاختيار المتعدد مخزَّن كسلسلة CSV من المعرّفات داخل حقل
varcharواحد (مثلcopycx،laparrt) ويُفكّ بعبارةid in (0$csv)المبنية بدمج نصّي مباشر — مخالف للتطبيع وعرضة لحقن SQL. - استعلامات شاشة العمليات تبني شرط البحث بدمج متغيّرات الطلب نصيًا (
patientid، التواريخ) — ثغرة حقن SQL مؤكدة فيoperations.php. - كود
operations.phpيستعلم عنlaparoscopy/hysteroscopyبعمودdateغير الموجود (العمود الفعليsdate) ثم يقرأ منهماinfertilitysheetidغير الموجود أيضًا — كود ميت/معطّل على الأرجح (استنتاج). - تناقض دلالة الحذف المنطقي: قوائم الشيت تُحمَّل بشرط
del is nullبينما السجلات الرئيسية بشرطdel = 0، والحذف يضعdel = 1— خليط يصعب صيانته. - جداول القوائم الـ 26 (lapar*/copy*) متطابقة البنية (
id,title,del) وفارغة من البذور في النسخة الاحتياطية؛ المفردات السريرية تُبنى أثناء التشغيل من إدخالات الأطباء. - بيانات
jncision/midlinejncisionمليئة بصفوف تجريبية مهملة (sss، wwwaa، 444...) معظمها بحذف منطقي، مع خطأ إملائي متعمد في الاسم (jncision بدل incision وpfnnestiel بدل Pfannenstiel). - حقل التكلفة اسمه
coast(خطأ إملائي لـ cost) ونوعهvarcharوليس رقميًا، وحقلdateفي جداول العقمvarcharوليسdate. - أكشن
updateالعام يقبل اسم الجدول والعمود من الطلب مباشرة دون قائمة سماح — يمكّن تعديل أي جدول في قاعدة البيانات (ثغرة Mass Assignment). - إنشاء سجلات مناظير فارغة تلقائيًا عند فتح شاشة الفحوصات يولّد بيانات وهمية، وتضطر التقارير لترشيحها بشرط «غير فارغ» في
completereport.php.
توصيات النقل إلى ERP
- توحيد النمطين في نموذج واحد: جدول
endoscopy_procedures(Model:EndoscopyProcedure) بحقول:patient_id,infertility_sheet_id(اختياري),type(laparoscopy/hysteroscopy),performed_at,place_id,intervention,cost(decimal),notes,doctor_id. - تطبيع النتائج لكل عضو في جدول تفصيلي
endoscopy_findings(Model:EndoscopyFinding) بحقول:procedure_id,site(uterus/right_tube/left_tube/right_ovary/left_ovary/pelvis/cervix/cavity/r_ostium/l_ostium/dilatation/introduction),finding_term_id,category(finding/management) — بدلًا من 26 عمود CSV. - دمج جداول القوائم الـ 26 المتطابقة في جدول معجم واحد
endoscopy_terms(Model:EndoscopyTerm) بحقولscope(laparoscopy/hysteroscopy)،site،category،title،is_active، مع علاقة many-to-many عبر جدول pivot بدل CSV. - نقل
jncision/midlinejncisionإلى موديول العمليات كجدولincision_typesذاتي العلاقة (parent_id) مع تنقية الصفوف التجريبية المهملة وتصحيح الأسماء قبل الترحيل. - اعتماد Soft Deletes القياسية في Laravel (
deleted_at) بدل خليطdel = 0/1/null، وتحويلcoastإلىcost decimal(10,2)وdateالنصّي إلىdateحقيقي مع تنظيف الصيغ أثناء الترحيل. - استبدال أكشن
updateالعام بـ API Resources مخصصة مع Form Requests للتحقق وقوائم سماح للحقول، وإلغاء الإنشاء التلقائي للسجلات الفارغة (إنشاء السجل فقط عند الحفظ الفعلي). - أثناء الترحيل: استيراد سجلات
laparoscopy/hysteroscopyغير الفارغة فقط (بنفس منطق ترشيح التقرير الشامل)، وتفكيك حقول CSV إلى صفوف findings مع الحفاظ على المصطلحات المرجعية. - إعادة بناء تقرير العمليات في Angular كشاشة موحدة تستعلم من
endoscopy_proceduresمباشرة، بما يصحح الكود المعطّل الحالي فيoperations.php.
العمليات والولادات (Operations & Deliveries)
يغطي هذا الموديول الدورة الجراحية الكاملة في العيادة: حجز العمليات عبر قائمة انتظار يومية، وتسجيل المذكرة الجراحية التفصيلية (Operative Note) لكل مريضة شاملة التخدير ونوع الشق الجراحي والفريق الطبي والأدوية المستخدمة أثناء العملية مع ربطها بالصيدلية للصرف والمحاسبة، بالإضافة إلى تقارير يومية للعمليات والولادات ونتائج الباثولوجيا والأنسجة (Histopathology)، وخطابات التحويل إلى المستشفيات، وتقرير إنهاء الحمل (الولادة الطبيعية / القيصرية / الإجهاض).
الوظائف الرئيسية
- قائمة انتظار العمليات (Operation Waiting List): إضافة مريضة بتاريخ العملية ونوع العملية (متعدد الاختيار) ومكان الإجراء مع ملاحظات، وعرض القائمة مجمّعة حسب اليوم بأسماء الأيام بالعربية، مع تعديل وحذف منطقي وتتبع المستخدم المُدخل.
- تسجيل المذكرة الجراحية التفصيلية لكل مريضة: نوع العملية، التاريخ ووقت البداية والنهاية، دواعي الإجراء (Indication)، نوع التخدير الرئيسي والفرعي (قوائم متسلسلة)، أطباء التخدير والمساعدون (فريقان)، نوع الشق الجراحي (Incision) ونوعه الفرعي، الغسيل البريتوني، خطوات العملية، الطبقات والدرنقة والخيوط الجراحية، نقل الدم، المضاعفات والتوصيات.
- تسجيل أدوية العملية في شبكة (Grid) مرتبطة بكتالوج الأدوية، مع توليد روشتة تلقائية في الصيدلية (
recepittmp/receiptdrugs) لتمكين الصرف والتحصيل المالي. - إضافة عناصر القوائم المرجعية أثناء العمل مباشرة (عملية جديدة، نوع تخدير، نوع شق جراحي، مستشفى) دون مغادرة الشاشة.
- تقرير العمليات اليومي مع البحث بالفترة والمريضة، ويشمل عمليات شيت العقم (Operations / Hysteroscopy / Laparoscopy) مع نتيجة الأنسجة والتكلفة ومكان الإجراء، وطباعته.
- تقرير الولادات اليومي (Deliveries): يعرض ولادات اليوم من سجل الحمل (
awifep) مع طريقة الولادة ومكانها (place2) وبيانات التسجيل، مع البحث والطباعة. - تقرير إنهاء الحمل (Termination): استعلام عن حالات الولادة حسب نوع الإنهاء (طبيعي / قيصري / إجهاض ...) من السجل الوبائي للولادات السابقة
phobstetric. - خطاب تحويل المريضة إلى مستشفى: اختيار المستشفى من
hospitalnamesوتعليمات العملية وطباعة خطاب يتضمن الصيغة التوليدية (G/P/Ab) المحسوبة آليًا. - تسجيل نتائج الباثولوجيا للمريضة (Cytology / Histopathology) بتاريخ وطبيب من شاشة الفحوصات.
- قائمة انتظار السونار رباعي الأبعاد (4D) مرتبطة بشيت متابعة الحمل مع إرسال المريضة لقائمة زيارات اليوم برسوم كشف محددة.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
operation | قائمة مرجعية بأسماء العمليات الجراحية (تُستخدم في قائمة الانتظار والمذكرة الجراحية) | id, title, name, del | تُشار إليها من op_wait_list.operation وoperativedetails.operationid وoperations.operation |
operationids | جدول ربط قديم بين العملية والطبيب والمساعد — غير مستخدم في الكود الحالي (استنتاج: جدول مهجور) | doctorid, assistantid, operationid | awusers عبر doctorid/assistantid و operation عبر operationid (استنتاج) |
operations | سجل العمليات الموجزة المرتبط بشيت العقم (التاريخ، المكان، نتيجة الأنسجة، التكلفة) | infertilitysheetid, operation (قائمة IDs مفصولة بفواصل), date, place, histopath (CSV), cost, note | infertilitysheet عبر infertilitysheetid، operation و histopath و place عبر القيم المخزنة |
operativedetails | المذكرة الجراحية التفصيلية الكاملة لكل عملية (الجدول المحوري في الموديول) | patientid, operationid, date, timestart, timeend, indication, anasthesaid, generalid, anasthetstsid, assistantid, jncisionid, midlineid, peritonealwash, opsteps, layers, drains, suture, bloodtransfusion, complications, recommendation, del | patients عبر patientid، operation عبر operationid، anasthesa عبر anasthesaid، generalanasthesa عبر generalid، jncision/midlinejncision عبر jncisionid/midlineid، awusers عبر حقول الفريق (CSV) |
operativedetailsdrugs | أدوية العملية المعطاة أثناء الجراحة مع ربطها بروشتة الصيدلية | operationid, drugid, drugtype, drugdos, drugname, doctorid, recepittmpid, recepitdrugid, deleted | operativedetails عبر operationid، drugs عبر drugid، recepittmp عبر recepittmpid، receiptdrugs عبر recepitdrugid، awusers عبر doctorid |
op_wait_list | قائمة انتظار/حجز العمليات اليومية | patientid, opdate, operation (CSV), place, notes, deleted, user_id, createdate | patients عبر patientid، place عبر place، operation عبر القائمة المخزنة، awusers عبر user_id |
anasthesa | قائمة مرجعية لأنواع التخدير الرئيسية | id, name, del | تُشار إليها من operativedetails.anasthesaid وgeneralanasthesa.anasthesaid |
generalanasthesa | الأنواع الفرعية للتخدير (قائمة متسلسلة تابعة لنوع التخدير الرئيسي) | id, name, anasthesaid, del | anasthesa عبر anasthesaid، وتُشار إليها من operativedetails.generalid |
hospitalnames | قائمة مرجعية بأسماء المستشفيات لخطابات التحويل | id, name | تُستخدم في شاشة التحويل instruction.php (اختيار بالمعرّف دون تخزين دائم) |
histopath | قائمة مرجعية لنتائج فحص الأنسجة (Histopathology) | id, title, del | تُشار إليها من operations.histopath (قائمة IDs مفصولة بفواصل) |
pathology | نتائج الباثولوجيا للمريضة (خلايا وأنسجة) تُسجل من شاشة الفحوصات | sdate, patientid, cytology, histopathology, doctorid, del | patients عبر patientid، awusers عبر doctorid |
detections | كتالوج أنواع الكشوفات/الخدمات وأسعارها (يُستخدم هنا لتسعير زيارة سونار 4D عند الإرسال لقائمة الزيارات) | id, title, detectionval, del | تُشار إليها من visits.detectionid؛ معرّف الخدمة 36 ثابت في الكود لرسوم 4D |
place | قائمة مرجعية لأماكن إجراء العمليات | id, title, del | تُشار إليها من op_wait_list.place وoperations.place |
place2 | قائمة مرجعية لأماكن الولادة (مكررة وظيفيًا مع place) | id, title, del | تُشار إليها من registeration.place2 في تقرير الولادات |
سير العمل (Workflow)
- تُضاف المريضة إلى قائمة انتظار العمليات من شاشة
operations.php?ac=waiting_list: يُحدد تاريخ العملية ونوع/أنواع العملية (تُخزن كمعرّفات مفصولة بفواصل فيop_wait_list.operation) ومكان الإجراء منplaceمع الملاحظات، ويُسجل المستخدم وتاريخ الإدخال. - تُعرض قائمة الانتظار مجمعة باليوم (بأسماء الأيام العربية) خلال فترة محددة، أو قائمة العمليات المستقبلية لمريضة بعينها، مع إمكانية التعديل أو الحذف المنطقي (
deleted = 1). - يوم العملية تُفتح شاشة المذكرة الجراحية
operativedetails.php?ac=showdataللمريضة؛ يُنشئ النظام سجلًا فارغًا فيoperativedetailsفور فتح الشاشة، ثم تُحفظ كل خانة عبر AJAX حقلًا بحقل (نمط Inline Edit). - يُختار نوع التخدير من
anasthesaفتُحمَّل الأنواع الفرعية منgeneralanasthesaديناميكيًا، وكذلك نوع الشق الجراحي منjncisionثم نوعه الفرعي منmidlinejncision، ويُختار أطباء التخدير والمساعدون من مستخدمي النظام (awusers) حسب الدور والتخصص. - تُضاف أدوية العملية صفًا صفًا في
operativedetailsdrugs؛ عند اختيار الدواء يُنشئ النظام تلقائيًا روشتة مؤقتة (recepittmp) وبنود صرف (receiptdrugs) في موديول الصيدلية، فإذا كانت الروشتة محصّلة (status=1) تُفتح روشتة جديدة. - تظهر العمليات الموجزة المسجلة في شيت العقم (
operationsالمرتبط بـinfertilitysheet) في تقرير العمليات اليومي مع المنظار الرحمي والبطني، ويُبحث فيها بالفترة أو المريضة وتُطبع. - تقرير الولادات (
Deliveries.php) يعرض ولادات اليوم من سجلawifepمع طريقة الولادة وبيانات التسجيل ومكان الولادة منplace2، مع البحث والطباعة. - تقرير الإنهاء (
termination.php) يستعلم عن سجل الولادات السابقةphobstetricحسب نوع إنهاء الحمل المختار ويعرض بيانات المريضات. - عند الحاجة لتحويل المريضة لمستشفى تُستخدم شاشة التحويل في
instruction.php: اختيار المستشفى منhospitalnamesوتعليمات العملية، ويُطبع خطاب يتضمن الصيغة التوليدية المحسوبة من سجلات الولادة. - تُسجل نتيجة الباثولوجيا بعد العملية في جدول
pathologyمن شاشة الفحوصات (investigation.php) بتاريخ وطبيب.
الارتباط بالموديولات الأخرى
- موديول المرضى (Patients): عبر
operativedetails.patientidوop_wait_list.patientidوpathology.patientid. - موديول العقم (Infertility Sheet): جدول
operationsمرتبط بـinfertilitysheetidويُعرض ضمن شيت العقم وتقاريره. - موديول الصيدلية (Pharmacy): أدوية العملية تنشئ روشتات عبر
operativedetailsdrugs.recepittmpid→recepittmpوrecepitdrugid→receiptdrugs، والأدوية من كتالوجdrugs. - موديول الزيارات والمالية (Visits): إرسال مريضة 4D لقائمة الزيارات ينشئ سجل
visitsبرسوم منdetections(المعرّف 36 ثابت بالكود). - موديول متابعة الحمل (Antenatal): تقرير الولادات يقرأ
awifepوregisteration(مكان الولادة منplace2) وancsheetلقائمة 4D. - موديول التاريخ المرضي (History): تقرير الإنهاء يقرأ
phobstetric.obstermination، وخطاب التحويل يحسب الصيغة التوليدية منه. - المستخدمون والصلاحيات (awusers/awrole): فريق العملية (تخدير/مساعدون) يُختار من
awusersحسبrole_idوspecialidبقيم ثابتة في الكود.
ملاحظات فنية
- لا توجد مفاتيح أجنبية معلنة إطلاقًا؛ جميع العلاقات استُنتجت من أسماء الأعمدة واستعلامات الكنترولرات.
- تعدد القيم يُخزن كنصوص مفصولة بفواصل (CSV) في
op_wait_list.operationوoperations.operationوoperations.histopathوحقول فريق العملية الأربعة فيoperativedetails— يكسر التطبيع ويمنع الاستعلام السليم. - جدول
operationيحتوي عمودينtitleوnameيُستخدمان بالتبادل في شاشات مختلفة (قائمة الانتظار تقرأtitleوالمذكرة الجراحية تقرأname) — مصدر محتمل لبيانات غير متسقة. - جدول
operationidsغير مستخدم في أي كنترولر أو عرض — جدول مهجور قابل للإسقاط. - ازدواجية القوائم المرجعية:
place(أماكن العمليات) وplace2(أماكن الولادة) بنفس البنية تمامًا، إضافة إلىcopyplaceوlaparplaceفي موديولات مجاورة. - أنواع بيانات ضعيفة:
operations.dateوoperations.costنصوص varchar، وpathology.patientidvarchar بينما بقية الجداول int. - حقن SQL محتمل: تمرير
patientidوparentidوtermtypeبالتسلسل النصي مباشرة في الاستعلامات (operations.php و operativedetails.php و termination.php). - فتح شاشة المذكرة الجراحية يُنشئ سجلًا فارغًا فورًا، ما يولّد سجلات يتيمة عند إغلاق الشاشة دون إدخال.
- قيم ثابتة بالكود (Hardcoded): معرّف خدمة 4D = 36 في
sendToVisits، وأدوار/تخصصات الفريق الجراحي (role_id 4/6 و specialid 1-4)، ودلالات نوع الإنهاء (1 = ولادة طبيعية، 2 = قيصرية). - أسلوبا حذف منطقي مختلطان:
del(NULL/0/1) في القوائم المرجعية مقابلdeleted(0/1) في جداول الحركة. - بيانات القوائم المرجعية المزروعة في النسخة تحتوي قيم تجريبية مهملة (مثل صفوف jncision: "sss"، "www") محذوفة منطقيًا فقط.
توصيات النقل إلى ERP
- إنشاء نماذج Laravel أساسية:
SurgicalBooking(بديلop_wait_list)،OperativeNote(بديلoperativedetails)،OperativeNoteDrug،InfertilityOperation(بديلoperations)،PathologyResult، مع قوائم مرجعية:Procedure،AnesthesiaType/AnesthesiaSubtype،IncisionType/IncisionSubtype،Hospital،HistopathologyFinding. - تطبيع كل الحقول متعددة القيم (CSV) إلى جداول Pivot:
booking_procedures،operation_procedures،operation_histopath_findings، وoperative_note_staff(بعمود دور: anesthetist / assistant) بدلاً من أربعة أعمدة CSV. - توحيد
placeوplace2(ومثيلاتهماcopyplaceوlaparplace) في جدول واحدlocationsبعمود نوع (مكان عملية / مكان ولادة)، وتوحيد عموديtitle/nameفي جدول العمليات المرجعي إلى عمود واحد مع ترحيل القيمتين. - إسقاط جدول
operationidsالمهجور بعد التحقق من خلو بياناته الإنتاجية، وتنقية صفوف الاختبار المحذوفة منطقيًا في القوائم المرجعية قبل الترحيل. - تحويل الأنواع:
dateإلى نوع تاريخ حقيقي، وcostإلى decimal، وpatientidفي pathology إلى مفتاح أجنبي رقمي، مع إعلان قيود المفاتيح الأجنبية كاملة. - استبدال نمط "إنشاء سجل فارغ عند فتح الشاشة + حفظ حقل بحقل" بنموذج إدخال يُحفظ دفعة واحدة عبر Form Request مع Validation، أو مسودة صريحة بحالة (draft/final).
- نقل تكامل الصيدلية إلى خدمة (Service) موحدة لإنشاء الروشتات بدل المنطق المكرر داخل الكنترولر، وربط أدوية العملية بوحدة المخزون/الفوترة في الـ ERP بأحداث (Events).
- نقل القيم الثابتة (رسوم 4D، أدوار الفريق، أنواع الإنهاء) إلى جداول إعدادات أو Enums معرفة بدل أرقام مزروعة في الكود.
- توحيد الحذف المنطقي باستخدام SoftDeletes القياسية في Laravel (
deleted_at) في جميع الجداول. - في واجهة Angular: فصل الشاشات إلى مكونات (قائمة الانتظار، المذكرة الجراحية بقوائم متسلسلة، تقارير العمليات/الولادات) مع APIs REST موثقة بدلاً من قوالب Smarty المختلطة.
الفحص الإكلينيكي والتشخيص (Clinical Examination & Diagnosis)
يغطي هذا الموديول تسجيل الفحص العام للمريضة (الوزن، الطول، مؤشر كتلة الجسم، ضغط الدم، النبض، سكر الدم العشوائي) مع نتائج الفحص لكل جهاز من أجهزة الجسم (الرأس والرقبة، الصدر والقلب، البطن، الحوض، الأطراف)، بالإضافة إلى قوائم نتائج الفحص الموضعي والعام (الثدي، الشعرانية، الغدة الدرقية)، ومحرك أسئلة وأجوبة قابل للتهيئة للتاريخ المرضي الحالي (Present History)، وكتالوجَي التشخيصات لعيادتي النساء ومتابعة الحمل.
الوظائف الرئيسية
- تسجيل عدة فحوصات عامة للمريضة الواحدة مرتبة تنازليًا بالتاريخ، مع تسجيل اسم الطبيب الفاحص من جدول المستخدمين
awusers. - إضافة صف فحص جديد فارغ فورًا عبر AJAX (
addNewRow)، ثم تعبئة كل خلية على حدة بالحفظ التلقائي الفوري (Inline AJAX update) دون زر حفظ. - حساب مؤشر كتلة الجسم (BMI) تلقائيًا في الواجهة من الوزن والطول، مع قناع إدخال لضغط الدم (حقلان:
b_pوbp2). - إدخال نتيجة فحص كل جهاز إما كنص حر أو من قائمة منسدلة معرّفة مسبقًا، حسب أعلام التهيئة (
head,chest,abdomen,pelvis,extremitis) في جدولprogramesetting. - إضافة قيمة جديدة لقوائم نتائج الفحص أثناء العمل مباشرة (
addexitem) مع ربطها فورًا بسجل الفحص الجاري. - حذف منطقي (Soft Delete) لسجلات الفحص عبر العلم
del. - إدارة بنك أسئلة التاريخ المرضي الحالي (
presenthistoryquestions) وإجاباتها (presenthistoryanswers) من شاشة إعداد مستقلة، مع ترتيب عرض الأسئلة (displayorder) وتمييز إجابات مفضلة (favorite). - تسجيل إجابات المريضة على أسئلة التاريخ المرضي بتاريخ زيارة محدد من شاشة الجيناكولوجي (تُخزن في جدول
gynaph) مع إمكانية الطباعة والاستعراض حسب التاريخ. - كتالوج تشخيصات لزيارات النساء (
diagnosis) وآخر لزيارات متابعة الحمل (diagnosisant)، مع اختيار متعدد يُخزن كقائمة مفصولة بفواصل في حقل الزيارة، وإضافة تشخيص جديد أثناء الزيارة. - قوائم نتائج الفحص الموضعي والعام (الثدي متعدد الاختيار، الشعرانية، الغدة الدرقية، الفحص الموضعي) تُستخدم في شيتات العقم والجيناكولوجي وتُخزن في أعمدة جدول
infertilitysheet. - كتالوج تفاصيل التخدير العام (
generalanasthesa) كمستوى فرعي تابع لنوع التخدير (anasthesa) ويُستخدم في شاشة تفاصيل العمليات.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
examination | سجل الفحص العام للمريضة (علامات حيوية + ملخص فحص الأجهزة) | patientid, doctorid, examinationdate, weight, height, bmi, b_p, bp2, pulse, rgb, headandneck, chestandheart, abdomen, pelvis, extremitis, del | patients عبر patientid، awusers عبر doctorid |
examinationhead | قائمة نتائج فحص الرأس والرقبة | id, name, del | examination عبر headandneck (استنتاج: يُخزن المعرف أو النص) |
examinationchest | قائمة نتائج فحص الصدر والقلب | id, name, del | examination عبر chestandheart |
examinationabdomen | قائمة نتائج فحص البطن | id, name, del | examination عبر abdomen |
examinationpelvis | قائمة نتائج فحص الحوض | id, name, del | examination عبر pelvis |
examinationextremitis | قائمة نتائج فحص الأطراف | id, name, del | examination عبر extremitis |
examinationlocalse | قائمة نتائج الفحص الموضعي (النسائي) — اختيار متعدد | id, title, del | infertilitysheet عبر examinationlocalse (قائمة معرفات بفواصل) |
generalbreast | قائمة نتائج فحص الثدي — اختيار متعدد | id, title, del | infertilitysheet عبر generalbreast (قائمة معرفات بفواصل) |
generalhirsutism | قائمة درجات الشعرانية (Hirsutism) | id, title, del | infertilitysheet عبر generalhirsutism |
generalthyroid | قائمة نتائج فحص الغدة الدرقية | id, title, del | infertilitysheet عبر generalthyroid |
generalanasthesa | تفاصيل/أنواع فرعية للتخدير العام تابعة لنوع التخدير الرئيسي | id, name, anasthesaid, del | anasthesa عبر anasthesaid، operativedetails عبر anasthesaid (موديول العمليات) |
diagnosis | كتالوج تشخيصات زيارات النساء (الجيناكولوجي) | id, name, conditions (يُستخدم كحذف منطقي), title, del | gyna عبر diagnosisid (قائمة معرفات بفواصل) |
diagnosisant | كتالوج تشخيصات زيارات متابعة الحمل (Antenatal) | id, name, conditions (حذف منطقي) | antenalvisit عبر diagnosisid (قائمة معرفات بفواصل) |
presenthistoryquestions | بنك أسئلة التاريخ المرضي الحالي (فئات) | id, name, displayorder, deleted | presenthistoryanswers عبر presenthistorycatid، gynaph عبر catid |
presenthistoryanswers | الإجابات المعرفة مسبقًا لكل سؤال تاريخ مرضي | id, presenthistorycatid, name, favorite, deleted | presenthistoryquestions عبر presenthistorycatid، gynaph عبر answerid |
سير العمل (Workflow)
- يفتح الطبيب ملف المريضة ثم تبويب الفحص (
examination.php?ac=index)؛ تُعرض جميع سجلات الفحص السابقة (غير المحذوفة) مرتبة بالتاريخ تنازليًا مع اسم الطبيب لكل سجل. - تقرأ الشاشة إعدادات
programesetting؛ فإذا كان علم الجهاز (رأس/صدر/بطن/حوض/أطراف) لا يساوي 1 تُحمَّل قائمته المنسدلة من جدول اللوكب المقابل، وإلا يظهر حقل نص حر. - عند الضغط على "إضافة" يُنشأ صف فحص فارغ فورًا في قاعدة البيانات (
addNewRow) بتاريخ اليوم ومعرف الطبيب من الجلسة، ويُعاد جزء HTML للصف الجديد. - تُحفظ كل خلية (وزن، طول، ضغط، نبض، نتيجة كل جهاز...) تلقائيًا عند مغادرتها عبر دالة
updateالعامة التي تستقبل اسم الجدول والعمود والقيمة من الواجهة، ويُحسب الـ BMI تلقائيًا في المتصفح. - يمكن إضافة قيمة جديدة لأي قائمة نتائج أثناء الفحص (
addexitem)؛ تُدرج في جدول اللوكب ثم يُحدَّث عمود سجل الفحص بمعرف القيمة الجديدة. - الحذف يتم منطقيًا بوضع
del = 1(delData). - في شاشة الإعداد
addpresenthistory.phpيُدير المسؤول أسئلة التاريخ المرضي الحالي وإجاباتها: إضافة سؤال (يأخذ ترتيب عرض تاليًا تلقائيًا)، إضافة إجابات لكل سؤال، تمييز مفضلة، وحذف منطقي. - أثناء زيارة الجيناكولوجي (كنترولر
gyna.php) تُعرض الأسئلة في أعمدة حسبdisplayorder(مجموعات 1-3، 4-6، 7-9، 10-12، أكبر من 12، وصفر = أخرى)، وتُحفظ الإجابات المختارة لكل تاريخ في جدولgynaphمع معرف المريضة والطبيب، مع إمكانية الطباعة والحذف حسب التاريخ. - في زيارة النساء يختار الطبيب تشخيصات متعددة من كتالوج
diagnosisفتُخزن معرفاتها كنص مفصول بفواصل فيgyna.diagnosisid؛ وبنفس الآلية تُخزن تشخيصاتdiagnosisantفيantenalvisit.diagnosisidلزيارات الحمل، مع إمكانية إضافة تشخيص جديد للكتالوج أثناء الزيارة. - في شيتات العقم والجيناكولوجي تُختار نتائج فحص الثدي والشعرانية والدرقية والفحص الموضعي من قوائم
generalbreastوgeneralhirsutismوgeneralthyroidوexaminationlocalseوتُخزن في أعمدة جدولinfertilitysheet، وتُفك ترميزها عند طباعة التقارير الكاملة (sh.php,Completesreport.php).
الارتباط بالموديولات الأخرى
- موديول المرضى:
examination.patientid→patients.id. - موديول المستخدمين والصلاحيات:
examination.doctorid→awusers.user_id، مع فحص الصلاحيات عبرrole_idفي الجلسة. - موديول إعدادات البرنامج: أعلام
programesetting.head/chest/abdomen/pelvis/extremitisتتحكم في إظهار القوائم المنسدلة مقابل النص الحر. - موديول زيارات النساء (Gyna):
gyna.diagnosisid→ معرفاتdiagnosis(CSV)، وgynaph.catid/answerid→presenthistoryquestions/presenthistoryanswers. - موديول متابعة الحمل (Antenatal):
antenalvisit.diagnosisid→ معرفاتdiagnosisant(CSV). - موديول شيت العقم: أعمدة
infertilitysheet.generalbreast/generalhirsutism/generalthyroid/examinationlocalse→ جداول اللوكب المقابلة. - موديول العمليات:
generalanasthesa.anasthesaid→anasthesa.id، وتُستهلك فيoperativedetails.php. - موديول التقارير:
sh.phpوCompletesreport.phpوcombinedreport.phpتفك ترميز معرفات الفحص والتشخيص للطباعة. - موديول الإعداد العام:
setup.phpيصنفdiagnosisوdiagnosisantضمن الجداول المسموح تفريغها، بينماgeneralanasthesaمحمي من الحذف.
ملاحظات فنية
- لا توجد مفاتيح أجنبية معلنة إطلاقًا؛ كل العلاقات مستنتجة من أسماء الأعمدة واستعلامات الكنترولرات.
examination.patientidمن نوعvarchar(191)بينماpatients.idرقمي — عدم تطابق أنواع.- جميع القيم السريرية الرقمية (الوزن، الطول، BMI، الضغط، النبض) والتواريخ مخزنة كـ
varcharبلا أي تحقق من الصحة. - أعمدة فحص الأجهزة في
examinationتخزن محتوى مختلطًا: نصًا حرًا أحيانًا ومعرف لوكب رقميًا أحيانًا أخرى (دالةaddexitemتكتب المعرف في نفس العمود النصي) — خطر جسيم على جودة البيانات عند الترحيل. - الاختيار المتعدد (التشخيصات، الثدي، الفحص الموضعي) يُخزن كنص مفصول بفواصل (CSV) داخل عمود واحد — مخالف للتطبيع الأول (1NF) ويستلزم جداول وسيطة عند الترحيل.
- عمود
conditionsفيdiagnosis/diagnosisantيُستخدم فعليًا كعلم حذف منطقي (1 = محذوف) رغم اسمه المضلل، إلى جانب وجود عمودdelآخر غير مستخدم فيdiagnosis. - دالة
examination::update()لا تتضمن أي فحص لتسجيل الدخول أو الصلاحيات، وتقبل اسم الجدول والعمود مباشرة من طلب POST — ثغرة تتيح تعديل أي جدول/عمود (Mass Assignment). كذلكdelDataوaddexitemيقبلان اسم الجدول من العميل. - تقارير
sh.phpوCompletesreport.phpتبني استعلامات SQL بدمج نصي مباشر (id in (0$var)) — سطح هجوم لحقن SQL. - جدول
gynaph(إجابات التاريخ المرضي الفعلية للمريضات) غير موجود في ملف الـ SQL Dump رغم استخدامه في الكود — يُنشأ غالبًا وقت التشغيل بواسطة RedBeanPHP في الوضع المرن (استنتاج). - جداول اللوكب كلها فارغة في هذا الـ Dump (
AUTO_INCREMENT=1)؛ المفردات السريرية الفعلية موجودة فقط في قاعدة بيانات الإنتاج. - منطق تجميع أسئلة التاريخ المرضي في أعمدة العرض (1-3، 4-6...) مكتوب صراحة (Hardcoded) داخل
gyna.phpاعتمادًا على قيمdisplayorder. - ازدواجية كتالوجات:
diagnosisوdiagnosisantمتطابقا البنية تقريبًا ومفترقان فقط حسب نوع العيادة.
توصيات النقل إلى ERP
- إنشاء موديل
ClinicalExamination(جدولclinical_examinations) بمفاتيح أجنبية حقيقيةpatient_idوdoctor_id، وأنواع صحيحة:decimalللوزن والطول والـ BMI، أعمدةsystolic/diastolic/pulseأعدادًا صحيحة، وdateلتاريخ الفحص، معSoftDeletes. - دمج جداول اللوكب الخمسة لفحص الأجهزة مع
examinationlocalseوgeneralbreastوgeneralhirsutismوgeneralthyroidفي جدول موحدexamination_finding_optionsبعمود تمييزbody_system(head_neck, chest_heart, abdomen, pelvis, extremities, local, breast, hirsutism, thyroid) بدلًا من تسعة جداول متطابقة البنية. - إنشاء جدول وسيط
examination_findings(examination_id, body_system, finding_option_id قابل للفراغ, free_text قابل للفراغ) لفصل النص الحر عن المعرفات، مع سكربت ترحيل ينظف المحتوى المختلط الحالي (رقم = معرف لوكب، غير ذلك = نص حر). - دمج
diagnosisوdiagnosisantفي كتالوج واحدdiagnosesبعمودspecialty(gyna/antenatal)، واستبدال أعمدة CSV بجدول وسيطvisit_diagnosis(morph أو visit_id + diagnosis_id)، مع التفكير في إسناد التشخيصات إلى ترميز ICD-10 مستقبلًا. - ترحيل محرك التاريخ المرضي إلى ثلاثة موديلات:
HistoryQuestionوHistoryAnswerOption(معis_favorite) وPatientHistoryAnswer(يحل محلgynaph) بمفاتيح أجنبية لـpatient_idوvisit_dateوdoctor_id، واستبدال منطق التجميع المكتوب صراحة بعمودdisplay_groupصريح. - إنشاء
AnesthesiaTypeوAnesthesiaSubtype(يحل محلanasthesaوgeneralanasthesa) بعلاقةbelongsToصريحة، ويُستهلك من موديول العمليات. - توحيد الحذف المنطقي على
deleted_at(Laravel SoftDeletes) بدلًا من الأعلام الثلاثة المتضاربةdelوdeletedوconditions. - فرض التحقق من الصحة (Form Requests) والتفويض (Policies) على جميع نقاط التعديل، وإلغاء نمط "اسم الجدول والعمود من العميل" نهائيًا واستبداله بنقاط API محددة الموارد (RESTful) في Laravel مع واجهات Angular Reactive Forms.
- الإبقاء على ميزة الحفظ التلقائي خلية-بخلية في واجهة Angular (PATCH على حقول مسماة بقائمة بيضاء) لأنها جوهرية في سير عمل العيادة.
- تصدير محتوى جداول اللوكب من قاعدة الإنتاج (وليس هذا الـ Dump الفارغ) قبل الترحيل لبناء بيانات الـ Seeders الخاصة بالمفردات السريرية.
التاريخ المرضي الشامل (Patient Medical History)
موديول مركزي لتوثيق التاريخ المرضي الكامل لمريضة النساء والتوليد على مستوى المريضة (وليس الزيارة): تاريخ الدورة الشهرية، وسائل منع الحمل السابقة، تاريخ الولادات والحمل السابق، الأمراض الطبية السابقة، العمليات الجراحية والنسائية السابقة، محاولات الإخصاب المساعد السابقة (IUI/IVF/ICSI) بتفاصيلها المعملية، والتاريخ العائلي للأمراض. تظهر هذه البيانات كملخص في رأس صفحة المريضة وتُستهلك في جميع الشيتات الطبية والتقارير.
الوظائف الرئيسية
- تسجيل سجلات متعددة لتاريخ الدورة الشهرية لكل مريضة: سن البلوغ
menarche، مدة الدورة، طول الدورة، الانتظام، كمية الطمث، عسر الطمث، وتاريخ آخر دورةphl_mp(LMP) المستخدم في حسابات الحمل. - تسجيل وسائل منع الحمل السابقة (نوع الوسيلة، المدة، تاريخ الإيقاف، ملاحظات).
- توثيق تاريخ الولادات السابقة (Obstetric History): مدة الحمل، طريقة انتهاء الحمل (ولادة طبيعية/قيصرية/إجهاض/حمل خارج الرحم/حمل عنقودي)، مكان الولادة، التاريخ، وبيانات حتى 3 أطفال لكل حمل (النوع، الجنس، الوزن، الاسم) لدعم التوائم.
- حساب الصيغة التوليدية (عدد القيصريات/الطبيعي/الإجهاض/الحمل خارج الرحم) تلقائياً وعرضها في رأس بيانات المريضة في كل الشاشات.
- تسجيل الأمراض الطبية السابقة والعمليات الجراحية العامة والعمليات النسائية السابقة مع السنة واسم الجرّاح والملاحظات.
- توثيق محاولات الإخصاب المساعد السابقة (IUI/IVF/ICSI/تجميد) مع المركز والسنة، وتفاصيل معملية لكل محاولة ICSI: عدد البويضات المسحوبة
opu، درجات البويضات GI/GII/GV، عدد الأجنة المنقولة، الأجنة المجمدة، نتيجة تحليل الحمل bhcg، ونبض الجنين fhr. - عرض دورات التنشيط الداخلية المكتملة (Monitoring Sheets) داخل صفحة التاريخ كجزء من تاريخ ART الداخلي.
- تسجيل التاريخ العائلي (المرض + صلة القرابة + ملاحظات).
- إضافة قيم جديدة لقوائم الاختيار (الانتظام، كمية الطمث، أنواع منع الحمل، أنواع العمليات، مراكز الإخصاب... إلخ) مباشرة من نفس الشاشة دون مغادرتها (inline lookup creation)، مع تعديل أسماء عناصر القوائم.
- التحرير الخلوي المباشر (inline cell editing) لأي حقل عبر دالة
updateعامة تستقبل اسم الجدول والعمود من الواجهة. - حذف منطقي (soft delete) لأي سجل تاريخ عبر العلم
del. - وضع عرض مبسّط بديل (Simple View) يعرض تشخيصات مبسطة بدلاً من نموذج التاريخ الكامل حسب إعدادات البرنامج، مع إمكانية إظهار/إخفاء كل قسم من أقسام التاريخ من جدول الإعدادات.
- إدارة بنك أسئلة "الشكوى الحالية" (Present History) كقوائم أسئلة وإجابات مع ترتيب عرض ومفضلة، تُستهلك في شيتات الكشف.
- تصدير بيانات التاريخ المرضي تلقائياً إلى ملف Excel خارجي عند فتح الصفحة (عبر
execلتشغيلexcel.php).
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
phmenstrual | سجلات تاريخ الدورة الشهرية لكل مريضة (آخر دورة LMP، البلوغ، المدة، الانتظام...) | patientid, menarche, duration, length, phregularity, phamount, phdysmenorrhoea, phl_mp, doctorid, del | patients عبر patientid، awusers عبر doctorid، phregularity/phamount/phdysmenorrhoea عبر الأعمدة المسماة بنفس الاسم |
phregularity | قائمة اختيار: انتظام الدورة (regular, irregular, menopause...) | name, del | تُرجع من phmenstrual.phregularity |
phamount | قائمة اختيار: كمية دم الطمث (مثل excessive) — وليس مبلغاً مالياً | name, del | تُرجع من phmenstrual.phamount |
phdysmenorrhoea | قائمة اختيار: عسر الطمث | name, del | تُرجع من phmenstrual.phdysmenorrhoea |
phcontraception | سجلات وسائل منع الحمل السابقة للمريضة | patientid, contype, contduration, contstopped, contranote, doctorid, del | patients عبر patientid، phcontracttype عبر contype، awusers عبر doctorid |
phcontracttype | قائمة اختيار: أنواع وسائل منع الحمل (IUD, OC, DMPA, Mirena, Condom...) | name, del | تُرجع من phcontraception.contype |
phobstetric | سجل الولادات/حالات الحمل السابقة، صف لكل حمل مع بيانات حتى 3 أطفال (توائم) | patientid, obstrduration, obstermination, obsplace, obsdate, outcomeid, babytype/babygendernew/babyweight/babyname (+ مكررة 1 و2), doctorid, del | patients عبر patientid، phobstericterminate عبر obstermination، phobstericterplace عبر obsplace، awusers عبر doctorid |
phobstericterminate | قائمة اختيار: طريقة انتهاء الحمل (SVD, CS, Ectopic, Abortion, V.mole) | name, del | تُرجع من phobstetric.obstermination؛ تُستخدم بمعرّفات ثابتة في حساب الصيغة التوليدية |
phobstericterplace | قائمة اختيار: مكان الولادة/انتهاء الحمل | name, del, patientid (عمود شاذ غير مستخدم — استنتاج) | تُرجع من phobstetric.obsplace |
phpastmedical | الأمراض الطبية السابقة للمريضة (مع علم للزوج) | patientid, medicaldisease, medicalnote, for_husband, doctorid, del | patients عبر patientid، phpastmedicaldisease عبر medicaldisease |
phpastmedicaldisease | قائمة اختيار: أسماء الأمراض الطبية السابقة | name, del | تُرجع من phpastmedical.medicaldisease |
phpastsurgical | العمليات الجراحية العامة السابقة (مع السنة والجرّاح وعلم للزوج) | patientid, surgicaloperation, phsurgicalyear, phsurgicalsurgeon, surgicalnote, for_husband, doctorid, del | patients عبر patientid، phpastsurgicaloperation عبر surgicaloperation |
phpastsurgicaloperation | قائمة اختيار: أسماء العمليات الجراحية | name, del | تُرجع من phpastsurgical.surgicaloperation |
phpastgynecological | العمليات النسائية السابقة (مع السنة والجرّاح) | patientid, gynecologicaloperation, gynecologicalyear, gynecologicalsurgeon, gynecologicalnote, doctorid, del | patients عبر patientid، phpastgynecologicaloperation عبر gynecologicaloperation |
phpastgynecologicaloperation | قائمة اختيار: أسماء العمليات النسائية | name, del | تُرجع من phpastgynecological.gynecologicaloperation |
phpastart | محاولات الإخصاب المساعد السابقة (IUI/IVF/ICSI/Cryo) بالمركز والسنة وبيانات تجميد الأجنة | patientid, arttype, artcenter, artyear, artnote, emdate, emembryos, straw1, doctorid, del | patients عبر patientid، phpastarttype عبر arttype، phpastartcenter عبر artcenter |
phpastarttype | قائمة اختيار: نوع المحاولة (IUI, IVF, ICSI, cryo, failed) | name, del | تُرجع من phpastart.arttype (القيم 2 و3 = IVF/ICSI مُعاملة بمنطق خاص في الكود) |
phpastartcenter | قائمة اختيار: مراكز الإخصاب التي أجريت بها المحاولات السابقة | name, del | تُرجع من phpastart.artcenter |
phpasticsi | التفاصيل المعملية لمحاولة ICSI/IVF سابقة (سجل ابن لكل صف في phpastart) | partentid, patientid, opu, gi, gii, gv, et, etf, frozen, bhcg, fhr | phpastart عبر partentid، patients عبر patientid |
phfamily | التاريخ العائلي للمريضة (مرض + صلة قرابة + ملاحظة) | patientid, family_disease, family_relative, familynote, doctorid, del | patients عبر patientid، phfamilydisease عبر family_disease، phfamilyrelative عبر family_relative |
phfamilydisease | قائمة اختيار: الأمراض العائلية | name, del | تُرجع من phfamily.family_disease |
phfamilyrelative | قائمة اختيار: صلة القرابة | name, del | تُرجع من phfamily.family_relative |
medicalhistory | قائمة اختيار: أمراض طبية للزوجة تُستخدم في شيت العقم (DM, HTN, SLE...) — كتالوج موازٍ منفصل عن phpastmedicaldisease | title, del | infertilitysheet عبر العمود النصي medicalhistory (قائمة معرفات مفصولة بفواصل) |
medicalhistorydm | قائمة اختيار: أمراض طبية للزوج في شيت العقم (varicocele, smoking, STD...) — اللاحقة dm تعني الزوج/الذكر (استنتاج من القيم) | title, del | infertilitysheet عبر medicalhistorydm (قائمة مفصولة بفواصل) |
surgicalhistory | قائمة اختيار: عمليات جراحية للزوجة في شيت العقم (myomectomy, ov cystectomy...) | title, del | infertilitysheet عبر surgicalhistory (قائمة مفصولة بفواصل) |
surgicalhistorydm | قائمة اختيار: عمليات جراحية للزوج في شيت العقم (varicocelectomy, herniorrhaphy...) | title, del | infertilitysheet عبر surgicalhistorydm (قائمة مفصولة بفواصل) |
familyhistory | قائمة اختيار: التاريخ العائلي في شيت العقم (DM, HTN, cancer...) — كتالوج موازٍ منفصل عن phfamilydisease | title, del | infertilitysheet عبر familyhistory (قائمة مفصولة بفواصل) |
سير العمل (Workflow)
- يفتح الطبيب صفحة «Patient History» (
patienthistory.php) بعد اختيار المريضة؛ إذا لم تُحدد مريضة يُعاد التوجيه للصفحة الرئيسية. - حسب إعداد
programesetting.simpleviewيُعرض إما نموذج مبسّط (تشخيصات بسيطة) أو النموذج الكامل بسبعة أقسام: الدورة الشهرية، منع الحمل، الولادات، الأمراض السابقة، الجراحات، العمليات النسائية، محاولات ART، والتاريخ العائلي، مع تحميل كل قوائم الاختيار وسجلات المريضة السابقة لكل قسم. - عند الضغط على «إضافة صف» في أي قسم تُستدعى دالة AJAX (مثل
addnewmenstural,addnewobstetric,addnewpastart...) تنشئ فوراً سجلاً فارغاً في قاعدة البيانات مرتبطاً بالمريضة والطبيب الحالي بتاريخ اليوم، وتُعيد صف HTML جديداً (قالب Smarty جزئي مثلnewMenstrualRow.html). - يملأ الطبيب الحقول مباشرة داخل الجدول؛ كل تغيير في خلية يستدعي الدالة العامة
updateالتي تستقبل اسم الجدول والعمود والقيمة وتحفظ مباشرة (حفظ خلوي لحظي بدون زر حفظ). - في قسم ART، عند إدخال تفاصيل معملية لمحاولة IVF/ICSI تُنشأ/تُحدّث تلقائياً سجلة ابنة في
phpasticsiمربوطة بـpartentid، كما تُعرض دورات التنشيط الداخلية المكتملة منmointoringsheetضمن نفس القسم. - إذا لم تكن القيمة المطلوبة موجودة في قائمة الاختيار، يضيفها المستخدم من نفس الشاشة فتُحفظ في جدول القائمة (مثل
phcontracttype) ويُحدَّث سجل المريضة فوراً بالمعرف الجديد؛ ويمكن أيضاً تعديل اسم عنصر قائمة عبرeditselect/updateselect. - الحذف يتم منطقياً برفع العلم
del=1عبرdelRows. - عند فتح الصفحة تُسجَّل المريضة في قائمة تصدير Excel (
excelinfopatients) ويُشغَّل سكربتexcel.phpفي الخلفية لتصدير بياناتها. - ملخص التاريخ (آخر دورة LMP، الصيغة التوليدية المحسوبة من
phobstetricبمعرّفات ثابتة للقيصرية/الطبيعي/الإجهاض...) يُعرض في رأس بيانات المريضة (_patientdata.php/_phmain.php) في كل شاشات الكشف والشيتات. - بشكل منفصل، شاشة
addpresenthistory.phpتُدير بنك أسئلة «الشكوى الحالية» (presenthistoryquestions/presenthistoryanswers) بترتيب عرض ومفضلة، وتُستهلك إجاباتها في شيتات الكشف.
الارتباط بالموديولات الأخرى
- موديول المرضى (patients): كل جداول السجلات ترتبط بالمريضة عبر
patientid، وتقرير الإنهاءات يربطphobstetric.patientidبجدولpatientsمباشرة. - موديول المستخدمين/الأطباء (awusers): كل سجل يحمل
doctoridالذي يُترجم لاسم الطبيب عبرawusers.user_id. - موديول شيت العقم (infertilitysheet): الكتالوجات
medicalhistory,medicalhistorydm,surgicalhistory,surgicalhistorydm,familyhistoryتُخزَّن كقوائم معرفات مفصولة بفواصل داخل أعمدةinfertilitysheetوتُفك في التقارير (sh.php,Completesreport.php). - موديول متابعة التنشيط (mointoringsheet): صفحة التاريخ تعرض الدورات المكتملة (
status=1) عبرmointoringsheet.patientidكتاريخ ART داخلي. - موديول الزيارات والشيتات (gynasheet, infertilitysheet, ancsheet, antenalvisit): تعرض ملخص التاريخ عبر
_phmain.phpو_patientdata.php(آخر LMP والصيغة التوليدية). - موديول التقارير (fullreport, completereport, combinedreport, termination, excel): يقرأ جداول
ph*لطباعة التقرير الكامل وتقرير الإنهاءات والتصدير إلى Excel. - موديول دمج المرضى (merge.php): ينقل كل سجلات
ph*من المريضة المكررة إلى الأصلية عند الدمج. - موديول الإعدادات (programesetting): أعلام إظهار/إخفاء أقسام التاريخ (
menstrual,contraception,obstetric,past,family,art...) ووضعsimpleviewومسار PHP لتصدير Excel. - موديول الشكوى الحالية:
presenthistoryquestions/presenthistoryanswersعبرpresenthistorycatid(يُدار منaddpresenthistory.phpويُستهلك في شيتات الكشف).
ملاحظات فنية
- لا توجد مفاتيح أجنبية معلنة إطلاقاً؛ كل العلاقات ضمنية، وكثير من أعمدة الربط نصية
varcharبدلاً منint(مثلphmenstrual.patientidوphobstetric.obstermination). - ازدواجية كتالوجات: يوجد كتالوجان منفصلان للأمراض (
phpastmedicaldiseaseمقابلmedicalhistory) وللجراحات وللتاريخ العائلي — أحدهما لشاشة التاريخ والآخر لشيت العقم — بنفس المعنى السريري تقريباً. - جداول شيت العقم تخزن المعرفات كقوائم نصية مفصولة بفواصل (comma-separated IDs) وتُفك بـ
id IN (0$list)عبر حقن نص مباشر في SQL — مخاطرة أمنية وتصميم غير معياري. - دوال
updateوdelRowsتستقبل اسم الجدول والعمود من المتصفح مباشرة وتمررها إلى ORM دون قائمة سماح (whitelist) — ثغرة تتيح تعديل أي جدول؛ ودالةdelRowsommedelبلا أي تحقق من الجلسة. - منطق الصيغة التوليدية في
_patientdata.phpيعتمد على معرّفات ثابتة مكتوبة في الكود (1=SVD، 2=CS، 3=Ectopic، 4=Abortion، 5=V.mole) رغم أن القائمة قابلة للتعديل من المستخدم. phobstetricغير معياري: بيانات حتى 3 أطفال في أعمدة مكررة (babytype,babytype1,babytype2...) بدل جدول أطفال مستقل، وعمودoutcomeidيقلبbabygendernewبمنطق خاص.- الكود يقرأ أعمدة غير موجودة في مخطط 2024 (
phpastart.ovdate,freezdate,phpasticsi.notes) — تُنشأ ديناميكياً بواسطة RedBeanPHP في وضع fluid (استنتاج)، ما يدل على انجراف مخطط غير موثق. - عمود
patientidداخل جدول القائمةphobstericterplaceشاذ ولا يُستخدم في الكود المقروء. - التواريخ مخزنة كـ
varcharفي معظم الجداول (sysdate,obsdate) ما يضعف الفرز والاستعلام، وسنوات العمليات نصوص حرة. - بيانات القوائم في نسخة 2024 فارغة بينما نسخة 2021 تحتوي القيم الفعلية، مع تلوث واضح بقيم تجريبية محذوفة منطقياً (aaaa, 777...) وقيم مكررة (DM ثلاث مرات في
familyhistory). - إنشاء الصف الفارغ في قاعدة البيانات قبل إدخال أي بيانات (insert-then-edit) يترك سجلات فارغة كثيرة إذا تراجع المستخدم.
- استدعاء
exec()لتشغيل تصدير Excel عند كل فتح للصفحة — عبء أداء ونمط غير آمن.
توصيات النقل إلى ERP
- إنشاء موديولات Laravel واضحة لكل قسم:
MenstrualHistory,ContraceptionHistory,ObstetricHistory(+ جدول ابنObstetricBabyيلغي الأعمدة المكررة الثلاثية),PastMedicalHistory,PastSurgicalHistory,PastGynecologicalHistory,PastArtCycle(+PastArtIcsiDetailأو دمجها كأعمدة في نفس الجدول),FamilyHistory— جميعها بمفتاح أجنبي حقيقيpatient_idوdoctor_id. - توحيد القوائم في جدول مرجعي واحد متعدد الأنواع
lookup_values(type + name + is_active) أو جداول Eloquent صغيرة، مع دمج الكتالوجات المزدوجة:medicalhistoryمعphpastmedicaldisease، وsurgicalhistoryمعphpastsurgicaloperation، وfamilyhistoryمعphfamilydisease. - استبدال أعمدة القوائم المفصولة بفواصل في شيت العقم بجداول pivot معيارية (many-to-many) مثل
infertility_sheet_medical_historiesمع تمييز الزوج/الزوجة بعمودfor_husbandبدلاً من جداول*dmمنفصلة. - تحويل كل التواريخ إلى أعمدة
date/timestampحقيقية، وتحويل أعمدة الربط النصية إلىunsignedBigIntegerمع قيود مفاتيح أجنبية، واستخدامsoftDeletesالقياسية بدل العلمdel. - استبدال جدول
phobstericterminateالقابل للتعديل بـEnum ثابت (SVD/CS/Ectopic/Abortion/V.mole) لأن منطق الصيغة التوليدية يعتمد على هذه القيم؛ وحساب G/P في خدمة Domain Service مختبَرة بدل الاستعلامات المتناثرة. - إغلاق الثغرات أثناء النقل: إلغاء أي endpoint عام يستقبل أسماء جداول/أعمدة من العميل، واعتماد Form Requests وValidation وPolicy لكل عملية، وإلغاء
exec()لصالح Laravel Queue/Export (مكتبة Laravel Excel). - تنقية البيانات قبل الترحيل: حذف صفوف القوائم التجريبية والمكررة، ودمج القيم المتطابقة، واستبعاد السجلات الفارغة الناتجة عن نمط insert-then-edit.
- نقل بنك أسئلة الشكوى الحالية إلى جدولي
present_history_questions/present_history_answersبعلاقة hasMany مع ترتيب عرض ومفضلة. - في واجهة Angular، الإبقاء على تجربة «الحفظ اللحظي للصف» لكنها عبر نماذج Reactive Forms مع إنشاء السجل عند أول حفظ فعلي (وليس عند فتح الصف) لتفادي السجلات الفارغة.
المتابعة وكروت المتابعة (Follow-up & Follow-up Cards)
يدير هذا الموديول متابعة الحمل للمريضة عبر "ملف متابعة" واحد نشط لكل حمل (تاريخ آخر دورة LMP، تاريخ الولادة المتوقع EDD، تاريخ IVF، عدد مرات الحمل والولادة G/P)، مع سجلات زمنية للزيارات والتشخيصات والفحوصات والتحاليل، إضافة إلى "كروت متابعة" قابلة للطباعة لكل زيارة عيادة تتضمن التشخيص والأدوية الموصوفة وترتبط بالصيدلية، وأخيراً مكتبة تعليمات نصية للمريضات تُطبع عند الطلب مع خطابات تحويل للمستشفيات.
الوظائف الرئيسية
- إنشاء ملف متابعة حمل تلقائياً عند أول دخول لشاشة المتابعة (سجل
followupبحالة 0 = جارٍ) مع حساب EDD تلقائياً (LMP + 9 أشهر + 7 أيام) وتاريخ IVF (LMP + 9 أشهر − 7 أيام). - تسجيل زيارات المتابعة الدورية: الوزن، ضغط الدم، عمر الحمل GA (يُحسب بالأسابيع من LMP)، نتيجة الموجات فوق الصوتية، وملاحظات — مع تنبيه إذا كان تاريخ الزيارة أقدم من LMP.
- إضافة صفوف تشخيص وفحص إكلينيكي وتحاليل/أشعات مؤرخة عبر استدعاءات AJAX، مع تحرير خلوي مباشر (inline edit) لأي حقل وحذف منطقي (
del = 1). - كتابة روشتات أدوية داخل شاشة المتابعة (جدول
followupdrugsيُنشأ وقت التشغيل) مع تمييز روشتة الزوجة عن الزوج (forhusband)، وعرض أرشيف الروشتات حسب التاريخ وطباعتها. - أرشفة ملفات الحمل المنتهية (
status = 1) وعرض تفاصيل أي حمل سابق كاملاً (زيارات/تشخيصات/فحوصات/تحاليل) من شاشة الأرشيف. - إنشاء كارت متابعة لكل زيارة عيادة (
followupcard) يلتقط تاريخ الدخول من آخر زيارة في جدولvisitsوقسم الكشف منdetectionsواسم الطبيب من المستخدم الحالي. - إضافة أدوية الكارت (
followupcarddrugs) من كتالوج الأدوية مع النوع والجرعة، وعند اعتماد الكارت تُنشأ روشتة صيدلية تلقائياً (recepittmp+receiptdrugs) لتسعيرها وتحصيلها في الصيدلية. - طباعة كارت المتابعة (التشخيص + الأدوية + بيانات المريضة والقسم) وإعادة طباعته لاحقاً دون إعادة إرساله للصيدلية.
- إدارة مكتبة تعليمات للمريضات (
instruction: عنوان + محتوى نصي منسق) مع إضافة وتعديل وحذف منطقي، واختيار عدة تعليمات وطباعتها باسم المريضة وتاريخ اليوم. - إصدار خطاب تحويل إلى مستشفى من نفس كنترولر التعليمات: يجمع بيانات الحمل الحالي من
mainantenentalوالتاريخ الولادي والمرضي والجراحي، مع اختيار المستشفى وتعليمات العمليات وطباعة الخطاب.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
followup | ملف متابعة الحمل الرئيسي (ملف واحد نشط لكل مريضة، ويؤرشف عند انتهاء الحمل) | patientid, history, lmp, eed, ivf, g, p, status | patients عبر patientid |
followupvisit | زيارة متابعة دورية (وزن، ضغط، عمر الحمل، سونار، ملاحظات) | followid, date, wt, bp, ga, us, notes, del | followup عبر followid |
followupdiagnosis | سطر تشخيص مؤرخ داخل ملف المتابعة | followid, date, diagnosis, del | followup عبر followid |
followupexam | سطر فحص إكلينيكي مؤرخ داخل ملف المتابعة | followid, date, exam, del | followup عبر followid |
followupinvest | سطر تحاليل/أشعات مطلوبة مؤرخ داخل ملف المتابعة (نص حر) | followid, date, invest, del | followup عبر followid |
followupcard | كارت متابعة الزيارة القابل للطباعة (تشخيص + فترة الزيارة + الطبيب + القسم) | patientid, doctorid, enterdate, exitdate, date, diagnosis, status, deleted, deptid | patients عبر patientid، awusers عبر doctorid، detections عبر deptid (مأخوذ من visits.detectionid) |
followupcarddrugs | أدوية كارت المتابعة (الدواء، النوع، الجرعة) وربطها بروشتة الصيدلية | cardid, drugid, drugtype, drugdos, recepittmpid | followupcard عبر cardid، drugs عبر drugid، recepittmp عبر recepittmpid |
instruction | مكتبة تعليمات نصية للمريضات قابلة للطباعة | patientid, name, content, tempdelete | patients عبر patientid (نظرياً فقط — القيمة ثابتة بـ 1 في الكود، فهي عملياً مكتبة عامة) |
سير العمل (Workflow)
- تدخل الممرضة/الطبيب شاشة المتابعة من ملف المريضة (
followup.php?patientid=N)؛ إن لم يوجد ملف متابعة نشط (status = 0) يُنشأ تلقائياً بسجلfollowupجديد بقيمة LMP = اليوم، وتُحسب EDD وIVF، وتُضاف أول زيارة فارغة فيfollowupvisit. - تُعرض الشاشة أربع قوائم مؤرخة (زيارات، تشخيصات، فحوصات، تحاليل) تنازلياً، ويُحسب عمر الحمل لكل زيارة بالأسابيع من LMP، مع تعليم الزيارات الأقدم من LMP كغير منطقية.
- يضيف الطبيب صفوفاً جديدة عبر AJAX (
newvisit/newdiag/newexam/newinv) ثم يحرر القيم خلية بخلية عبر دالةupdateالعامة (اسم الجدول والعمود والقيمة تُرسل من المتصفح)، وتعديل LMP يعيد حساب EDD وIVF فوراً. - يكتب الطبيب روشتة اليوم من نفس الشاشة (تُحفظ في جدول
followupdrugsغير الموجود بالـ dump — يُنشأ وقت التشغيل)، ويمكن عرض أرشيف الروشتات بالتواريخ منفصلة للزوجة والزوج وطباعة أي منها بقالبgyna/print.html. - عند انتهاء الحمل يُغلق الملف (
status = 1) ويظهر في شاشة الأرشيف (archive)، ومن هناك تُفتح تفاصيل أي حمل سابق للقراءة عبرpregdetail. - بالتوازي، في كل زيارة عيادة يفتح الطبيب شاشة كارت المتابعة (
followupcard.php?ac=addit)؛ يُنشأ كارت جديد (status = 0) يلتقط تاريخ آخر زيارة منvisitsوقسمها (detectionid)، ويُسجل التشخيص ويضاف الدواء سطراً سطراً من كتالوجdrugs. - عند الحفظ/الطباعة (
printit) يُعتمد الكارت (status = 1)، وتُحفظ الأدوية فيfollowupcarddrugs، وتُنشأ روشتة مؤقتة في الصيدلية (recepittmpبمصدرdrugstablename = followupcarddrugs) مع سطورreceiptdrugsليتم تحصيلها وصرفها من موديول الصيدلية، ثم يُطبع الكارت. - شاشة عرض الكروت (
index) تُظهر كل الكروت المعتمدة للمريضة مع اسم الطبيب وقائمة الأدوية مجمعة، مع إمكانية إعادة الطباعة فقط (yesOnly) أو الحذف المنطقي. - في موديول التعليمات: تُدار مكتبة التعليمات (إضافة/تعديل/حذف منطقي عبر
tempdelete)، ويختار المستخدم مجموعة تعليمات لطباعتها باسم المريضة ولقبها (منwifetypes) وتاريخ اليوم. - من نفس كنترولر التعليمات تُصدر خطابات التحويل للمستشفيات: تُجمع بيانات الحمل الحالي من
mainantenentalوآخر سونار منmainantenentalusوالتاريخ المرضي/الجراحي/النسائي من جداولph*، ويُختار المستشفى منhospitalnamesوتعليمات العمليات منoperationinstructionsثم يُطبع الخطاب.
الارتباط بالموديولات الأخرى
- موديول المرضى (patients): عبر
followup.patientidوfollowupcard.patientid، مع قراءة ألقاب الزوجة/الزوج منwifetypesوhusbandtypesعند الطباعة. - موديول الزيارات والاستقبال (visits / detections):
followupcard.enterdateيُلتقط من آخرvisits.visitdate، وfollowupcard.deptidمنvisits.detectionid(جدول أقسام الكشفdetections). - كتالوج الأدوية (drugs): عبر
followupcarddrugs.drugidوfollowupdrugs.drugid، مع قراءة التصنيفات والأنواع والجرعات المميزة من نفس الجدول لملء القوائم. - موديول الصيدلية (recepittmp / receiptdrugs): اعتماد كارت المتابعة ينشئ روشتة صيدلية كاملة عبر
followupcarddrugs.recepittmpidوrecepittmp.drugstablename = 'followupcarddrugs'لتحصيلها لاحقاً. - المستخدمون والصلاحيات (awusers / roles):
followupcard.doctoridيشير إلىawusers.user_id، وكل دالة محمية بفحص الدخول والصلاحية حسبrole_id. - موديول متابعة الحمل الرئيسي (mainantenental / mainantenentalus): خطاب التحويل في كنترولر التعليمات يقرأ الحمل الحالي وبيانات السونار منهما (تداخل وظيفي مع موديول ANC).
- التاريخ المرضي (phobstetric / phpastmedical / phpastsurgical / phpastgynecological): تُجمع في خطاب التحويل لحساب G/P وسرد الأمراض والعمليات السابقة.
- إعدادات البرنامج (programesetting): تُقرأ في كل شاشات العرض والطباعة (ترويسة العيادة وبيانات الطباعة).
ملاحظات فنية
- جدول
followupdrugs(روشتات شاشة المتابعة) مستخدم بكثافة في الكود لكنه غير موجود في ملف الـ SQL dump إطلاقاً — يُنشأ تلقائياً وقت التشغيل بواسطة RedBeanPHP في الوضع المرن (fluid)، وهذه فجوة خطيرة في توثيق المخطط يجب حصرها قبل الترحيل. - دوال
updateوdelتستقبل اسم الجدول واسم العمود من المتصفح مباشرة وتكتب بهما عبرR::load— ثغرة Mass Assignment تتيح تعديل أي جدول في قاعدة البيانات من أي مستخدم مصرح له بالموديول. - في
instruction.phpيُحذف السجل بسلسلة SQL مُركّبة نصياً:UPDATE instruction SET tempdelete = 1 WHERE id = ' . $id— ثغرة SQL Injection محتملة، وعدة دوال (مثلaddopinstوgetinstdetail) فحوصات الصلاحية فيها معطلة بالتعليق. - خطأ منطقي في
followupcard.phpسطر 270: استخدام=(إسناد) بدلاً من==داخل شرطif، فالشرط صحيح دائماً. instruction.patientidمكتوب ثابتاً بقيمة 1 عند الإضافة والتعديل — العمود بلا معنى فعلي والجدول عملياً مكتبة عامة غير مرتبطة بمريضة.- لا توجد مفاتيح أجنبية معلنة في أي جدول؛ كل العلاقات استنتاجية من أسماء الأعمدة وكود الكنترولرات، وتتعدد أنماط الحذف المنطقي (
delوdeletedوtempdeleteوstatus). - ازدواجية وظيفية واضحة: شاشة المتابعة
followupتكاد تطابق موديول ANC الرئيسي (mainantenentalوملحقاته) — نفس مفاهيم LMP/EDD/زيارات/روشتات، وكنترولر التعليمات يحتوي منطق تحويل مستشفيات لا علاقة له بالتعليمات. - تواريخ EDD/IVF تُحسب بسلاسل
strtotimeنصية (LMP + 9 أشهر ± 7 أيام) بدلاً من قاعدة Naegele القياسية (LMP + 280 يوماً)، وعمر الحمل يُعاد حسابه في الكود ولا يُخزن إلا نصياً فيfollowupvisit.ga. - الجداول
followupcardوfollowupcarddrugsبترميز latin1 بينما البقية utf8mb4 — خطر تلف النصوص العربية في حقل التشخيص. - أخطاء قاعدة البيانات تُبتلع بصمت (
catchفارغ) في معظم الدوال، ولا يوجد أي تسجيل (logging) أو تحقق من المدخلات.
توصيات النقل إلى ERP
- إنشاء موديل Laravel رئيسي
Pregnancy(يدمجfollowupمعmainantenentalفي كيان واحد للحمل — استنتاج مدعوم بتطابق الحقول) بحقول:patient_id,lmp,edd,ivf_date,gravida,para,status(enum: active/closed) مع حساب EDD كـ Accessor بقاعدة Naegele. - إنشاء موديل
AntenatalVisit(يستوعبfollowupvisit) بحقول رقمية مُهيكلة:weight(decimal)،bp_systolic/bp_diastolic،gestational_age_weeksمحسوب،ultrasound_notes، معpregnancy_idكمفتاح أجنبي حقيقي. - توحيد
followupdiagnosisوfollowupexamوfollowupinvestفي موديل واحدClinicalNoteبعمودtype(enum: diagnosis/examination/investigation) لأن بنيتها متطابقة تماماً (followid + date + text + del)، أو ربط التشخيص بقاموس ICD-10 مستقبلاً. - إنشاء موديل
EncounterأوVisitCard(يحل محلfollowupcard) مرتبط بـVisitوDepartmentوUserبمفاتيح أجنبية معلنة، مع موديلPrescription+PrescriptionItemموحد يستبدلfollowupcarddrugsوfollowupdrugsوجداول الروشتات المتناثرة في باقي الموديولات (نمط مصدر واحد للروشتة يغذي الصيدلية عبر Event/Job بدلاً من الكتابة المباشرة فيrecepittmp). - نقل
instructionإلى موديلInstructionTemplateكمكتبة قوالب عامة (إسقاط عمودpatientidالعديم الفائدة)، وفصل منطق خطاب التحويل إلى خدمة مستقلةReferralLetterServiceمع موديلReferralيؤرشف الخطابات الصادرة بدلاً من الطباعة دون أثر. - استبدال التحرير الخلوي العام (tableName/colName من المتصفح) بـ API Endpoints محددة مع FormRequest Validation وPolicies لكل عملية، وإغلاق ثغرتي Mass Assignment وSQL Injection نهائياً.
- توحيد الحذف المنطقي على
SoftDeletesالقياسية في Laravel (deleted_at)، وترحيل البيانات مع تحويل ترميز جدولي latin1 إلى utf8mb4 والتحقق من سلامة النصوص العربية. - قبل الترحيل: عمل dump حي من قاعدة الإنتاج لالتقاط مخطط
followupdrugsالفعلي وأي جداول أخرى أنشأها RedBeanPHP وقت التشغيل وغير موجودة في النسخة الاحتياطية المرجعية.
التحاليل والفحوصات (Investigations & Lab Orders)
يدير هذا الموديول كتالوج التحاليل المعملية والفحوصات (مصنّفة في فئات إكلينيكية مثل أمراض الدم، الكيمياء، الهرمونات، الفيروسات...)، وطلب التحاليل للمريضة أو الزوج من داخل شيتات متابعة الحمل وأمراض النساء والعقم، إضافة إلى شاشة فحوصات مرنة (Other Investigations) تتيح للطبيب تعريف أعمدة فحوصات خاصة وتسجيل قيمها لكل مريضة بنمط EAV، كما يتضمن آلية تصدير الملف الكامل للمريضة إلى ملفات Excel كنسخ احتياطية.
الوظائف الرئيسية
- إدارة كتالوج التحاليل: إضافة/تعديل/حذف منطقي لفئات التحاليل (
investcats) وبنود التحاليل (invests) مع ترتيب عرض مخصص (displayorder) عبر شاشةaddinvestigation.php. - تمييز تحاليل "مفضلة" (
favorite) لتظهر بشكل أسرع عند طلب التحاليل من الشيتات. - طلب تحاليل لكل زيارة/شيت: اختيار بنود من الكتالوج وحفظها في جداول أوامر منفصلة لكل تخصص (
ancsheetinvestلمتابعة الحمل،gynasheetinvestلأمراض النساء،infertilitysheetinvestللعقم) مع تحديد ما إذا كان التحليل للزوجة أم للزوج (forhusband) وطباعة أمر التحليل. - تسجيل نتائج التحاليل (
investresult) يدوياً على مستوى كل أمر تحليل، وعرضها مجمّعة حسب التاريخ في الشيتات والتقارير المجمعة. - شاشة فحوصات المريضة الشاملة (
investigation.php): تجميع وعرض وتحرير مباشر (inline AJAX) لفحوصات السائل المنوي والأشعة بالصبغة والموجات الصوتية والمنظار البطني والرحمي والرنين والهرمونات والباثولوجي (جداول موديول العقم). - فحوصات أخرى ديناميكية (Other Investigations): تعريف الطبيب لأعمدة فحوصات مخصصة (
otherinvestigations) ثم إنشاء صف لكل مريضة بتاريخ معين (otherinvestigationsrows) وتخزين القيم بنمط سمة/قيمة (otherinvestigationsvalues). - تصدير دفعي للملف الطبي الكامل للمريضة (تاريخ مرضي، فحص، تحاليل، زيارات، متابعة حمل) إلى ملفات Excel منسقة عبر
excel.phpومكتبة PHPExcel، مع قائمة انتظار للمرضى المطلوب تصديرهم (excelinfopatients). - التحقق من ترخيص البرنامج: جدول
excelinfoيخزّن الرقم التسلسلي لتفعيل النسخة (يُفحص عند تسجيل الدخول) رغم أن اسمه يوحي بأنه خاص بالإكسل.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
investcats | فئات كتالوج التحاليل (22 فئة مزروعة: Hematology, Chemistry, Hormonal profile, Virology, Tumor markers, Genetics, Radiological, ANC booking...) ويُستخدم displayorder لتجميع الفئات في أعمدة شاشة طلب التحاليل. | id, name, displayorder, deleted | أب لجدول invests عبر investcatid |
invests | كتالوج بنود التحاليل نفسها (276 بنداً مزروعاً مثل CBC, FSH, AMH, HBs Ag, CA 125, Karyotyping...) مع إمكانية التفضيل والحذف المنطقي. | id, investcatid, name, favorite, deleted | investcats عبر investcatid؛ يُشار إليه من ancsheetinvest وgynasheetinvest وinfertilitysheetinvest عبر investid |
investigations | جدول قديم بأعمدة ثابتة لنتائج تحاليل حجز متابعة الحمل (Hb, Platelets, FBS, OGTT, HBsAg, HCV, CUA, Ferritin) بزوجي عمودين لكل تحليل: تاريخ (invesd*) ونتيجة (invest*). فارغ في النسخة الحالية ويُقرأ فقط في ancsheet00.php وCompletesreport.php. | id, ancsheetid, invesdhb/investhb, invesdplat/investplat, invesdogtt, invesdhbs, invesdhcv, invesdcua, invesdferr | شيت متابعة الحمل عبر ancsheetid (استنتاج) |
otherinvestigations | تعريفات الفحوصات المخصصة التي يضيفها الطبيب (تمثل أعمدة الشبكة الديناميكية في شاشة الفحوصات). | id, name, deleted | أب لجدول otherinvestigationsvalues عبر investid |
otherinvestigationsrows | صف فحوصات مخصصة لمريضة بتاريخ معين (رأس السجل في نمط EAV). | id, date, patientid, doctorid, deleted | patients عبر patientid؛ awusers عبر doctorid |
otherinvestigationsvalues | قيم الفحوصات المخصصة (تفاصيل نمط EAV): قيمة واحدة لكل تقاطع صفّ × تعريف فحص؛ تُنشأ تلقائياً لكل التعريفات عند إضافة صف جديد. | id, investrowid, investid, value, date | otherinvestigationsrows عبر investrowid؛ otherinvestigations عبر investid |
excelinfo | اسم مضلِّل: يخزّن الرقم التسلسلي لترخيص البرنامج (hash SHA-512 مرتبط بجهاز الخادم) وتاريخ التفعيل، ويُفحص في login.php عند الدخول والتفعيل. صف واحد فقط. | id, time, serial | لا علاقات (جدول إعدادات مستقل) |
excelinfopatients | قائمة انتظار للمرضى المطلوب توليد ملف Excel لهم؛ تُملأ من patienthistory.php وcompletereport.php وتُفرَّغ بالكامل (TRUNCATE) بعد كل تشغيل لـ excel.php. | id, patientid, statusno | patients عبر patientid؛ statusno منسوخ من patients.statusno ويحدد مجلد الحفظ |
سير العمل (Workflow)
- يقوم مدير النظام/الطبيب من شاشة إدارة التحاليل (
addinvestigation.php) بإنشاء فئات التحاليل وبنودها، وتحريرها مباشرة عبر AJAX، وتمييز المفضلة، والحذف المنطقي (deleted = 1). - داخل شيت متابعة الحمل أو أمراض النساء أو العقم، تُعرض الفئات مجمّعة حسب نطاقات
displayorder(مكوّدة يدوياً: 1-2، 3، 4-5، 6-11، أكبر من 11) مع قائمة المفضلة، ويختار الطبيب التحاليل المطلوبة (checkboxes) ويحدد التاريخ وهل هي للزوجة أم للزوج. - عند الحفظ يُنشأ سجل لكل بند مختار في جدول الأوامر الخاص بالشيت (
ancsheetinvestأوgynasheetinvestأوinfertilitysheetinvest) حاملاًpatientidوinvestidوdateوdoctoridوforhusband، ثم يُعرض أمر التحاليل للطباعة باسم المريضة أو الزوج. - لاحقاً تُسجَّل النتائج في حقل
investresultلكل سجل، وتُعرض التحاليل مجمّعة حسب التاريخ (زوجة/زوج) داخل الشيت وفي التقرير المجمع (completereport.php) الذي يجلب اسم التحليل من الكتالوجinvests. - شاشة الفحوصات العامة (
investigation.php?patientid=...) تعرض لكل مريضة جداول السائل المنوي وHSG وUS/TVS والمنظارين وMRI/CT والهرمونات والباثولوجي، وتُنشئ تلقائياً صفاً فارغاً بتاريخ اليوم إن لم يوجد، مع تحرير أي خلية مباشرة عبرupdate(). - في قسم الفحوصات الأخرى: إضافة تعريف فحص جديد (
otherinvestsAdd) ينشئ عموداً جديداً، وإضافة صف للمريضة (otherinvestsRow) ينشئ سجلاً فيotherinvestigationsrowsوقيماً فارغة فيotherinvestigationsvaluesلكل تعريف نشط داخل معاملة واحدة، ثم تُملأ القيم بالتحرير المباشر. - عند فتح ملف المريضة في
patienthistory.phpأوcompletereport.phpتُضاف المريضة تلقائياً إلى قائمةexcelinfopatientsإن لم تكن موجودة. - يعمل السكريبت
excel.php(يُشغَّل مباشرة، على الأرجح بمجدولة cron - استنتاج) فيقرأ القائمة، ويفرّغها، ويبني لكل مريضة جدول HTML شاملاً (تاريخ مرضي، فحص، تحاليل، زيارات، متابعة حمل) ويحوّله إلى ملف.xlsxمنسّق يُحفظ فيexcel_backups/{statusno}/{date}.xlsx.
الارتباط بالموديولات الأخرى
- المرضى (patients): عبر
otherinvestigationsrows.patientidوexcelinfopatients.patientidوكذلكpatientidفي جميع جداول أوامر التحاليل الفرعية، وstatusnoالمنسوخ منpatients.statusno. - متابعة الحمل (Antenatal):
ancsheetinvest.investid→invests.idوancsheetinvest.ancsheetid→ شيت متابعة الحمل، وinvestigations.ancsheetid(الجدول القديم)، وكذلكmainantenentalinvest. - أمراض النساء (Gyna):
gynasheetinvest.investid→invests.idإضافة إلىgynainvestigationوfollowupinvestالتابعة لموديولات المتابعة. - العقم (Infertility):
infertilitysheetinvest.investid→invests.id، وشاشةinvestigation.phpتعرض وتحرر جداول موديول العقم (semen,hsg,ustv,laparoscopy,hysteroscopy,mrict,hormon,pathology). - المستخدمون (awusers): عبر
doctoridفيotherinvestigationsrowsوجميع جداول أوامر التحاليل لإظهار اسم الطبيب الطالب. - التقارير (completereport / Completesreport / patienthistory): تقرأ الكتالوج والأوامر وتغذّي قائمة تصدير الإكسل.
- المراقبة (Monitoring): جدول
mointoringsheetinvestigationيتبع نفس النمط ويرجع للكتالوج ذاته (استنتاج من تشابه البنية).
ملاحظات فنية
- لا توجد مفاتيح أجنبية معلنة إطلاقاً؛ جميع العلاقات مستنتجة من أسماء الأعمدة واستعلامات الكنترولرات.
- اسم جدول
excelinfoمضلِّل تماماً: هو مخزن ترخيص/تفعيل البرنامج (serial SHA-512) وليس له علاقة بالإكسل، وقد أُدرج عمداً ضمن الجداول المحمية من الحذف فيsetup.php. - جدول
investigationsقديم (legacy) بأعمدة ثابتة مكررة لكل تحليل (زوج تاريخ/نتيجة)، فارغ من البيانات، وقد حلّ محله نمطancsheetinvestالمرتبط بالكتالوج؛ كما يُستعلم عنه فيCompletesreport.phpبمعرّف شيت IVF أحياناً (خلط محتمل في المعرّفات). - تكرار بنيوي كبير: ثلاثة جداول أوامر متطابقة البنية (
ancsheetinvest,gynasheetinvest,infertilitysheetinvest) تختلف فقط في سياق الشيت. - منطق تجميع الفئات في الواجهة مكوَّد يدوياً على نطاقات
displayorder(1-2 / 3 / 4-5 / 6-11 / >11 / 0 / -1) ومكرر في أكثر من كنترولر (ancsheet00.php,antenalvisit.php...). - ثغرة أمنية في
investigation.php::update()وaddinvestigation.php::update(): استقبال اسم الجدول واسم العمود من الطلب مباشرة (tableName/colName) ما يسمح بالكتابة في أي جدول؛ كما يُدمجdoctoridفي نصوص SQL بدون ربط معاملات. - بيانات الكتالوج المزروعة تحتوي سجلات تجريبية وتالفة (أسماء فارغة، بنود مثل "vvv" و"new33"، وبنود بـ
investcatid = 0لا تنتمي لأي فئة). - شاشة
investigation.phpتُنشئ تلقائياً صفوفاً فارغة في 7 جداول عند أول فتح للملف، ما يولّد بيانات وهمية (سجلات بلا قيم) بمرور الوقت. excel.phpسكريبت إجرائي بلا فئة كنترولر ولا تحقق من الصلاحيات، يعتمد مكتبة PHPExcel المهجورة، ويستخدم مواضع صفوف مكوَّدة يدوياً للتنسيق ما يجعله هشاً لأي تغيير في البنية، ويسمّي الملفات بتاريخ اليوم فقط (الكتابة فوق التصدير السابق لنفس اليوم).otherinvestigationsvaluesيخزّن كل القيم كنص حر (varchar) دون وحدات قياس أو مدى مرجعي أو نوع بيانات.
توصيات النقل إلى ERP
- إنشاء كتالوج موحّد في Laravel: نموذج
LabTestCategory(منinvestcats) وLabTest(منinvests) مع مفاتيح أجنبية حقيقية، وإضافة حقول ناقصة إكلينيكياً (كود التحليل، الوحدة، المدى المرجعي، نوع النتيجة) وتنظيف السجلات التجريبية والفارغة قبل الترحيل. - توحيد جداول الأوامر الثلاثة (
ancsheetinvest,gynasheetinvest,infertilitysheetinvestومثيلاتها) في نموذج واحدLabOrder+LabOrderItemبعلاقة polymorphic (orderable_type/orderable_id) نحو الزيارة أو الشيت، مع حقولpatient_id,doctor_id,ordered_for(wife/husband),result,result_date. - إسقاط جدول
investigationsالقديم نهائياً (فارغ ومهجور) بعد التأكد من خلوّه في قاعدة الإنتاج، وترحيل أي بيانات تاريخية محتملة إلىLabOrderItem. - استبدال نمط EAV في الفحوصات الأخرى بنموذج
CustomInvestigation(تعريف) وCustomInvestigationResultمع التحقق من نوع القيمة، أو دمجها كلياً في الكتالوج الموحد كفحوصات يعرّفها المستخدم بدلاً من نظام موازٍ. - استبدال ترتيب العرض المكوَّد (
displayorderونطاقاته الثابتة) بحقل ترتيب صريح وتجميع قابل للتهيئة من واجهة الإدارة في Angular. - إلغاء آلية
excelinfo(الترخيص) لأنها خاصة بالنسخة المكتبية القديمة، والاستعاضة عنها بإدارة الاشتراكات/التفعيل في الـ ERP إن لزم. - استبدال قائمة
excelinfopatientsوسكريبتexcel.phpبنظام Jobs/Queues في Laravel مع مكتبة حديثة (Laravel Excel / PhpSpreadsheet) أو تقارير PDF، وتسجيل حالة كل عملية تصدير بدلاً من TRUNCATE. - فرض التحقق من المدخلات ومنع تمرير أسماء الجداول والأعمدة من الواجهة؛ استخدام Form Requests وEloquent مع whitelist صريح للحقول القابلة للتعديل.
- الاحتفاظ بمسار ترحيل بيانات واضح: ربط معرّفات الكتالوج القديمة بالجديدة في جدول mapping لضمان سلامة التقارير التاريخية.
الصيدلية والأدوية (Pharmacy & Drugs)
تطبيق فرعي مستقل داخل النظام (مجلد pharmacy/) يدير كتالوج الأدوية الموحّد للعيادة (نحو 2,000 صنف دوائي مع التصنيف والشكل الصيدلي والجرعة بالعربية)، ومخزون الصيدلية بنظام دفتر حركات (Ledger) يسجل كل عملية إدخال وصرف، وفواتير الشراء من الموردين، وصرف الروشتات (Receipts) القادمة آليًا من الشيتات الإكلينيكية (متابعة الحمل، النساء، العمليات) — أي أنه حلقة الوصل بين الوصف الطبي داخل العيادة وصرف الدواء الفعلي من المخزن.
الوظائف الرئيسية
- إدارة كتالوج الأدوية (
drugs.php): إضافة/تعديل/حذف صنف دوائي بحقول التصنيف العلاجي (drugcat) والاسم التجاري والشكل الصيدلي (Tab/Syrup/Amp...) ونص الجرعة بالعربية، مع جدول عرض DataTables وبحث تكميلي (Autocomplete) لكل حقل على حدة. - تسجيل فواتير الشراء من الموردين (
buys.php): رقم الفاتورة، التاريخ، اسم المورد (نص حر)، المستخدم المستلم، وبنود الفاتورة (دواء + كمية) — مع زيادة رصيد المخزون آليًا داخل معاملة (Transaction). - تعديل وحذف فواتير الشراء مع عكس أثرها على الأرصدة وتسجيل حركة تصحيحية في دفتر المخزن.
- دفتر حركات المخزون (
store.php): تقرير زمني لكل حركة دواء (الرصيد قبل/بعد/الفرق) مع نوع العملية: 0 = توريد، 1 = صرف، 2 = تعديل فاتورة، 3 = حذف/تصحيح. - شاشة صرف الروشتات (
receipt.php): عرض الروشتات المعلّقة القادمة من الشيتات الإكلينيكية باسم الطبيب والمريضة، وعرض تفاصيل الأدوية مع تحذير إذا كان الرصيد الحالي أقل من المطلوب، ثم تأكيد الصرف بخصم الكميات من المخزون وتغيير حالة الروشتة. - توليد الروشتات آليًا من الموديولات الإكلينيكية: كنترولرات
followupcard.phpوoperativedetails.phpفي النواة تُنشئ سجلrecepittmpوبنوده فيreceiptdrugsعند حفظ الوصفة الطبية، فتظهر فورًا في طابور الصيدلية. - إدارة طاقم/رئيس المجلس (
stuff.php): وظيفة جانبية تدير جدولcouncilstaff، مع نسخة مكررة بالكامل من دوال تعديل وحذف الفواتير الموجودة فيbuys.php.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
drugs | كتالوج الأدوية الرئيسي (~2,000 صنف مزروع مسبقًا) مع رصيد المخزون الجاري لكل صنف | id, drugcat, drugname, drugtype, drugdos, initialbalance, currentbalance | يُشار إليه من importdetails.drug_id، pharmacystore.drug_id، receiptdrugs.drugs_id، وجداول الوصفات الإكلينيكية عبر drugid |
drugdos | جدول مرجعي للجرعات — فارغ وغير مستخدم في أي كود؛ حقل name معرّف خطأً كرقم (int) بدل نص، والجرعات تُخزَّن فعليًا كنص حر في drugs.drugdos | id, name, deleted | لا توجد (جدول ميت) |
pharmacystore | دفتر حركات المخزون: سجل لكل عملية على رصيد دواء (قبل/بعد/الفرق) بطابع زمني ونوع عملية | drug_id, amountbefore, amountafter, amountvary, opdate, optype | drugs عبر drug_id |
recepittmp | رأس الروشتة (Receipt header) المُنشأ آليًا من الشيتات الإكلينيكية وينتظر الصرف في الصيدلية؛ status: 0 = معلّقة، 1 = تم الصرف | doctor_id, patient_id, rect_date, drugstablename, status | awusers عبر doctor_id، patients عبر patient_id، ارتباط متعدد الأشكال (Polymorphic) بجدول الوصفة المصدر عبر drugstablename |
receiptdrugs | بنود الروشتة: دواء وكمية لكل سطر في الروشتة المعلّقة | receipt_id, drugs_id, amount | recepittmp عبر receipt_id، drugs عبر drugs_id، وتُشير إليه جداول الوصفات الإكلينيكية عبر recepitdrugid |
importbill | رأس فاتورة الشراء من المورد (اسم المورد نص حر بلا جدول موردين) | invoicenum, invoicedate, suppliers, receiveuser | awusers عبر receiveuser |
importdetails | بنود فاتورة الشراء (دواء + كمية)؛ الجدول الوحيد في الموديول الذي يملك فهرسًا على المفتاح الأجنبي | bill_id, drug_id, amount | importbill عبر bill_id، drugs عبر drug_id |
importtdetails | نسخة مكررة من importdetails (نفس الأعمدة بترميز utf8mb4) — فارغة وغير مستخدمة في أي كنترولر (جدول ميت/مهجور) | bill_id, drug_id, amount | نفس علاقات importdetails نظريًا (استنتاج) |
سير العمل (Workflow)
- يُجهَّز كتالوج الأدوية مرة واحدة (بيانات مزروعة ~2,000 صنف) ويُضاف عليه من شاشة الأدوية؛ عند إضافة صنف جديد يُسجَّل رصيد افتتاحي يُنسخ إلى
currentbalance. - عند وصول توريد من مورد، يُدخل أمين المخزن فاتورة شراء (
buys.php → addnew) داخل معاملة واحدة: سجل فيimportbill، ثم لكل بند سجل فيimportdetails+ حركة توريد (optype=0) فيpharmacystore+ تحديثdrugs.currentbalance. - في العيادة، عند حفظ وصفة في كارت المتابعة أو تفاصيل العمليات (كنترولرات النواة
followupcard.php/operativedetails.php) يُنشأ آليًا رأس روشتة فيrecepittmpبحالة 0 مع اسم جدول الوصفة المصدر، وتُنسخ الأدوية إلىreceiptdrugsبكمية افتراضية 1، ويُحفظ رقما الروشتة والبند (recepittmpid/recepitdrugid) داخل سجل الوصفة الإكلينيكية نفسه. - يفتح موظف الصيدلية شاشة الروشتات (
receipt.php) فيرى الطابور باسم الطبيب والمريضة، ويدخل على التفاصيل حيث يُحذَّر تلقائيًا إن كان رصيد أي صنف أقل من الكمية المطلوبة. - عند تأكيد الصرف (
updatereceipt) تُسجَّل لكل صنف حركة صرف (optype=1) فيpharmacystoreويُخصم منdrugs.currentbalance— مع تخطّي الأصناف التي لا يكفي رصيدها — ثم تتحول حالة الروشتة إلى 1 (تم الصرف). - تعديل فاتورة شراء (
update) يعكس الكميات القديمة ويسجل حركات تصحيح (optype=2)؛ وحذف الفاتورة (del) يخصم الكميات ويسجل حركات (optype=3). - تقرير المخزن (
store.php → show) يعرض دفتر الحركات كاملًا باسم الدواء ونوع العملية والتاريخ كسجل تدقيق للمخزون.
الارتباط بالموديولات الأخرى
- موديول المرضى:
recepittmp.patient_id → patients.id(اسم المريضة منwifename). - المستخدمون والصلاحيات:
recepittmp.doctor_id → awusers.user_idوimportbill.receiveuser → awusers.user_id، مع نظام صلاحياتauthoالمشترك مع تطبيق النواة. - الشيتات الإكلينيكية (متابعة الحمل، النساء، العقم، العمليات...): جداول الوصفات
followupcarddrugs,operativedetailsdrugs,ancsheetdrugs,gynadrugs,gynasheetdrugs,mainantenentaldrugs,infertilitydrugsوغيرها تحمل أعمدةdrugid → drugs.idوrecepittmpid → recepittmp.idوrecepitdrugid → receiptdrugs.id. - ارتباط متعدد الأشكال:
recepittmp.drugstablenameيخزن اسم جدول الوصفة المصدر كنص (مثلfollowupcarddrugsأوoperativedetailsdrugs). - موديول الزيارات: شاشة طباعة الروشتة في كارت المتابعة تقرأ من
visitsوdetections(استخدام غير مباشر). - إدارة المجلس: كنترولر
stuff.phpيكتب في جدولcouncilstaff(خارج جداول هذا الموديول).
ملاحظات فنية
- جدولان ميتان:
drugdos(فارغ، حقلnameمن نوع int خطأً، لا يُستخدم في أي كود) وimporttdetails(نسخة مكررة فارغة منimportdetailsبلا أي مرجع في الكود). - ثغرة حقن SQL في
drugs.php → show(): قيمة البحثsSearchتُدمج في الاستعلام مباشرة بلا Prepared Statement. - ثغرة خطيرة في
receipt.php → update(): نقطة نهاية عامة تستقبل اسم الجدول والعمود والقيمة من المستخدم وتكتب في أي جدول بقاعدة البيانات. - تكرار كود ضخم: دوال
update/del/delupمنسوخة حرفيًا بينbuys.phpوstuff.php، وكنترولرreceipt.phpيكرر نفس المنطق فيindex()وshow(). - تعليقات الكود مضللة: التعليق يقول إن
optype"0 للحذف و1 للتعديل" بينما الاستخدام الفعلي: 0 توريد، 1 صرف، 2 تعديل، 3 حذف — قيم مُدمجة في الكود (Hardcoded) بلا جدول مرجعي. - لا توجد مفاتيح أجنبية معلنة إطلاقًا؛ حذف فاتورة يخصم الكمية من الرصيد دون التحقق من عدم سلبيته، ومنطق تعديل الفاتورة في
buys.php → update()هشّ وبه شروط يصعب تتبعها (مقارنةbillIDnبـdrug_id). - لا يوجد جدول موردين:
importbill.suppliersنص حر، ولا أسعار شراء أو بيع ولا تواريخ صلاحية أو أرقام تشغيلات (Batches) في المخزون. - الكمية في بنود الروشتة ثابتة دائمًا = 1 عند التوليد الآلي من الشيتات، والتصنيف والشكل الصيدلي والجرعة في
drugsنصوص حرة غير منضبطة (تكرارات مثلAnti-viruis\r\n). - عند صرف روشتة، الأصناف التي لا يكفي رصيدها تُتخطى بصمت ثم تُعلَّم الروشتة كلها "تم الصرف" — فقدان لمعلومة الصرف الجزئي.
توصيات النقل إلى ERP
- إنشاء موديلات Laravel:
Drug(مع فصل التصنيف إلىDrugCategoryوالشكل الصيدلي إلىDosageFormكجداول مرجعية بدل النص الحر)، وStockMovementبدلpharmacystoreمع Enum لنوع الحركة، وPurchaseInvoice+PurchaseInvoiceItemبدلimportbill/importdetails، وPrescription+PrescriptionItemبدلrecepittmp/receiptdrugs. - إسقاط الجدولين الميتين
drugdosوimporttdetailsنهائيًا من خطة الترحيل. - إنشاء جدول
suppliersمستقل وربط فواتير الشراء به بمفتاح أجنبي بدل النص الحر، وإضافة حقول الأسعار وتواريخ الصلاحية وأرقام التشغيلات إن أرادت الإدارة إدارة مخزون حقيقية. - التوقف عن تخزين
currentbalanceكحقل يُحدَّث يدويًا، وجعله محسوبًا من دفتر الحركات (أو تحديثه عبر Observers/Events داخل معاملات قاعدة بيانات) مع قيد يمنع الرصيد السالب. - استبدال الارتباط النصي متعدد الأشكال (
drugstablename+ أعمدةrecepittmpid/recepitdrugidالمبعثرة في 8+ جداول وصفات) بعلاقة Polymorphic قياسية في Laravel (prescribable_type/prescribable_id) أو بتوحيد جداول الوصفات الإكلينيكية كلها في جدولprescription_itemsواحد مرتبط بنوع الشيت. - دعم الصرف الجزئي: حالة الروشتة يجب أن تكون Enum (معلّقة/مصروفة جزئيًا/مصروفة/ملغاة) مع تسجيل الكمية المصروفة فعليًا لكل بند بدل تخطّي النواقص بصمت.
- تنظيف بيانات الكتالوج قبل الترحيل: توحيد التصنيفات المكررة وإزالة محارف
\r\nوالمسافات الزائدة، وفرض Unique على (الاسم + الشكل الصيدلي). - إغلاق الثغرات أثناء الترحيل بطبيعة Laravel: Form Requests للتحقق، Eloquent/Query Builder بدل دمج النصوص في SQL، وحذف أي نقطة نهاية كتابة عامة مثل
receipt.php → update()، مع نقل صلاحيات الصيدلية إلى Policies/Gates.
الماليات والتقارير (Financial & Reports)
يغطي هذا الموديول الجانب المالي للعيادة ومنظومة التقارير بأكملها: تسجيل رسوم الكشف مع كل زيارة (نقدًا أو فيزا مع الخصم والمتبقي)، وإدارة رصيد إجمالي للمريضة يُسدَّد على أقساط، وتقارير الإيرادات اليومية والمديونيات، إضافة إلى التقارير السريرية المجمَّعة (التقرير الكامل، المدمج، الشامل، وإحصاءات الحقن المجهري)، وأدوات صيانة قاعدة البيانات (النسخ الاحتياطي، دمج قواعد قديمة، واستيراد ملفات SQL).
الوظائف الرئيسية
- تسجيل رسوم الزيارة داخل جدول
visitsنفسه: نوع الكشف من كتالوجdetectionsمع الحقول الماليةtotaldetectionvalueوdetectionvalue_cashوdetectionvalue_visaوdiscountوrestdetectionvalue(المتبقي كدَين). - التقرير المالي اليومي/الفتري (financialreport): إجمالي الإيرادات، النقدي، الفيزا، الخصومات، المديونيات، المرتجعات، مع تمييز المرضى الجدد خلال الفترة، والبحث باسم الزوجة أو الزوج أو العنوان، مع شاشة طباعة.
- إدارة "المبلغ الإجمالي" للمريضة: إضافة رصيد عبر جدول
totalbalance(من شاشة الزيارات بطلب AJAX) وحساب المتبقي = مجموع الرصيد − مدفوعات الأقساط المسجلة كزيارات بكودdetectionid = -99. - تقرير الأرصدة (balance): دمج إضافات الرصيد من
totalbalanceمع مدفوعات الأقساط منvisitsعبر استعلام UNION لعرض صافي الحركة. - تقرير المتبقيات (rest): حصر الزيارات التي بها مديونية
restdetectionvalue > 0بعد خصم ما سُدِّد لاحقًا (زيارات بكودdetectionid = 999"دفع متبقى") وما خُصم. - معالجة المرتجعات: زيارات بكود
detectionid = 9999"مرتجع العملاء" مرتبطة بالزيارة الأصلية عبرvisits.visitidوتُخصم من إيرادات اليوم. - تقرير استخدام الأدوية: حصر المريضات اللاتي وُصف لهن دواء معين خلال فترة عبر 6 جداول وصفات (gynadrugs، mainantenentaldrugs، ancsheetdrugs، infertilitydrugs، gynasheetdrugs، infertilitysheetdrugs).
- التقرير الكامل (fullreport): مصفوفة نشاط لكل مريضة زارت العيادة خلال فترة، تُبيِّن الأقسام السريرية التي بها بيانات (تاريخ مرضي، فحص، استقصاءات، متابعة حمل، نساء، موجات صوتية، سونار، عمليات) مع عدد الزيارات.
- التقرير المدمج (combinedreport): بحث إحصائي/وبائي بالعمر والتشخيص النسائي وتشخيص الحمل والعمليات والإجهاض، مع حساب نسبة مئوية من إجمالي المريضات.
- التقرير الشامل للمريضة (completereport): تجميع كل بيانات المريضة (ديموغرافيا، تاريخ مرضي، فحص، استقصاءات، نساء، متابعة حمل) في شاشة واحدة، مع تصدير Excel بتشغيل سكربت خارجي
excel.phpوحفظ الملفات فيcore/excel_backups/<statusno>. - تقرير الشيتات الشامل (Completesreport): نسخة أحدث تجمع شيتات العقم والحقن المجهري ومتابعة الحمل والنساء مع عشرات جداول القيم المرجعية في تقرير واحد.
- إحصاءات الحقن المجهري (Ivfstatistics): حصر دورات
ivfsheetبتاريخ آخر دورة شهرية (fresh/frozen) مع بروتوكول التنشيط ومراحل التحضير (ovst، eprep) وحساب سن المريضة وقت المحاولة. - النسخ الاحتياطي (backup): تنفيذ
mysqldumpوحفظ النسخة فيcore/db_backupsوفي مسار إضافي من إعدادات البرنامج، مع تنزيلها للمتصفح، إضافة لأدوات إصلاح بيانات (استكمالdrugidالناقص وتوليد أرقام ملفاتstatusnoالمفقودة). - دمج قاعدة بيانات قديمة (merge): نقل نحو 40 جدولًا من قاعدة عيادة قديمة إلى الحالية جدولًا جدولًا عبر RedBeanPHP ثم تشغيل إصلاحات لاحقة.
- استيراد قاعدة جديدة (newdb): رفع ملف SQL وتنفيذه سطرًا بسطر مباشرة على قاعدة البيانات.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
totalbalance | سجل إضافات الرصيد الإجمالي للمريضة (دائن يُسدَّد لاحقًا على أقساط)؛ يُضاف من شاشة الزيارات ويُحتسب المتبقي بخصم زيارات "دفع قسط" | id, patientid, balance, deleted, userid, adddate | patients عبر patientid، awusers عبر userid (استنتاج) |
totalbalancepaids | كان مخصصًا لتسجيل سداد دفعات الرصيد الإجمالي، لكنه جدول مهجور: لا يوجد أي كود يقرأ منه أو يكتب فيه؛ السداد الفعلي يُسجَّل كصفوف في visits بكود detectionid = -99 | id, patientid, paid, userid, paydate | patients عبر patientid (استنتاج) |
سير العمل (Workflow)
- عند فتح زيارة جديدة من شاشة الاستقبال (
visits.php) تختار الموظفة نوع الكشف من كتالوجdetections، فتُسجَّل قيمته الإجمالية والمدفوع نقدًا/فيزا والخصم والمتبقي في صف الزيارة نفسه بجدولvisits. - إذا اشترت المريضة باقة/مبلغًا إجماليًا، تضيف الموظفة الرصيد عبر زر في شاشة الزيارات يستدعي
visits.php?addbalanceفيُخزَّن صف جديد فيtotalbalanceباسم المستخدم وتاريخ اليوم، ويعرض النظام فورًا المتبقي (مجموع الأرصدة − مدفوعات الأقساط). - سداد قسط من الرصيد يُسجَّل كزيارة بكود
detectionid = -99، وسداد متبقي زيارة سابقة بكود999مع ربطها بالزيارة الأصلية عبرvisits.visitid، والمرتجع بكود9999. - في نهاية اليوم تفتح الإدارة التقرير المالي (
financialreport.php?index/search) لعرض حركة اليوم أو فترة: لكل زيارة النوع والقيمة والنقدي والفيزا والخصم والمتبقي والمرتجع، مع إجماليات وقائمة المرضى الجدد، ثم الطباعة منshowprint. - تقرير الأرصدة
financialreport.php?balance(وبحثه عبرmonitoring.php) يعرض حركة "إضافة للمبلغ الإجمالي" مقابل "دفع قسط" بصافي محسوب، وتقرير المتبقياتrestيحصر المديونيات القائمة. - للتقارير السريرية:
fullreportيحدد فترة ويستعرض نشاط كل مريضة في كل قسم، وcombinedreportيجري بحثًا إحصائيًا بمعايير تشخيصية، وcompletereport/Completesreportيولّدان ملفًا شاملًا لمريضة واحدة مع إمكانية تصدير Excel، وIvfstatisticsيستخرج إحصاءات دورات الحقن المجهري. - دوريًا يأخذ المدير نسخة احتياطية من
backup.php?takeit(mysqldump ثم تنزيل)، وعند الانتقال من نظام قديم تُستخدمmerge.phpلدمج قاعدة قديمة أوnewdb.phpلتنفيذ ملف SQL مرفوع.
الارتباط بالموديولات الأخرى
- موديول المرضى:
totalbalance.patientidوtotalbalancepaids.patientid↔patients.id، وكل التقارير تعرضwifenameوhusdandnameوstatusno. - موديول الزيارات والاستقبال: الرسوم تُسجَّل في
visits(detectionid,detectionvalue_cash,detectionvalue_visa,restdetectionvalue) وهي مصدر كل التقارير المالية، مع كتالوج أنواع الكشفdetectionsوجدول إقفال اليومendvisitreports. - موديول الصيدلية/الأدوية: تقرير استخدام الأدوية يقرأ من
drugsوجداول الوصفات الست عبرdrugidوpatientid. - الموديولات السريرية (التاريخ المرضي، الفحص، الاستقصاءات، متابعة الحمل، النساء، الموجات، العمليات): تُقرأ جداولها (
ph*,examination,semen,hsg,gyna,mainantenental,ultrasound*,sonar,operativedetails...) في التقارير الكاملة والمدمجة عبرpatientid. - موديول الشيتات (العقم/الحقن المجهري/متابعة الحمل):
CompletesreportوIvfstatisticsيقرآنinfertilitysheetوivfsheetوancsheetوجداولهما الفرعية عبرpatientidوivfsheetidوinfertilitysheetid. - موديول الإعدادات والمستخدمين:
programesetting(مسار النسخ الاحتياطي وphppathوقاعدة ERP الخارجية) وtotalbalance.userid↔ مستخدمي النظامawusers(استنتاج)، كما توجد دالة مزامنة كتالوج الكشوفات إلى قاعدة ERP خارجية (addAllDetectionToERPفي visits.php).
ملاحظات فنية
totalbalancepaidsجدول ميت تمامًا: لا يظهر في أي كنترولر أو قالب؛ المدفوعات تُسجَّل بدلًا منه كزيارات بأكواد سحرية.- منطق محاسبي مبني على قيم سحرية مثبتة في الكود (
detectionid= -99 قسط، 999 سداد متبقٍ، 9999 مرتجع) دون جدول أنواع حركات، ما يجعل جدول الزيارات يلعب دور دفتر يومية مالي. - لا توجد قيود مفاتيح أجنبية إطلاقًا؛ كل العلاقات مستنتجة من أسماء الأعمدة وجمل JOIN.
- ثغرات حقن SQL واسعة: التواريخ والعناوين وأسماء الأزواج تُلصق نصيًا في الاستعلامات (financialreport، monitoring، combinedreport)، ودالة
Add()في Completesreport وIvfstatistics تكتب في أي جدول/عمود يصل عبر POST دون أي تحقق. newdb.phpينفّذ ملف SQL مرفوعًا مباشرة، وbackup.phpيمرر كلمة مرور القاعدة في أمر نظام (system())، مع بقايا بيانات اعتماد قديمة معلَّقة في الكود.- القيم المالية بدقة صفرية:
visitsتستخدمdecimal(10,0)وtotalbalance.balanceمن نوعint(لا كسور عملة)، والجدولان بترميزlatin1بخلاف باقي القاعدةutf8mb4. - تكرار كود كبير: استعلامات البحث/الطباعة منسوخة حرفيًا داخل نفس الكنترولر، و
onesetup(حذف قوائم وأدوار) مكرر في أكثر من كنترولر تقارير بلا علاقة بالتقارير. - تصدير Excel يعتمد على
exec()لمسار PHP مخزَّن في الإعدادات (إرث تشغيل على Windows/WAMP) ويكتب ملفات لكل مريضة في مجلدات باسم رقم الملف. - الجدولان فارغان في النسخة المفحوصة (AUTO_INCREMENT=1) أي أن الإصدار الحالي للعميل قد لا يستخدم خاصية الرصيد الإجمالي فعليًا (استنتاج).
توصيات النقل إلى ERP
- إنشاء نموذج
PatientLedgerEntry(دفتر حساب المريض) موحَّد يستوعب: رسوم الزيارة، إضافة رصيد (يحل محلtotalbalance)، سداد قسط، سداد متبقٍ، خصم، مرتجع — بعمودtype(enum) بدل الأكواد السحرية -99/999/9999، معreference_idللحركة الأصلية بدلvisits.visitid. - فصل الفاتورة عن الزيارة: نموذج
Invoiceمرتبط بالزيارة (بنود من كتالوج الخدماتservicesالذي يحل محلdetections) ونموذجPaymentبعمود طريقة الدفع (cash/visa) بدل عمودين منفصلين، وحساب المتبقي والمديونية ديناميكيًا لا تخزينه. - إسقاط
totalbalancepaidsنهائيًا دون ترحيل (جدول ميت)، وترحيل صفوفtotalbalanceإن وُجدت إلى حركات إيداع في دفتر الحساب. - استخدام
decimal(10,2)لكل المبالغ، وقيود مفاتيح أجنبية فعلية إلىpatientsوusers، وحذف ناعم موحَّد (deleted_at) بدل أعمدةdeletedالرقمية. - بناء التقارير (المالي اليومي، الأرصدة، المديونيات، استخدام الأدوية) كطبقة استعلامات/Resources في Laravel مع API لواجهة Angular، وتقارير المريضة الشاملة كـ endpoints تجميعية أو خدمة توليد PDF بدل تصدير Excel عبر
exec(). - الاستغناء عن
backup.phpوmerge.phpوnewdb.php: النسخ الاحتياطي عبر أدوات مُدارة (spatie/laravel-backup أو نسخ على مستوى الخادم)، ودمج القواعد القديمة كسكربتات ترحيل (ETL) تُنفَّذ مرة واحدة وقت الانتقال، ومنع أي رفع/تنفيذ SQL من الواجهة. - تطبيق التحقق من المدخلات والاستعلامات المعدة مسبقًا (Eloquent/Query Builder) في كل شاشات البحث، وإزالة أي نقطة كتابة عامة على غرار
Add()، مع صلاحيات دقيقة للتقارير المالية (أدوار محاسب/مدير).
مجلس الأطباء والجلسات (Medical Board & Sessions)
موديول مستقل (تطبيق فرعي board) لإدارة مجلس الأطباء داخل العيادة: يتيح للأطباء رفع طلبات استشارة/مناقشة حالات سريرية إلى المجلس، ثم تنظيم جلسات دورية يحضرها أعضاء المجلس لمناقشة الطلبات المعلّقة، وتسجيل رأي كل عضو (قبول/رفض) على كل طلب، وتدوين القرار النهائي للمجلس، مع إمكانية تأجيل الطلبات لجلسة لاحقة وأرشفة الجلسات والطلبات المنتهية، إضافة إلى نظام تعليقات متداخل (تعليق ورد على تعليق) على كل طلب، وشاشة لتشكيل هيئة المجلس (رئيس، أمين، أعضاء).
الوظائف الرئيسية
- إنشاء طلب عرض حالة على المجلس: يُنشأ الطلب تلقائيًا كمسودة (
status=0) عند فتح الشاشة، مع حفظ تلقائي للعنوان والتفاصيل أثناء الكتابة (AJAX auto-save)، ثم إرساله للمجلس (status=1) بتاريخ اليوم. - عرض قائمة الطلبات المعلّقة (المرسلة وغير المناقشة) وقائمة أرشيف الطلبات التي نوقشت وأُغلقت (
status=2). - فتح جلسة مجلس جديدة تلقائيًا: عند فتح شاشة الجلسات يُنشأ سجل جلسة مسودة (
status=0) وتُسجّل تلقائيًا قائمة أعضاء المجلس (المستخدمون أصحابpositionid١ و٢ و٣) كأعضاء للجلسة. - تسجيل حضور وغياب الأعضاء في الجلسة بإضافة/حذف سجل في
bsessionmembers. - تسجيل رأي كل عضو حاضر على كل طلب معروض: قبول (
1) أو رفض (2) في جدولbmemberopenion. - تدوين القرار النهائي للمجلس نصيًا على الطلب (حقل
decisionفيbrequests). - تأجيل طلب لجلسة قادمة (علامة
delay=1) أو إلغاء التأجيل. - إغلاق الجلسة وأرشفتها: تُغلق الجلسة (
status=1) وتُؤرشف كل الطلبات المناقشة (status=2) مع ربطها برقم الجلسةsessionid، وتُعاد الطلبات المؤجلة إلى قائمة الانتظار — كل ذلك داخل معاملة (Transaction) واحدة. - نظام تعليقات متداخل على الطلبات: تعليقات رئيسية وردود عليها (
relatedcommentid)، مع إضافة وحذف (حذف التعليق الرئيسي يحذف ردوده). - عرض تفاصيل الجلسات المؤرشفة: الأعضاء الحاضرون وآراؤهم وقرارات المجلس على كل طلب.
- إدارة تشكيل المجلس (شاشة
stuff): تعيين رئيس المجلس (status=0) وأمين المجلس (status=1) والأعضاء (status=2) من بين مستخدمي النظام، مع تعديل وحذف.
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
brequests | طلبات عرض الحالات على المجلس؛ دورة الحياة: مسودة (0) ← مُرسل (1) ← مناقَش ومؤرشف (2)، مع علامة تأجيل وقرار نهائي نصي | id, memberid, title, details, status, date, delay, decision, sessionid | awusers عبر memberid، bsession عبر sessionid |
bsession | جلسات المجلس؛ الحالة: مفتوحة (0) أو مغلقة/مؤرشفة (1)، مع تاريخ الإغلاق ومنشئ الجلسة | id, date, status, memberid | awusers عبر memberid (منشئ الجلسة) |
bsessionmembers | سجل حضور أعضاء المجلس في كل جلسة (جدول ربط جلسة × عضو)؛ وجود السجل يعني الحضور وحذفه يعني الغياب | id, sessionid, memberid | bsession عبر sessionid، awusers عبر memberid |
bmemberopenion | رأي كل عضو حاضر على كل طلب داخل الجلسة: قبول (1) أو رفض (2)؛ سجل واحد لكل (طلب × عضو جلسة) يُحدَّث عند تغيير الرأي | id, requestid, sessionmemberid, openion | brequests عبر requestid، bsessionmembers عبر sessionmemberid |
bcomments | تعليقات متداخلة على الطلبات: التعليق الرئيسي له relatedcommentid=0 والردود تشير إلى التعليق الأب | id, memberid, requestid, comment, relatedcommentid | awusers عبر memberid، brequests عبر requestid، bcomments (ذاتية) عبر relatedcommentid |
councilstaff | تشكيل هيئة المجلس: رئيس (0)، أمين (1)، عضو (2) — كل سجل يربط مستخدمًا بدوره في المجلس | id, userid, status | awusers عبر userid |
سير العمل (Workflow)
- يفتح الطبيب شاشة «إضافة طلب» (
requests.php)؛ إن وُجدت مسودة طلب سابقة غير مرسلة تُحمَّل، وإلا يُنشأ سجل طلب جديد فارغ باسمه تلقائيًا. - يكتب الطبيب عنوان الحالة وتفاصيلها، وتُحفظ القيم تلقائيًا أولًا بأول عبر دالة
update()(AJAX). - عند الضغط على «إرسال» (
sendrequest) يتحول الطلب إلىstatus=1ويُختم بتاريخ اليوم ويظهر في قائمة الطلبات المعلّقة. - يتبادل الأطباء النقاش كتابيًا على الطلب عبر التعليقات والردود (
addcomment/deletecomment). - يفتح أمين المجلس شاشة الجلسات (
sessions.php)؛ إن لم توجد جلسة مفتوحة تُنشأ جلسة جديدة ويُسجَّل تلقائيًا كل أعضاء المجلس (مستخدموpositionid1–3) فيbsessionmembers. - يُحدَّث الحضور الفعلي بإزالة الغائبين وإعادة إضافة الحاضرين (
addsessionmember/removesessionmember). - تُعرض الطلبات المعلّقة واحدًا تلو الآخر (
requestDetails)؛ يسجل كل عضو حاضر رأيه قبول/رفض (saveopinion)، ويُدوَّن قرار المجلس النهائي نصيًا (savedecision)، أو يُؤجَّل الطلب لجلسة قادمة (delay). - عند إنهاء الجلسة (
savesession): تُغلق الجلسة بتاريخ اليوم، وتُؤرشف الطلبات المناقشة (status=2) مع ربطها بالجلسة، وتُعاد الطلبات المؤجلة إلى قائمة الانتظار (داخل معاملة واحدة). - يمكن لاحقًا استعراض أرشيف الجلسات وتفاصيل كل جلسة: الحضور، الطلبات المناقشة، آراء الأعضاء، والقرارات (
archiveshowall/sessiondetails/requestDetailsArchive). - بشكل مستقل، تُدار عضوية المجلس من شاشة
stuff.php: تعيين الرئيس والأمين والأعضاء في جدولcouncilstaff.
الارتباط بالموديولات الأخرى
- موديول المستخدمين والصلاحيات (Core): كل أعمدة
memberidوuseridفي الجداول الستة تشير إلىawusers.user_id، وتُجلب أسماء الأطباء منه في كل الشاشات. - موديول شؤون الأطباء/الوظائف: اختيار أعضاء الجلسة يعتمد على
awusers.positionidبقيم مثبّتة في الكود (1، 2، 3) — ولا يوجد جدولpositionsفي نسخة قاعدة البيانات المفحوصة (استنتاج: قيم وظائف الأطباء الاستشاريين والأخصائيين). - موديول المرضى: لا يوجد ربط هيكلي بجدول
patientsإطلاقًا؛ بيانات المريض والحالة تُكتب نصًا حرًا فيtitleوdetailsفقط — فجوة بيانات جوهرية. - موديول الصيدلية: كنترولر
stuff.phpيحتوي دوال كاملة منسوخة من موديول الصيدلية (updategg،del،delup) تتعامل مع جداولimportbillوimportdetailsوdrugsوpharmacystore— كود ميت منسوخ بالخطأ ولا علاقة له بالمجلس.
ملاحظات فنية
- جدول
councilstaffشبه مهجور وظيفيًا: كنترولر الجلسات علّق الاستعلام عنه واستبدله باستعلام مباشر علىawusers.positionid IN (1,2,3)بقيم مثبّتة في الكود، فأصبح تشكيل المجلس المُدار من شاشةstuffغير مؤثر فعليًا في الجلسات. - ثغرة أمنية حرجة في
requests.php::update(): تستقبل اسم الجدول واسم العمود والقيمة من POST مباشرة وتكتبها في أي جدول بقاعدة البيانات (Arbitrary table/column write). stuff.phpبلا أي تحقق من تسجيل الدخول أو الصلاحيات (فحوصاتauthoمعلّقة)، ويستخدم استعلامات SQL مبنية بدمج النصوص (مثل'... user_id = ' . $userid) — قابلة لحقن SQL.- لا توجد مفاتيح أجنبية (Foreign Keys) مُعرّفة إطلاقًا؛ كل العلاقات استُنتجت من أسماء الأعمدة واستعلامات الكنترولرات.
- تضارب في الترميز:
bcommentsوbsessionوcouncilstaffبترميزlatin1بينما البقيةutf8mb4— خطر تلف للنصوص العربية في التعليقات. - غياب الطوابع الزمنية: لا يوجد
created_atفي التعليقات والآراء، وتاريخ الطلب/الجلسة يُسجَّل فقط عند الإرسال/الإغلاق. - حقلا
titleوdetailsفيbrequestsمحدودان بـvarchar(191)— التفاصيل السريرية تُبتر عند هذا الحد رغم أن الواجهة تعرضها كمساحة نص كبيرة. - قيم الحالات كلها أرقام سحرية مثبّتة في الكود: حالة الطلب (0/1/2)، حالة الجلسة (0/1)، الرأي (1=قبول، 2=رفض)، دور العضو (0=رئيس، 1=أمين، 2=عضو) — بلا جداول مرجعية.
- معالجة الأخطاء صورية: كتل
try/catchفارغة تبتلع الاستثناءات بصمت في معظم الدوال. - الجداول الستة فارغة في نسخة قاعدة البيانات (AUTO_INCREMENT=1) — لا بيانات تاريخية تحتاج ترحيلًا من هذه النسخة (استنتاج: الموديول لم يُستخدم إنتاجيًا أو نُظِّفت بياناته).
توصيات النقل إلى ERP
- إنشاء خمسة نماذج Laravel:
BoardRequestوBoardSessionوBoardSessionMemberوBoardMemberOpinionوBoardComment، مع مفاتيح أجنبية صريحة وقيودON DELETEمناسبة. - إضافة عمود
patient_idإلزامي فيboard_requestsمرتبط بجدول المرضى الموحد، وربط اختياري بالزيارة/الملف السريري — لمعالجة أكبر فجوة في التصميم الحالي (الحالة نص حر بلا مريض). - تحويل الأرقام السحرية إلى
Enumفي Laravel:RequestStatus(draft/submitted/discussed)،SessionStatus(open/closed)،Opinion(accept/refuse)،CouncilRole(head/secretary/member). - دمج
councilstaffفي نظام الأدوار/الصلاحيات بالـ ERP (مثل Spatie Permissions أو جدولboard_membersبحقلrole)، وإلغاء الاعتماد المثبّت علىpositionid IN (1,2,3)بجعل عضوية المجلس قابلة للإدارة فعليًا. - ربط رأي العضو مباشرة بـ
user_idوsession_idبدل المرور عبرsessionmemberid(أو الإبقاء عليه مع قيد فريد علىrequest_id + session_member_id)، مع إضافة طوابع زمنية لكل رأي وتعليق. - توسيع حقل التفاصيل إلى
TEXT، وإضافةcreated_at/updated_atوsoft deletesلكل الجداول لأغراض التدقيق الطبي. - استبدال آلية الحفظ التلقائي «أكتب في أي جدول» بنقطة نهاية REST مخصصة ومحمية (
PATCH /board-requests/{id}) مع Validation وFormRequest. - حذف الكود الميت الخاص بالصيدلية من
stuff.phpنهائيًا وعدم ترحيله — وظائفه مكررة في موديول الصيدلية الأصلي. - نظرًا لخلو الجداول من البيانات في النسخة المفحوصة، يمكن بناء الموديول في الـ ERP من الصفر بالتصميم المحسّن دون عبء ترحيل بيانات (يُتحقق من نسخة الإنتاج الأحدث قبل الاعتماد النهائي).
النظام والصلاحيات والإعدادات (Platform, Auth, Roles & Settings)
هذا الموديول هو البنية التحتية للنظام بالكامل (إطار العمل المخصص "aw framework"): تسجيل دخول المستخدمين عبر مكتبة Login مدمجة، ومنظومة صلاحيات على أربعة مستويات (الدور ← الكنترولر ← الإجراء ← زر الواجهة، إضافةً إلى إظهار/إخفاء عناصر القائمة الجانبية لكل دور)، وسجل إعدادات البرنامج المركزي الذي يتحكم في معظم خصائص الشاشات الطبية والطباعة والترقيم، إلى جانب بنية الفروع والطوابق والأجهزة (غير مفعّلة عملياً)، وشاشة الانتظار للعرض في الاستقبال، وواجهة برمجية (API) لتطبيق موبايل للمريضات، وصفحات المساعدة، وعدد من الجداول التجريبية المهملة.
الوظائف الرئيسية
- تسجيل دخول وخروج المستخدمين بجلسات PHP مع خيار "تذكرني" عبر كوكي مؤمَّن، وتشفير كلمات المرور بخوارزمية bcrypt، وإيقاف مؤقت بعد ثلاث محاولات فاشلة (مكتبة
_library/login_system). - التحقق من الصلاحية عند كل طلب: كل إجراء في كل كنترولر يستدعي
autho::checkauthoize()التي تطابق الدور مع الكنترولر والإجراء (awcontroll←awcontrollprop←awrolecontrollprop). - إدارة الأدوار (
_role.php) بمصفوفة صلاحيات تفاعلية: إظهار/إخفاء عناصر القائمة لكل دور، ومنح/منع كل إجراء لكل كنترولر، وأربعة أزرار سريرية مثبّتة بالكود (إضافة مريضة، إضافة زيارة، تعديل زيارة، حذف زيارة). - إدارة المستخدمين (
_member.php) مع ربط كل مستخدم بدور ووظيفة (awroleposition) وتخصص (awrolespecialize) يُحمَّلان ديناميكياً حسب الدور. - إدارة شجرة القائمة الجانبية (
_menu.php) بالسحب والإفلات، مع وضعَي عرض (مبسّط/كامل) يتحكم بهما إعدادsimpleview، وخاصية ربط الرابط بالمريضة الحالية (withpatient). - سجل إعدادات مركزي واحد (
programesetting) بنحو 75 عموداً: بيانات المركز والطبيب، هوامش وخطوط الطباعة، تفعيل/تعطيل أقسام التاريخ المرضي والسونار والعقم، عدّادات أرقام الإيصالات الشهرية، وربط قاعدة بيانات ERP خارجية. - أداة الإعداد (
setup.php) المحمية بكلمة مرور ثابتة: ربط قاعدة ERP واختيار الخزينة الافتراضية، وروتين خطير لتفريغ جداول قاعدة البيانات مع قائمة استثناء مثبّتة بالكود. - تطبيق شاشة الانتظار (
screen/): يعرض صوراً دعائية منscreen_sliderمع اسم المريضة المُنادى عليها وقائمة الخمس التاليات من زيارات اليوم، بتحديث دوري عبر AJAX. - واجهة API لتطبيق موبايل المريضات (
mobileservices.php): تسجيل مريضة جديدة بكلمة مرور، تسجيل دخول بالموبايل، حجز وتعديل وإلغاء الزيارات، عرض الروشتات، وقراءة محادثات الدردشة، مع مزامنة بيانات العميلة مع نظام ERP خارجي عبر curl. - إدارة مقالات المساعدة (
help.php) بإضافة وتعديل وحذف ناعم. - بنية جاهزة (غير مفعّلة) لتعدد الفروع والطوابق والأجهزة وتتبّع حركة المريضة بين الأجهزة (
branches,floors,devices,device_tracking) ورسائل داخلية بين المستخدمين (messages).
الجداول وبنية البيانات (Data Models)
| الجدول | الغرض | أهم الحقول | العلاقات |
|---|---|---|---|
awcontroll | سجل الكنترولرات الخاضعة لنظام الصلاحيات (81 صفاً مزروعاً يغطي كل شاشات النظام) | id, label, name | أب لـ awcontrollprop عبر awcontroll_id |
awcontrollprop | الإجراءات (actions) المتاحة لكل كنترولر مع قيمة سماح افتراضية (index, addit, show, edit, updateit, del...) | id, proplabel, checkval, awcontroll_id | awcontroll عبر awcontroll_id |
awmenu | شجرة القائمة الجانبية (102 عنصر) بمستويين مع الترتيب والأيقونات ووضع العرض المبسّط/الكامل | label, link, parent, sort, icon, form, withpatient | ذاتية عبر parent؛ awrolemenu عبر menu_id |
awrole | الأدوار الوظيفية (Management, pharmacist, reception, doctors, rays, assistants...) | id, name | أب لجداول الصلاحيات والمستخدمين عبر role_id |
awrolebtn | صلاحيات أزرار الواجهة لكل دور؛ أربعة أزرار مثبّتة بالكود (1 إضافة مريضة، 2 إضافة زيارة، 3 تعديل زيارة، 4 حذف زيارة) | role_id, btn_id, checkval | awrole عبر role_id |
awrolecontrollprop | مصفوفة منح/منع كل إجراء لكل دور (نحو 3000 صف) | role_id, controllprop_id, checkval | awrole عبر role_id، awcontrollprop عبر controllprop_id |
awrolemenu | إظهار/إخفاء عناصر القائمة الجانبية لكل دور | role_id, menu_id, checkval | awrole عبر role_id، awmenu عبر menu_id |
awroleposition | الوظائف داخل الدور (مثل: Council Head, Sonographer, Supervisor) | id, roleid, name | awrole عبر roleid؛ awusers عبر positionid |
awrolespecialize | التخصصات داخل الدور (Anasthests, operation للأطباء والمساعدين) | id, roleid, name | awrole عبر roleid؛ awusers عبر specialid |
awusers | حسابات الموظفين: بيانات الدخول والتفعيل واستعادة كلمة المرور ومحاولات الدخول الفاشلة والدور والفرع | user_id, user_name, user_password_hash, role_id, specialid, positionid, branch_id, attend | awrole عبر role_id؛ branches عبر branch_id (استنتاج، القيمة "-1" تعني كل الفروع) |
programesetting | سجل الإعدادات المركزي الوحيد (~75 عموداً): هوية المركز، الطباعة، مفاتيح تفعيل الخصائص، أقسام التاريخ المرضي، عدّادات الإيصالات، ربط ERP، بيانات بريد بنص صريح | centername, simpleview, erpdb, erpdbsave, serial_month, last_serial, last_refund_serial, branches, email, password | قاعدة ERP خارجية عبر erpdb/erpdbsave |
branches | فروع المركز — جدول فارغ وملف الكنترولر Branches.php غير موجود رغم تسجيله في القائمة والصلاحيات | id, name, created_at, updated_at | awusers عبر branch_id (استنتاج) |
floors | طوابق المبنى — فارغ وغير مستخدم في الكود | id, name, deleted, default_value | devices عبر floor_no (استنتاج) |
devices | الأجهزة/الغرف داخل الطوابق — فارغ، الكنترولر adddevices مسجّل في awcontroll لكن الملف غير موجود | device_name, location, floor_no, deleted | floors عبر floor_no |
device_tracking | تتبّع حركة المريضة بين الأجهزة بإشارة متعددة الأشكال (polymorphic) لأي سجل سريري — ميزة مخطَّطة غير منفَّذة (استنتاج) | patient_id, device_id, target_id, target_table, visit_date, visit_time, user_id | patients عبر patient_id، devices عبر device_id، awusers عبر user_id |
messages | رسائل داخلية بين المستخدمين — فارغ ولا يوجد كود يستخدمه (دردشة المريضات تتم عبر جدول chat في موديول آخر) | message, sender_id, receiver_id, created_at | awusers عبر sender_id وreceiver_id |
screen_slider | صور العرض الدوّار على شاشة الانتظار في الاستقبال | id, image, create_date | تُقرأ في تطبيق screen/ مع جدولي visits وpatients |
help | مقالات المساعدة داخل النظام مع حذف ناعم | name, content, tempdelete | لا علاقات |
table2 | جدول تجريبي مهمل — فارغ بلا أي استخدام | id, name2 | لا علاقات |
table3 | جدول تجريبي مهمل — فارغ بلا أي استخدام | id, name | لا علاقات |
tablename | بقايا قالب إنشاء جداول — فارغ ومهمل | id, del | لا علاقات |
testtbl1 | جدول اختبار مهمل — فارغ | id, name2 | لا علاقات |
testtbl2 | جدول اختبار مهمل — فارغ | id, name | لا علاقات |
سير العمل (Workflow)
- يفتح المستخدم
login.phpفتتحقق مكتبة Login من اسم المستخدم وكلمة المرور فيawusers(bcrypt) وتكتب في الجلسةuser_idوrole_id، مع إيقاف مؤقت بعد ثلاث محاولات فاشلة وخيار "تذكرني" بكوكي مؤمَّن. - عند فتح أي شاشة، يستدعي الكنترولر
autho::checkautho()للتأكد من تسجيل الدخول ثمautho::checkauthoize()التي تبحث عن الكنترولر فيawcontrollوالإجراء فيawcontrollpropثم قرار الدور فيawrolecontrollprop، وعند الرفض يُحوَّل المستخدم إلى صفحة خطأ الصلاحية. - تُبنى القائمة الجانبية من
awmenuتكرارياً حسبparentوsort، مع تصفية حسب وضع العرض (programesetting.simpleviewمقابلawmenu.form) وصلاحية الدور فيawrolemenu، وإلحاق رقم المريضة الحالية بالروابط الموسومةwithpatient. - ينشئ مدير النظام دوراً جديداً في
_role.phpثم يضبط مصفوفته: عناصر القائمة (إظهار/إخفاء)، وكل إجراء لكل كنترولر (سماح/منع)، والأزرار السريرية الأربعة فيawrolebtnالتي تُنشأ تلقائياً عند أول فتح. - يضيف المدير المستخدمين في
_member.php: فحص فوري لتفرّد اسم المستخدم، ثم إدراج مباشر فيawusersمع الدور والوظيفة والتخصص المحمّلَين حسب الدور المختار. - يضبط المدير إعدادات البرنامج في
programesetting.php(شعار وخلفية وهوامش طباعة ومفاتيح تفعيل أقسام الملف الطبي...) فتُحدَّث الصف الوحيد رقم 1 الذي تقرأه كل الشاشات السريرية. - من شاشة
setup.php(كلمة مرور ثابتة 123456) يُربط النظام بقاعدة بيانات ERP خارجية وتُختار الخزينة الافتراضية من جدولsaveفيها، وتوجد أيضاً أداة تفريغ شامل للجداول للبدء من جديد. - تعمل شاشة الانتظار
screen/controllers/index.phpدون تسجيل دخول: تعرض صورscreen_sliderواسم المريضة المُنادى عليها (زيارة اليوم ذاتview=1وend_visit=0) وقائمة الخمس التاليات، وتُحدَّث عبر AJAX منloadInfo. - تطبيق الموبايل يستدعي
mobileservices.phpمباشرة (دون مصادقة): تسجيل مريضة، دخول بالموبايل وكلمة المرور، حجز زيارة (كشف/سونار/إعادة)، عرض الروشتات منgynadrugsوdrugs، وقراءة الدردشة، مع مزامنة بيانات العميلة مع نظام ERP عبر curl ومفتاح API مثبّت بالكود.
الارتباط بالموديولات الأخرى
- موديول المرضى:
device_tracking.patient_idوكل دوالmobileservices.phpتكتب وتقرأ في جدولpatients، وشاشة الانتظار تقرأpatients.wifename. - موديول الزيارات: شاشة الانتظار وواجهة الموبايل تتعاملان مع جدول
visitsعبرpatientidوحقلَيviewوend_visit. - موديول الوصفات والأدوية: عرض الروشتات في الموبايل يقرأ
gynadrugs.drugidالمرتبط بكتالوجdrugs. - موديول الدردشة/المتابعة:
mobileservices.php::selectChattingيقرأ جدولchatالمرتبط بـpatients.id. - كل الموديولات السريرية والمالية: تعتمد على
awusers.user_id(المستخدم المنفّذ) وعلى مفاتيحprogramesettingوعلى التحقق المركزي في_autho.php. - نظام ERP الخارجي:
programesetting.erpdbوerpdbsaveيربطان بقاعدة بيانات ERP منفصلة (جدولsaveللخزائن) مع مزامنة العملاء عبر curl فيmobileservices.php. - موديول الترخيص/النسخ الاحتياطي: شاشة الدخول تتضمن فحص ترخيص (معطَّل بالتعليق) على جدول
excelinfo، وإعدادات النسخ الاحتياطي (backupdest,backupdriver) فيprogramesetting.
ملاحظات فنية
- لا توجد أي مفاتيح أجنبية معلنة؛ كل العلاقات مستنتجة من أسماء الأعمدة واستعلامات الكود، و
awusers.branch_idنص (varchar) بقيم سحرية ("-1" تعني كل الفروع). - ميزة الفروع والأجهزة غير مكتملة: جداول
branchesوfloorsوdevicesوdevice_trackingفارغة، وملفا الكنترولرBranches.phpوadddevices.phpغير موجودين رغم تسجيلهما في القائمة والصلاحيات. - ثغرات أمنية جوهرية: نقاط API في
mobileservices.phpبلا مصادقة ومعAccess-Control-Allow-Origin: *، وحقن SQL فيpatientLoginوgetErpSave(تجميع نصي مباشر)، وكلمة مرور شاشة الإعداد ثابتة (123456)، وبيانات اتصال قاعدة البيانات ومفاتيح ERP API مكتوبة نصاً صريحاً في_public/aw_config.phpوapi_config.php، وبريد وكلمة مرور بنص صريح فيprogramesetting. - مكتبة JWT (
_library/php-jwt-master) مرفقة لكن لا يوجد أي استدعاء لها في الكود — تبعية ميتة. - تطبيق شاشة الانتظار ينفّذ
ALTER TABLE visitsأثناء التشغيل لإضافة عمودend_visitإن لم يوجد — تعديل مخطط بيانات وقت التشغيل وهو نمط خطير. - جدول
awusersبمحرك MyISAM (لا معاملات)، وعدّادات أرقام الإيصالات (last_serial) في صف الإعدادات معرّضة لتعارض التزامن. - أزرار الصلاحيات الأربعة في
awrolebtnمثبّتة بالكود داخل_role.phpوليست جدول مرجعي قابل للتوسعة. - خمسة جداول خردة/اختبار يجب حذفها:
table2,table3,tablename,testtbl1,testtbl2— كلها فارغة وبلا أي استخدام. - روتين
settingdatabase()فيsetup.phpقادر على تفريغ معظم جداول قاعدة البيانات بقائمة استثناء مثبّتة بالكود — مخاطرة تشغيلية عالية.
توصيات النقل إلى ERP
- المصادقة: استبدال مكتبة login_system بمصادقة Laravel الأصلية مع Sanctum لتطبيق Angular وواجهة الموبايل، ونقل
awusersإلى جدولusersقياسي (مع حذف أعمدة التفعيل والتذكّر لأن الإطار يتولاها). - الصلاحيات: استبدال الجداول الخمسة (
awcontroll,awcontrollprop,awrolecontrollprop,awrolemenu,awrolebtn) بحزمة spatie/laravel-permission بصيغة صلاحية لكل إجراء (مثلvisits.delete)، وتحويل أزرار الواجهة الأربعة إلى صلاحيات مسماة، وبناء القائمة في Angular بحراسة المسارات حسب الصلاحيات بدل جدول قائمة في قاعدة البيانات. - الوظائف والتخصصات: تحويل
awrolepositionوawrolespecializeإلى جدولَيpositionsوspecializationsمرجعيين مرتبطين بالمستخدم. - الإعدادات: تفكيك
programesetting(75 عموداً) إلى جدول إعدادات مفتاح/قيمة مجمّع (هوية المركز، الطباعة، الخصائص، أقسام الملف الطبي)، ونقل بيانات البريد إلى.env، وتحويل عدّادات الإيصالات إلى آلية تسلسل معاملاتية (sequences) آمنة من التزامن. - الفروع: اعتماد
branchesكنموذج أساسي بمفتاحbranch_idرقمي على المستخدمين والزيارات والماليات، واستبدال القيمة السحرية "-1" بجدول ربطbranch_user. - الأجهزة والتتبع: إن كانت إدارة الطوابير مطلوبة فعلاً، إعادة تصميمها كنماذج
Room/Device/PatientFlowEventبعلاقة polymorphic؛ وإلا حذفfloorsوdevicesوdevice_trackingوmessagesلأنها فارغة وغير مستخدمة. - شاشة الانتظار: نموذج
ScreenSlideمع صفحة عرض عامة في Angular تستهلك نقطة "طابور اليوم" عبر polling أو WebSocket، ونقل عمودvisits.end_visitإلى migration رسمي في موديول الزيارات. - واجهة الموبايل: إعادة بناء
mobileservices.phpكـ REST API موثّق ومصادَق عليه (Sanctum)، مع معالجة إلزامية لثغرات الحقن وفتح CORS قبل أي إطلاق، ونقل مفاتيح ERP إلى إعدادات مشفّرة. - الحذف: إسقاط الجداول التجريبية الخمسة ومكتبة JWT غير المستخدمة، وعدم نقل أداة تفريغ قاعدة البيانات وكلمة المرور الثابتة في
setup.php(تُستبدل بأوامر artisan محمية). - النماذج المقترحة:
User,Role/Permission(spatie),Position,Specialization,Branch,Setting,ScreenSlide,HelpArticle, واختيارياًMenuItemوRoom/Device/PatientFlowEvent.
خريطة العلاقات الشاملة (ERD)
قاعدة البيانات تضم 312 جدولًا بدون أي مفتاح أجنبي مُعلن (Declared Foreign Key) على الإطلاق؛ جميع العلاقات «ضمنية» تُفهم من تسمية الأعمدة (patientid, doctorid, ancsheetid, ...) ومن جمل JOIN داخل الكنترولرات في core/controllers. هذا القسم يرسم الخريطة الكلية: الكيانات المحورية الأربعة (المريضة، الزيارة، المستخدم، الفرع)، والعلاقات الرئيسية بينها وبين الموديولات الإكلينيكية، وأنماط التصميم الثلاثة المتكررة (نمط الشيت الأب وأبنائه، نمط جداول الترميز الصغيرة، نمط EAV للتحاليل الحرة)، ثم قائمة الجداول المكررة والمهجورة المكتشفة في الـ dump.
الكيانات المحورية (Hub Entities)
patients— مركز النظام بأكمله: يرتبط به 73 جدولًا مباشرة عبر العمودpatientid(وأحيانًاpatient_id): الزيارات، كل الشيتات الإكلينيكية (حمل/نساء/عقم/حقن مجهري/متابعة تنشيط)، كل جداول التاريخ المرضيph*، الفحوصات والأشعة والمناظير، الأدوية والتحاليل، الأرصدة المالية، الملفات المرفوعة. السجل الواحد يضم الزوجة والزوج معًا.awusers— المستخدمون والأطباء: يرتبط به 59 جدولًا عبر أعمدة متعددة الأسماء:doctorid(في ~45 جدولًا إكلينيكيًا)،userid/user_id(إدخال البيانات)،memberid(موديول البورد)،assistantid/anasthetstsid(فريق العمليات)،enddoctorid(إنهاء الزيارة)،sender_id/receiver_id(الرسائل). مفتاحه الأساسيuser_idوليسid— استثناء عن بقية الجداول.visits— حركة الاستقبال اليومية: يرتبط صعودًا بـpatients.idوdetections.id(نوع الكشف وسعره) وvisit_periods.id(الفترة) وawusersوbranches. لافت أن الجداول الإكلينيكية لا تشير إلى الزيارة إطلاقًا — لا يوجد عمودvisitidإلا فيvisitsنفسه وvisits_updates(سجل التدقيق)؛ فالربط الإكلينيكي كله يتم عبرpatientid+ التاريخ، وهذه نقطة ضعف بنيوية تمنع ربط أي إجراء بزيارة بعينها.branches— الفروع: كيان حديث الإضافة؛ لا يرتبط به سوى جدولين:awusers.branch_idوvisits.branch_id— أي أن تعدد الفروع مطبق على مستوى الاستقبال والمستخدمين فقط، وكل البيانات الإكلينيكية مشتركة بين الفروع.- محاور ثانوية (الشيتات الأم):
infertilitysheetيرتبط به 17 جدولًا عبرinfertilitysheetid(أكبر شيت في النظام)،ancsheetيرتبط به 6 جداول عبرancsheetid،mointoringsheetله 3 جداول أبناء عبرmointoringsheetidو9 جداول ترميز خاصة به، وivfsheetجدولان (eprep,ovst).
العلاقات الرئيسية
| من (الجدول الابن) | إلى (الجدول الأب) | عمود الربط | النوع |
|---|---|---|---|
visits, old_visits, endvisitreports, lastvisit | patients | patientid → patients.id | 1:N |
الشيتات الأم: ancsheet, gynasheet, infertilitysheet, ivfsheet, mointoringsheet, followupcard, mainantenental, maingyna | patients | patientid → patients.id | 1:N (عمليًا 1:1 في gynasheet/infertilitysheet) |
التاريخ المرضي: phobstetric, phmenstrual, phfamily, phcontraception, phpastmedical, phpastsurgical, phpastgynecological, phpastart, phpasticsi, previous_marriage, hus_previous_marriage | patients | patientid → patients.id | 1:N |
الأشعة والمناظير: ultrasound, ultrasoundgyna, ultrasoundobst, gynaus, ustv, sonar, gtimage, hsg, hysteroscopy, laparoscopy, mrict, pathology, semen, hormon | patients | patientid → patients.id | 1:N |
visits | detections / visit_periods / branches / awusers | detectionid → detections.id، visit_period → visit_periods.id، branch_id → branches.id، user_id / enddoctorid → awusers.user_id | N:1 |
visits_updates, patients_updates | visits, patients | visitid → visits.id، patientid → patients.id (+ userid_edit) | 1:N (سجل تدقيق) |
ancsheetdrugs, ancsheetinvest, ancnewvisit, investigations, registeration, op_4d_list | ancsheet | ancsheetid → ancsheet.id | 1:N |
17 جدولًا منها: newvisit, tvs, dtvs, sis, folliculom, hormonalprofile, hormonalprofile2, semen2, semeninfertility, hsginfertility, hysteroscopyinfertility, laparoscopyinfertility, icsi, operations, wifep, awifep, wifeepc | infertilitysheet | infertilitysheetid → infertilitysheet.id | 1:N |
newvisitg | gynasheet | gynasheetid → gynasheet.id | 1:N |
gynasheetdrugs, gynasheetinvest, infertilitysheetdrugs, infertilitysheetinvest | gynasheet / infertilitysheet (عبر المريضة) | patientid فقط — لا يوجد عمود sheetid (شيت واحد لكل مريضة) | 1:N غير مباشر |
mointoringsheetdrugs, mointoringsheetinvestigation, mointoringsheetvisits | mointoringsheet | mointoringsheetid → mointoringsheet.id | 1:N |
mointoringsheet | 9 جداول ترميز: mointoringsheetprocedure/protocol/ejac/pesa/tese/sryo/hmg/agonist/hcg | procedure/protocol/... → {lookup}.id (مؤكدة بـ LEFT JOIN في الكنترولر) | N:1 |
eprep, ovst | ivfsheet | ivfsheetid → ivfsheet.id | 1:N |
followupcarddrugs | followupcard | cardid → followupcard.id | 1:N |
followupvisit, followupinvest, followupexam, followupdiagnosis | followup | followid → followup.id | 1:N |
13 جدول *drugs + pharmacystore + receiptdrugs + importdetails | drugs | drugid / drug_id / drugs_id → drugs.id | N:1 |
6 جداول *invest / *investigation | invests → investcats | investid → invests.id، invests.investcatid → investcats.id | N:1 |
*drugs ↔ recepittmp | recepittmp ← patients/awusers | recepittmpid → recepittmp.id؛ recepittmp.patient_id/doctor_id | N:1 |
otherinvestigationsvalues | otherinvestigationsrows + otherinvestigations | investrowid → rows.id، investid → otherinvestigations.id | N:M (نمط EAV) |
operativedetails, operativedetailsdrugs, operationids | operations / awusers | operationid → operations.id؛ doctorid/assistantid/anasthetstsid → awusers.user_id | 1:N + N:M (فريق العملية) |
gynausficils | gynaus | gynausid → gynaus.id (مؤكدة بـ JOIN) | 1:N |
presenthistoryanswers | presenthistoryquestions | catid/answerid في جداول الشكوى (مؤكدة بـ JOIN) | N:1 |
awusers | awrole / branches | role_id → awrole.id، branch_id → branches.id | N:1 |
awrolemenu, awrolecontrollprop, awrolebtn | awrole ↔ awmenu / awcontrollprop | role_id + menu_id / ... | N:M (صلاحيات) |
bsession, bsessionmembers, bcomments, bmemberopenion, brequests | bsession ↔ awusers | sessionid + memberid | N:M (بورد الأطباء) |
totalbalance, totalbalancepaids | patients / awusers | patientid, userid | 1:N (مالية) |
device_tracking | patients / awusers / أي جدول | patient_id, user_id, target_id + target_table (مرجع متعدد الأشكال Polymorphic) | N:1 |
أنماط التصميم المتكررة
- نمط «الشيت الأب + الأبناء» (Sheet Pattern) — النمط الجوهري للنظام: كل تخصص إكلينيكي له جدول شيت رئيسي مرتبط بالمريضة، وتتفرع منه جداول أبناء قياسية بنفس البنية دائمًا: جدول
*drugs(روشتة: drugid, drugtype, drugdos, forhusband, recepittmpid) وجدول*invest(تحاليل: investid, investresult, forhusband) وأحيانًا*us(سونار) و*visits(زيارات متابعة). الأمثلة:ancsheet→(ancsheetdrugs, ancsheetinvest, ancnewvisit)،gynasheet→(gynasheetdrugs, gynasheetinvest, newvisitg)،infertilitysheet→(infertilitysheetdrugs, infertilitysheetinvest, newvisit + 14 جدول فحوصات)،mointoringsheet→(drugs, investigation, visits)،mainantenental→(drugs, invest, us)،followupcard→(followupcarddrugs). البنية متطابقة لكنها منسوخة بالكامل لكل تخصص بدل توحيدها في جدول واحد بعمود نوع. - نمط جداول الترميز الصغيرة (Lookup Pattern): نحو 190 جدولًا (61% من القاعدة) بنية كل منها
id + title/name + del/deletedفقط، يغذي قائمة منسدلة واحدة في الشاشات. وصل الأمر إلى تخصيص جدول مستقل لكل حقل منسدل حتى داخل الموديول الواحد: 9 جداول لشيت التنشيط (mointoringsheet*)، 14 جدولًا لتقرير المنظار الرحمي/البطني (copy*,lapar*)، 7 جداول لنتائج السائل المنوي (semen2result*,semen2place*)، وجداول التاريخ المرضيph*. - نمط EAV (Entity–Attribute–Value) للتحاليل الحرة: ثلاثية
otherinvestigations(تعريف التحليل/العمود) ←otherinvestigationsrows(صف لكل مريضة + تاريخ + طبيب) ←otherinvestigationsvalues(القيمة: investrowid + investid + value). يسمح بإضافة أنواع تحاليل جديدة دون تعديل البنية، على حساب صعوبة الاستعلام والتقارير. - نمط سجل التدقيق بالنسخ:
patients_updatesوvisits_updatesنسخ كاملة من بنية الجدول الأصلي مضافًا إليهاuserid_edit/date_editلحفظ النسخ القديمة قبل التعديل. - نمط الحذف المنطقي غير الموحد: أربع تسميات مختلفة لنفس المفهوم:
deleted,del,tempdelete,status— يجب مراعاتها جميعًا عند أي ترحيل. - مرجع متعدد الأشكال (Polymorphic):
device_tracking.target_id + target_tableيشير إلى أي جدول بالاسم، وrecepittmp.drugstablenameيحدد جدول الروشتة المصدر نصيًا.
الجداول المكررة والمهجورة المكتشفة
| المجموعة | الجداول | الملاحظة |
|---|---|---|
| جداول تجارب مهجورة | table2, table3, tablename, testtbl1, testtbl2, patients_tmp | مخلفات تطوير بلا أي استخدام في الكود — آمنة الحذف بعد التحقق |
| استنساخ رباعي لنفس القائمة | ssemen, sseemen, sseemmen, sseemmeen | 4 جداول ترميز متطابقة البنية، أنشئ واحد لكل عمود من أعمدة السائل المنوي الأربعة في ivfsheet (ssemen/sseemen/sseemmen/sseemmeen) بدل جدول واحد بعمود نوع |
| أزواج شبه مكررة | antype/antypes، place/place2، importdetails/importtdetails، hormonalprofile/hormonalprofile2، semen/semen2، excelinfo/excelinfopatients | أجيال متعاقبة من نفس الوظيفة بقيت جنبًا إلى جنب (الإصدار 2 هو المستخدم غالبًا) |
عائلة copy* | copycavity, copycx, copydil, copyintrod, copylostium, copyrostium, copyplace + نسخ copym* (mcavity, mcx, mlostium, mrostium) | 10 جداول ترميز لتقرير المنظار الرحمي بدأت كنسخ (copy) وأصبحت أصلية، مع نسخة m* ثانية لكل منها تقريبًا |
| بيانات تاريخية | old_visits | أرشيف زيارات بنية قديمة (قبل إضافة الفروع والفترات) — للقراءة فقط |
| موديولات ANC متوازية | ancsheet+ancnewvisit مقابل mainantenental+antenalvisit مقابل followup+followupvisit | ثلاثة أجيال لمتابعة الحمل تعمل بالتوازي في الكود، لكل منها جداول أدوية/تحاليل خاصة |
| جداول معطلة/غير مفعلة | patientfiles, patients_updates (جزئيًا), help, messages | موجودة بالبنية لكن الكود الفعّال لا يكتب فيها أو يتجاوزها (استنتاج من مراجعة الكنترولرات) |
خطة النقل إلى نظام الـ ERP (ERP Migration Blueprint)
الهدف هو استيعاب نظام عيادة النساء والتوليد القديم (PHP/Smarty — 312 جدولًا بلا أي مفاتيح أجنبية) كموديول جديد Modules/Obgy داخل منظومة Moon ERP القائمة (Laravel/nwidart + Angular)، مع الاستغناء نهائيًا عن مزامنة cURL مع قاعدة الـ ERP الخارجية: يصبح المريض هو نفسه عميل الـ ERP، وتتكامل التحاليل مع موديول المعمل LIS، والصيدلية مع المخازن، والماليات مع الحسابات، والمستخدمون مع نظام الصلاحيات الموحد. المحصلة: تتقلص 312 جدولًا قديمًا إلى نحو 85 جدولًا جديدًا (~55 موديل نطاق + جدول قواميس موحد + جداول Pivot ووسائط)، مع إسقاط ~40 جدولًا ميتًا أو مشتقًا.
أولًا: أنماط الدمج العرضية (Cross-cutting Consolidation)
| النمط القديم | الحل المقترح |
|---|---|
~190 جدول قوائم صغيرة بنفس البنية id + title + del (منها رباعية ssemen/sseemen/sseemmen/sseemmeen و24 جدول lapar*/copy* و9 جداول mointoringsheet*) | جدول قواميس موحد obgy_lookups بأعمدة (domain, parent_id, title_ar, title_en, sort, is_active, deleted_at)، مع تحويل القوائم الطبية الثابتة (فصائل الدم، طريقة الولادة CS/SVD/NVD، توقيت الولادة FT/PT، أنواع فقدان الحمل) إلى Enums في الكود |
10 جداول روشتات مستنسخة (ancsheetdrugs, mainantenentaldrugs, gynadrugs, gynasheetdrugs, infertilitydrugs, infertilitysheetdrugs, mointoringsheetdrugs, followupcarddrugs, operativedetailsdrugs, recorddrugs) | جدولا visit_prescriptions + prescription_items بعلاقة Polymorphic نحو الشيت/الزيارة/الدورة، مع عمود المستفيد (زوجة/زوج) وكمية الصرف الفعلية |
8 جداول تحاليل مستنسخة (ancsheetinvest, mainantenentalinvest, gynainvestigation, gynasheetinvest, infertilityinvest, infertilitysheetinvest, mointoringsheetinvestigation, followupinvest) + ثلاثية EAV | جدولا visit_investigations (LabOrder) + lab_order_items بعلاقة Polymorphic، مرتبطان بكتالوج موديول المعمل LIS |
~40 عمودًا يخزن معرفات مفصولة بفواصل (CSV) مثل gyna.diagnosisid وoperations.operation | جداول Pivot حقيقية لكل علاقة، مع تسجيل المعرفات المعلقة في سجل أخطاء الترحيل |
ثلاثة أنماط حذف منطقي متضاربة (del / deleted / conditions) + جداول تدقيق منسوخة (patients_updates, visits_updates) | SoftDeletes (deleted_at) موحد + حزمة تدقيق قياسية laravel-auditing |
| نقاط AJAX عامة تستقبل اسم الجدول والعمود من المتصفح (ثغرة كتابة شاملة + حقن SQL) وواجهة موبايل بلا مصادقة | لا يُنقل أي منها: REST APIs محددة الموارد بـ FormRequests وPolicies ومصادقة Sanctum |
ثانيًا: خريطة الموديلات المقترحة حسب النطاق
1) المرضى والتسجيل
| الموديل المقترح | الجداول القديمة | ملاحظات الدمج |
|---|---|---|
Patient + ObgyPatientProfile | patients (نصف الزوجة) | المريضة تصبح هي سجل المريض/العميل في الـ ERP مباشرة؛ الملف الإضافي يحمل رقم الملف (بتسلسل معاملاتي بدل MAX+1) والرقم القومي والخطورة |
Spouse | أعمدة husband* في patients | فصل بيانات الزوج في جدول 1-1 |
PreviousMarriage | previous_marriage + hus_previous_marriage | دمج بعمود تمييز (زوجة/زوج) مع إصلاح ترميز latin1 |
ObstetricBaseline | أعمدة pno/cs/ab/ectopic/vmodel/svd | أرصدة افتتاحية رقمية للصيغة التوليدية |
MedicalRecord, DeliveryRegistration, MediaAttachment | records, registeration, patientfiles + مجلدات الرفع | تصحيح coast → cost decimal؛ وسائط بجدول حقيقي وروابط موقعة |
قواميس: JobTitle, PersonTitle, Complaint... | wifejobs+husbandjobs، wifetypes+husbandtypes، complaint+complaintant، education، wifestatus، risktype، origin | توحيد القوائم المزدوجة في obgy_lookups؛ فصائل الدم Enum؛ إسقاط patients_tmp وlocations وجداول التطوير |
2) المواعيد والزيارات وجسر الماليات
| الموديل المقترح | الجداول القديمة | ملاحظات الدمج |
|---|---|---|
Appointment + Encounter | visits (الحجز + الطابور) وfollowupcard | تفكيك الجدول المركب؛ ربط السجلات الإكلينيكية بـ encounter_id يعالج العيب البنيوي (لا يوجد ربط زيارة في أي جدول إكلينيكي) |
Service, VisitPeriod, ClinicClosure, TreatmentClosure | detections, visit_periods, vacations, endvisitreports | سعة الفترات تُفحص بمعاملة قاعدة بيانات؛ تفعيل الإجازات فعليًا في منع الحجز |
PatientLedgerEntry + Invoice + Payment | totalbalance + الأكواد السحرية في visits (-99 قسط / 999 سداد / 9999 مرتجع) | دفتر حساب بأنواع حركات Enum صريحة ورصيد محسوب؛ الترحيل للحسابات عبر Events |
| — | old_visits, visits_updates, lastvisit, totalbalancepaids | تُسقط: أرشيف ميت / تدقيق مهجور / مؤشر يُشتق بالاستعلام / جدول ميت |
3) النواة الإكلينيكية المشتركة والتاريخ المرضي
| الموديل المقترح | الجداول القديمة | ملاحظات الدمج |
|---|---|---|
ClinicalExamination + ExaminationFinding | examination + 9 جداول نتائج فحص متطابقة البنية | كتالوج نتائج موحد بعمود جهاز الجسم؛ إلغاء الإنشاء التلقائي عند العرض |
Diagnosis + Pivot | diagnosis + diagnosisant | دمج بعمود تخصص وجدول وسيط بدل CSV |
HistoryQuestion / HistoryAnswerOption / PatientHistoryAnswer | presenthistoryquestions/answers + جدول gynaph (وقت تشغيل) | gynaph غير موجود في النسخة الاحتياطية — يجب تصديره من الإنتاج |
Prescription/Item + LabOrder/Item | 18 جدول الروشتات/التحاليل المستنسخة + ثلاثية EAV | راجع جدول الأنماط العرضية أعلاه |
نماذج التاريخ المرضي: MenstrualHistory, ObstetricHistory+ObstetricBaby, ContraceptionHistory, PastMedical/Surgical/GynecologicalHistory, PastArtCycle+تفاصيل ICSI, FamilyHistory | جداول ph* التسعة + wifep/awifep + الكتالوجات المزدوجة و*dm | توحيد سجل الحمول السابقة في مصدر واحد وحساب الصيغة التوليدية كخدمة/Accessor؛ طريقة انتهاء الحمل Enum ثابت |
4) متابعة الحمل وأمراض النساء
| الموديل المقترح | الجداول القديمة | ملاحظات الدمج |
|---|---|---|
Pregnancy | ancsheet + mainantenental + followup | دمج ثلاثة أجيال متوازية لملف الحمل في كيان واحد؛ المطابقة بالمريضة + LMP وأعلام done/endpreg |
AntenatalVisit, AntenatalUltrasound, FourDScanBooking, ClinicalNote | ancnewvisit+antenalvisit+followupvisit، mainantenentalus+أعمدة T/TT-scan، op_4d_list، followupdiagnosis/exam/invest | عمر الحمل GA يُحسب ولا يُخزن؛ حالة 4D صريحة بدل أعلام البتات |
PregnancyLoss + قوائمه, ExternalProvider | wifeepc + wifeepctype/ttt، wifeobst+wifeepcobst | إعادة الربط بالمريضة مباشرة بدل شيت العقم؛ إسقاط anprotocol اليتيم |
GynaVisit, GynaSheet+GynaSheetVisit, GynaUltrasound+Follicle, InfertilityProfile+Plan | gyna، gynasheet+maingyna+newvisitg، gynaus+gynausficils، gynainfertility+أعمدة gyna.inf_* | القواميس التسعة الفارغة ← obgy_lookups مع التصدير من الإنتاج؛ إهمال شاشة gynasheet00 |
5) العقم والحقن المجهري وتحاليل الزوج
| الموديل المقترح | الجداول القديمة | ملاحظات الدمج |
|---|---|---|
InfertilityFile | infertility + جداوله الفرعية + infertilitysheet (64 عمودًا) | دمج الجيلين في ملف واحد لكل مريضة بجداول فرعية مهيكلة وPivot بدل CSV |
IvfCycle | ivfsheet + mointoringsheet | توحيد المسارين بقيد فهرس فريد جزئي = دورة نشطة واحدة لكل مريضة |
IvfCycleVisit + FollicleMeasurement | ovst + mointoringsheetvisits + folliculom | شبكة حويصلات مطبّعة (جانب/قطر/عدد) بدل 26 عمودًا مشفرًا |
OocyteRetrieval, SemenSample, EmbryoTransfer, Cryopreservation, EndometrialPrep, CycleOutcome | أعمدة مراحل ivfsheet + eprep + جدول sefo (وقت تشغيل) | نمذجة المراحل كجداول فرعية؛ إسقاط icsi المشتق واستبداله باستعلام |
SemenAnalysis, AndrologyInvestigation, HormoneResult+HormoneDefinition | semen+semeninfertility، semen2 العريض، hormon+hormonalprofile+hormonalprofile2 | تطبيع طولي (صف لكل فحص/هرمون) مع وحدة ومدى مرجعي وربط بـ LIS؛ حذف اليتيم sseemmeen وإعادة تسمية الرباعية المشوهة بعد مراجعة العيادة |
6) التصوير والمناظير والعمليات
| الموديل المقترح | الجداول القديمة | ملاحظات الدمج |
|---|---|---|
ImagingStudy + FetalScanFinding + GynaScanFinding | ultrasound(+detail), ultrasoundobst(+detail), ultrasoundgyna, tvs, dtvs, sis, hsg, hsginfertility, mrict, sonar | رأس دراسة موحد بنوع وحالة اعتماد؛ 16 جدول مفردات ← obgy_lookups؛ صور وفيديو السونار ← وسائط قياسية |
AnnotatedDiagram + DiagramMarker | gtimage + gtdetail | إحداثيات نسبية للعلامات |
EndoscopyProcedure + EndoscopyFinding + EndoscopyTerm | laparoscopy, hysteroscopy, laparoscopyinfertility, hysteroscopyinfertility + 24 قائمة lapar*/copy* | نموذج واحد بحقل نوع + جدول نتائج (موضع/تصنيف) بدل 26 عمود CSV + معجم موحد |
OperativeNote, SurgicalBooking, InfertilityOperation, Procedure, AnesthesiaType, IncisionType, Hospital, HistopathologyFinding, PathologyResult, Location | operativedetails(+drugs), op_wait_list, operations, operation, anasthesa+generalanasthesa, jncision+midlinejncision, hospitalnames, histopath, pathology, place+place2 | فريق العملية CSV ← Pivot بأدوار؛ دمج الأماكن بعمود نوع؛ إسقاط operationids؛ أدوية العمليات ← نظام الروشتات الموحد |
7) المعمل والصيدلية والمجلس والمنصة
| الموديل المقترح | الجداول القديمة | ملاحظات الدمج |
|---|---|---|
LabTestCategory + LabTest (طبقة Mapping على LIS) | investcats (22 فئة) + invests (276 بندًا) + EAV المخصص | كل بند قديم يُربط ببند كتالوج LIS عبر obgy_lis_test_map؛ إسقاط investigations القديم وexcelinfo (ترخيص) |
Drug, DrugCategory, DosageForm, Supplier, PurchaseInvoice/Item, StockMovement | drugs (~2000)، importbill+importdetails، pharmacystore، recepittmp+receiptdrugs | كتالوج الأصناف والمخزون يُسند لاحقًا لموديول مخازن الـ ERP؛ دفتر حركات برصيد محسوب يمنع السالب؛ إسقاط drugdos وimporttdetails |
BoardRequest, BoardSession, BoardSessionMember, BoardMemberOpinion, BoardComment | brequests, bsession, bsessionmembers, bmemberopenion, bcomments, councilstaff | إعادة بناء من الصفر (الجداول فارغة) مع إضافة patient_id الإلزامي وEnums للحالات ودمج العضوية في صلاحيات الـ ERP |
| منصة الـ ERP القياسية | awusers, awrole + 5 جداول صلاحيات, awmenu, programesetting, branches, mobileservices | Sanctum + spatie/laravel-permission؛ تفكيك الإعدادات إلى مفتاح/قيمة و.env؛ فروع بـ Pivot بدل "-1"؛ إعادة كتابة واجهة الموبايل بمصادقة إلزامية |
ثالثًا: نقاط التكامل مع منظومة Moon ERP
- ملف المرضى الموحد: إلغاء مزامنة cURL والقاعدة الثانية نهائيًا — مريضة العيادة هي عميل/مريض الـ ERP عبر
patient_id، مع جدول مطابقة لمعرفاتobygyPatientIdالتاريخية وأحداثPatientRegistered/Updatedلأي مستهلك داخلي. - موديول المعمل LIS: طلب التحاليل من أي شيت يطلق حدث
LabOrderPlacedينشئ أوردر في LIS بالبنود الممَيِّزة عبرobgy_lis_test_map، وترجع النتائج بحدثLabResultReceivedلتظهر داخل الشيت الإكلينيكي بدل النص الحر. - الصيدلية والمخازن: صرف الروشتة يطلق
PrescriptionDispensedفيُخصم المخزون وتُنشأ حركة بيع في موديول المخازن؛ كتالوج الأدوية يُساد (Master) في أصناف الـ ERP، والمشتريات بالكامل لموديول المشتريات. - الحسابات: أحداث
VisitInvoiced / PaymentReceived / RefundIssuedتنشئ فواتير وسندات وقيود في موديول الحسابات بدل دفتر اليومية المتخفي فيvisitsوأكواده السحرية؛ قائمة أسعار الخدمات (detections) تُدار من الـ ERP. - المستخدمون والصلاحيات: مخزن مستخدمين واحد، Sanctum للتوكنات، spatie/permission بصلاحية لكل إجراء قديم (~590) وصلاحيات مسماة للأزرار الإكلينيكية، ونطاق الفروع عبر
branch_user. - موديول المستشفى HMS المخطط: تُصمَّم كيانات
EncounterوOperativeNoteوSurgicalBookingوHospitalوخدمة الطابور بشكل غير مرتبط بالموديول ليعاد استخدامها من HMS لاحقًا.
رابعًا: مراحل التنفيذ (Phased Rollout)
- المرحلة 0 — التأسيس (حجم M): هيكل الموديول، إطار
obgy_lookupsوالـ Enums، حزمة التدقيق، عدة الترحيل ETL (محولات التواريخ والترميز وفاحص الأيتام)، وتصدير إلزامي من قاعدة الإنتاج (قيم القواميس + جداول وقت التشغيلsefo/gynaph/followupdrugs)، وربط المستخدمين والأدوار بمنظومة الصلاحيات. - المرحلة 1 — المرضى والاستقبال (L): دمج المريضة في ملف الـ ERP، فصل الزوج، الأرصدة الافتتاحية، المواعيد والطابور والفترات والإجازات، كتالوج الخدمات، دفتر حساب المريض وجسر الحسابات. أول تشغيل فعلي للاستقبال.
- المرحلة 2 — النواة الإكلينيكية والكتالوجات (L): الفحص والتشخيص ومحرك التاريخ المرضي، جدولا الروشتات والتحاليل الموحدان، ربط كتالوج التحاليل بـ LIS، وتكامل الصيدلية مع المخازن.
- المرحلة 3 — الحمل والنساء (L): دمج أجيال ملف الحمل الثلاثة، زيارات ومتابعات وسونار الحمل وحجوزات 4D وفقدان الحمل، وزيارات وشيتات وسونار النساء — أعلى حجم بيانات وأصعب إزالة تكرار.
- المرحلة 4 — العقم والحقن المجهري والأندرولوجيا (L): توحيد ملف العقم ودورة
IvfCycleوجداول المراحل وشبكة الحويصلات، وتطبيع السائل المنوي والهرمونات — الأغنى إكلينيكيًا ويتطلب اعتماد الأطباء لدلالات القوائم. - المرحلة 5 — التصوير والمناظير والعمليات (M): توحيد دراسات التصوير ونتائجها، معجم المناظير، المذكرات الجراحية وقوائم الانتظار والباثولوجيا.
- المرحلة 6 — المجلس والكروت والتقارير والموبايل (M): إعادة بناء مجلس الأطباء، قوالب التعليمات والتحويل، طبقة التقارير الإحصائية كاستعلامات + لوحات Angular، وواجهة موبايل REST موثقة وموثَّقة الهوية.
- المرحلة 7 — الوسائط والتحول النهائي (M): ترحيل 4.8 جيجابايت وسائط (جرد بالبصمات ثم rsync مرحلي ثم سجلات وسائط)، تشغيل متوازٍ مع مطابقة، ترحيل الفرق الأخير، تجميد النظام القديم للقراءة فقط، وإيقاف مزامنة cURL والقاعدة القديمة نهائيًا.
خامسًا: سجل مخاطر ترحيل البيانات
- غياب المفاتيح الأجنبية كليًا (312 جدولًا): كل العلاقات ضمنية — يلزم فحص أيتام مسبق لكل علاقة وفق قائمة الـ ERD، مع عزل السجلات اليتيمة في جدول
etl_orphansبسبب مسجل ومراجعة عينات مع الأطباء. - السجلات الإكلينيكية لا تشير لأي زيارة: الربط بالمريضة + التاريخ فقط؛ يُبنى مُطابق استدلالي (مريضة + تاريخ + قسم) لإسناد السجلات إلى
Encounter، وما لا يُطابق يُسند لزيارة تاريخية اصطناعية. - الجداول المكررة بالأجيال: ثلاثة مسارات لمتابعة الحمل، وجيلان للعقم، و
ivfsheetمقابلmointoringsheet، وأربعة جداول للسائل المنوي وثلاثة للهرمونات — قواعد دمج حتمية (مريضة + LMP/تاريخ) بأسبقية أجيال يعتمدها الأطباء، مع تقرير دمج لكل مريضة. - التواريخ نصوص: صيغ
Y/m/dو0000-00-00وفراغات ونصوص حرة — محلل دفاعي مع طابور رفض وإحصاءات لكل عمود. - أعمدة CSV متعددة القيم (~40 عمودًا): تفكيك إلى Pivot مع التحقق من القواميس وتسجيل المعرفات المعلقة كقيمة "غير معروف (قديم)".
- ترميز البيانات العربية: خلط latin1/utf8mb4 وقيم مشوهة — تحويل بمسار latin1 ← binary ← utf8mb4 لكل جدول مع مراجعة بصرية لعينات الأسماء العربية، والقاعدة الهدف utf8mb4 بالكامل.
- النسخة الاحتياطية ≠ الإنتاج: جداول القواميس فارغة في نسخة 2024، وجداول وقت التشغيل (
sefo,gynaph,followupdrugs) وأعمدة RedBean الديناميكية غائبة — تصدير إنتاجي طازج قبل كل بروفة ترحيل مع بوابة مقارنة مخططات في خط الأنابيب. - 4.8 جيجابايت وسائط مرتبطة باصطلاح تسمية المجلدات فقط: جرد بالبصمات (Checksums) ثم نسخ مرحلي وسجلات وسائط بقاعدة البيانات وتحقق من الأعداد والأحجام، مع إبقاء الشجرة القديمة للقراءة فقط 6 أشهر.
- الأكواد المالية السحرية: (-99/999/9999 في
detectionidوالربط الذاتي) — إعادة اشتقاق معاملاتية إلى أنواع حركات صريحة ومطابقة الأرصدة لكل مريضة مع شاشات النظام القديم قبل التسليم للحسابات. - تضارب الهويات: أرقام ملفات بـ MAX+1 ومسودات
done=0وأرقام قومية مكررة — تمريرة إزالة تكرار (رقم قومي/هاتف/اسم+ميلاد) بطابور مراجعة بشرية، ولا تُرحَّل المسودات الخالية من بيانات إكلينيكية. - الديون الأمنية لا تُنقل: لا يُنقل أي من نقاط الكتابة العامة أو واجهة الموبايل المفتوحة أو استعلامات التقارير المدموجة نصيًا أو كلمات المرور الثابتة؛ بوابة اختبار اختراق قبل المرحلة 6، وقاموس مركزي لتصحيح الأعمدة المُهجَّأة خطأ (
husdandname,coast,registeration...).
ملحق: اكتشاف النسخة الثانية (مستشفى Green Nature) (MED Deployment Discovery)
أثناء استكمال العمل اكتُشفت نسخة ثانية عاملة من النظام القديم على نفس الخادم: med.greennature.com.sa في المسار /home/medgreennatureco/public_html/med. هي من نفس عائلة الكود، لكنها إصدار أحدث وأوسع مُهيّأ كـ«مركز/مستشفى» وليس عيادة نساء وتوليد فقط. هذا الملحق يلخّص حقائق النشر، وحجم الفروقات بالأرقام، والمجالات الوظيفية التسعة الجديدة، وأثر ذلك على خارطة الطريق. التحليل تم بقراءة الكود فقط (RedBeanPHP وSQL الخام وقوالب Smarty) دون أي تعديل على النسختين ودون لمس قاعدة البيانات الحيّة.
الإجابة المباشرة على سؤال الإدارة: هل أخذ التحليل الأصلي إعدادات المركز/المستشفى في الحسبان؟
لا — ولم يكن ذلك ممكنًا أصلًا. النسخة التي حُلِّلت في التقرير المنشور (/obgy، 312 جدولًا) لا تحتوي هذه القدرات إطلاقًا: لا كود تنويم، ولا معمل أجنة، ولا قسم أشعة، ولا عيادة ذكورة، ولا طبقة منظمات/تأمين. وما في MED ليس «إعدادات» لنفس البرنامج، بل نسخة أحدث متشعّبة (Fork) فيها كود إضافي ضخم: نعم توجد مفاتيح إعدادات كثيرة (programesetting أضافت 44 مفتاحًا جديدًا مثل system_type، branches، organizations، tanks_view)، لكن كل مفتاح يُفعّل مسارات كود غير موجودة في النسخة المُحلَّلة من الأساس. الدليل القاطع: MED تعتمد على تبعيات Composer (vendor/autoload.php، Monolog/Psr) لا وجود لها في OBGY — وتبعية Composer لا يمكن «تشغيلها بإعداد». الخلاصة: التقرير المنشور صحيح تمامًا لنطاق النسخة التي حلّلها، لكنه يغطي النواة العيادية فقط؛ وهذا الملحق يضيف النطاق المستشفوي المكتشف.
للمقارنة على مستوى الكود المشترك: من 57 ملفًا مشتركًا بالاسم، 21 متطابق تمامًا و36 مُعدَّل — وبعض التعديلات انفجارية (visits.php قفز من 1,946 إلى 9,660 سطرًا ومن 65 إلى 220 دالة). من إجمالي 413 جدولًا مُشارًا إليه في كود MED: 137 معروف من الـ312 الأصلية و~276 جديد، منها ~178 وُثّقت تفصيليًا في ملاحق المجالات (70–78).
حقائق النشر
| البند | النسخة المُحلَّلة (OBGY) | النسخة المكتشفة (MED) |
|---|---|---|
| المسار | /home/amrtechogate/public_html/obgy (نسخة تحليل) | /home/medgreennatureco/public_html/med (تشغيل حي) |
| الدومين | — | med.greennature.com.sa |
| قاعدة البيانات | dump بتاريخ 2024-07-12 (312 جدولًا) | medgreennatureco_med + اتحاد قواعد متعددة عبر R::addDatabase (erpDB/old/new/obor/royalDb) |
| نمط التشغيل | عيادة نساء وتوليد | مركز/مستشفى (system_type + فروع + مناطق + منظمات) |
| التطبيقات الفرعية | core, board, pharmacy | core, board, pharmacy, vote (كشك تقييم رضا المرضى) |
| سلسلة الأدوات | بدون Composer | Composer + Monolog/Psr؛ منطقة زمنية وضبط R::freeze مختلفان |
| تكامل ERP | لا يوجد | جسر حي مع Moon ERP (فواتير بيع، أطباء، مديونية عملاء) عبر cURL وقاعدة erpDB |
المجالات الوظيفية التسعة الجديدة (ملخص الملاحق 70–78)
| الملحق | المجال | جداول جديدة | أبرز ما فيه |
|---|---|---|---|
| 70 | التنويم وغرف العمليات (Inpatient & OR) | 9+ | غرف عمليات وإقامة على طوابق، محرّكا حجز متوازيان غير متزامنين (operations_main مقابل operations_rooms_cal)، لوحة إشغال حيّة؛ التنويم محمّل كأعمدة على جدول visits بلا كيان سرير/دخول مستقل |
| 71 | معمل أطفال الأنابيب والأجنة (Embryology/IVF Lab) | ~40 | ورقة معمل كاملة، تدريج الأجنة يوم 2–6، تجميد/إذابة، خزانات نيتروجين بنموذجي تخزين متوازيين، سجل عهدة tankcellhistory — كل ذلك غائب كليًا عن الأصل (كان ivfsheet مسطّحًا فقط) |
| 72 | وحدة مناظير موسّعة (Endoscopy Suite) | 14 | تضيف مناظير الجهاز الهضمي (معدة/قولون) خارج نطاق النساء أصلًا + 3 أنماط قوالب تقارير + أرشيف صور لكل منظار |
| 73 | عيادة الذكورة + قسم الأشعة (Andrology + Rays) | 29 | عيادة ذكورة مستقلة كاملة (زيارات/تاريخ/فحص/سونار/وراثة) وقسم أشعة بنمط «طلب → قائمة عمل → تقرير → صور → أرشيف» مع كتالوج مُسعّر |
| 74 | الفروع والمناطق والمنظمات وجسر ERP | 22 | نطاق فروع لكل مستخدم، تسلسل مناطق، منظمات متعاقدة (تأمين/شركات) بأرقام ملفات خاصة، جسر أجهزة مختبر ثنائي الاتجاه، تكامل مالي حي مع Moon ERP |
| 75 | تشغيل العيادات وخدمة العملاء (Clinic Ops & CRM) | 27 | جدولة أسبوعية طبيب×غرفة، مؤشرات انتظار وأداء أطباء، شكاوى مرضى، رسائل SMS بقالبين ومزوّدين، إقرارات موقّعة، تتبّع حركة الملفات الورقية، كشك تقييم رضا |
| 76 | المخزون المعملي والماليات (Inventory & Finance) | ~17 | قوائم أسعار وخصومات تعاقدية لكل منظمة، باقات فحوصات، نقطة بيع صيدلية bill_paying، معامل خارجية، نموذج نتائج مختبر مُطبَّع يستبدل نموذج «الأوراق» |
| 77 | حكم «إعدادات أم نسخة أحدث؟» (Config vs Fork) | — | الحكم بالأرقام: Fork حقيقي فوق نواة إطارية مشتركة؛ 21 كنترولر «أوراق» استُبدل بوحدات معيارية (ورقة IVF الواحدة → 6 وحدات معملية) |
| 78 | إحصاء المخطط الكامل (Schema Census) | 276 (إجمالي) | 413 جدولًا في الكود: 137 معروف + 276 جديد؛ visit أصبح كيان «اللقاء» المركزي بـ60+ عمودًا (تسعير، تأمين، توجيه بين الأقسام) |
الدلالة الاستراتيجية
- المورّد القديم سبق وطوّر النظام نحو «وضع المستشفى» بنفسه — وهذا يُثبت صحة اتجاه خارطة طريق HIS التي أقرّها المجلس: السوق احتاج فعلًا تنويمًا وعملياتٍ وفروعًا وتأمينًا، والمورّد بناها ولو بطريقة فوضوية (أعمدة على
visits، محرّكا حجز متوازيان، استعلامات SQL مُسلسلة نصيًا). - قدرات MED يجب أن تدخل كمدخلات نطاق في
Modules/Obgy(معمل الأجنة، الذكورة، المناظير الموسّعة) وفيModules/HIS(التنويم/الأسرّة/غرف العمليات/جدولة العيادات/المنظمات) — التفصيل في الملحق التالي (تعديلات خطة النقل §96). - MED هي خط الأساس الصحيح للهجرة وليس OBGY: هي النسخة الحيّة المتطوّرة، وبياناتها الإنتاجية (قاعدتان إنتاجيتان الآن) يجب أن تدخل في حسابات الـETL والتسعير.
- الدَّين الأمني تضاعف: إلى جانب ثغرات OBGY المعروفة، تضيف MED مفاتيح JWT وكلمات مرور SMS مكتوبة صلبًا في الكود، ونقطة تجاوز مصادقة في تقارير العمليات — تُعالج ضمن مسار المعالجة التشغيلية (المرحلة 0b) ولا يُنقل أي منها للنظام الجديد.
ملحق: الإقامة الداخلية وغرف العمليات (MED: Inpatient & OR Management)
هذه الوحدة هي «جوهرة» نسخة المركز/المستشفى (MED) المكتشفة على med.greennature.com.sa، وهي غير موجودة في النسخة الأصلية التي جرى تحليلها (312 جدولاً). تُدير غرف العمليات وغرف الإقامة الداخلية (التنويم) عبر طابقين منطقيين: حجز بالساعات (Hourly Reservation) وتقويم تفاعلي (FullCalendar) مع تتبّع إشغال الغرف لحظياً وتقارير تشغيلية للعمليات والإقامة. تمثّل دليلاً مباشراً على خارطة طريق التنويم في نظام معلومات المستشفى (HIS).
for_departmentنظرة عامة على البنية
تنقسم الوحدة إلى ثلاث مناطق وظيفية مترابطة. الأولى: التعريفات الأساسية (غرف العمليات، غرف الإقامة، أنواع العمليات). الثانية: محركات الحجز وهي محركان متوازيان — محرّك «الساعات» القديم (operations_reserve) الذي يقسّم اليوم إلى خانات نصف/كامل الساعة ويخزّنها سطراً لكل ساعة، ومحرّك «التقويم» الأحدث (operations_calendar) المبني على FullCalendar بموارد (Resources) يخزّن العملية في صف واحد يحمل وقت بداية ونهاية. الثالثة: التقارير والإشغال اللحظي (تقارير العمليات والإقامة، تقرير الغرف، قائمة اليوم).
اكتشاف معماري مهم: توسعة جداول قائمة وليست جداول جديدة فقط
- أنواع العمليات لا تستخدم جدولاً جديداً، بل تُعاد كتابتها فوق جدول
detectionsالموجود أصلاً بإضافة العلمfor_operation = 1وأعمدة جديدة (استنتاج من الكود):operation_time،residence_time،operations_rooms،cost_details،instructions،sort. الجدول الأصلي في الـ dump يحوي فقطid, title, detectionval, del. - جدول
visitsالأصلي لا يحوي أي عمود تنويم/عمليات. نسخة MED أضافت إليه (استنتاج) أعمدة الإقامة وغرفة العملية:for_department،for_doctor،for_husband،room_no،res_room_no،bed_no،enterance،p_exit،res_enterance_date،res_enterance،res_p_exit،recep_enterance،recep_p_exit،operation_attend،operation_result،operation_time،op_card_add،rec_card_add،today_list،today_list_dept،today_list_sort،in_clinic،clinic_entered،child. - قسم العمليات يُعرّف بثابت سحري
for_department = 13، وأطباؤه عبرawrole(id=13).related_dr_depts(قائمة أدوار مفصولة بفواصل).
جدول الكيانات
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
operations_rooms | جديد | غرف العمليات (OR) موزّعة على طوابق | name, start_time, end_time, floor_no, branch_id, create_date, deleted | floor_no→floors.id، branch_id→branches |
residence_rooms | جديد | غرف الإقامة الداخلية (التنويم) | name, start_time, end_time, floor_no, create_date, deleted | floor_no→floors.id |
operations_rooms_cal | جديد | سجل العملية في محرك التقويم (صف واحد للعملية) — يجمع غرفة العملية وغرفة الإقامة معاً | room_id, res_room_id, patient_id, patient_name, doctor_id, assistant_id, operation_type_id, date, start_time, end_time, res_start_time, res_end_time, cost, cost_details, instructions, for_husband, vip, notes, contacted_patient, contacted_user_id, sms_message, created_by, updated_by, created_at, updated_at | room_id→operations_rooms، res_room_id→residence_rooms، patient_id→patients، doctor_id/assistant_id→awusers، operation_type_id→detections |
operations_main | جديد | رأس الحجز في المحرك القديم (الساعات) — يربط العملية بساعاتها ونوعها | doctor_id, the_date, operation_types_id, operation_hours, residence_hours, operations_rooms_id, residence_rooms_id, create_date | →operations_rooms، →residence_rooms، →detections، →awusers |
doctors_reserves | جديد | سطر حجز لكل ساعة في غرفة عملية (المحرك القديم) | doctor_id, operations_room_id, hour_text, the_date, operation_type, operation_main_id | operation_main_id→operations_main، operations_room_id→operations_rooms |
residence_reserves | جديد | سطر حجز لكل ساعة في غرفة إقامة (المحرك القديم) | doctor_id, residence_room_id, hour_text, the_date, operation_type, operation_main_id | operation_main_id→operations_main، residence_room_id→residence_rooms |
operation_data | جديد | «بورد» تفاصيل العملية المرتبط بالزيارة (طاقم تخدير/تمريض ونتائج) | visit_id, deleted (+ أعمدة الطاقم — استنتاج) | visit_id→visits |
detections (موسّع) | معروف+توسعة | يُعاد استخدامه كـ «أنواع العمليات» عبر for_operation=1 | أضيف: for_operation, operation_time, residence_time, operations_rooms, cost_details, instructions, sort | operations_rooms = قائمة معرّفات غرف مفصولة بفواصل أو -1 (الكل) |
visits (موسّع) | معروف+توسعة | الزيارة هي حامل بيانات الإقامة الفعلية ودخول/خروج المريض من الغرف | أضيف (استنتاج): for_department, room_no, res_room_no, bed_no, enterance, p_exit, res_enterance_date, res_p_exit, op_card_add, today_list, today_list_dept, in_clinic | res_room_no→residence_rooms، room_no→operations_rooms |
floors | معروف | الطوابق (السادس/السابع/الثامن مستخدمة فعلياً) | id, name, deleted | مرجع لـ floor_no |
clinic_rooms / clinic_reserves | جديد | غرف وحجوزات العيادات (تستخدمها قائمة اليوم لتوزيع الأقسام والطبيب الحالي) | today_list, room_id, reserve_day_no, reserve_hour, doctor_id, is_active | →visits.today_list_dept، →awusers |
دورة حياة الحجز (محرك التقويم — الأحدث)
- تحميل التقويم:
index()يجهّز غرف العمليات والإقامة وأنواع العمليات والأطباء (دور 13). - الموارد:
rooms()وresidenceRooms()تُرجعان قائمة الغرف كـ JSON resources مرتّبة بالطابق. - الأحداث:
events()يقرأoperations_rooms_calضمن نطاق تاريخ، ويلوّن الحدث حسب الطابق/VIP، ويكشف التعارض بفحص تقاطع الأوقات في نفس الغرفة (لون أحمر عند التعارض). - اختيار المريض:
searchPatients()بحث حي فيpatientsبالاسم أو رقم الملفstatusno. - الحفظ:
saveOperation()ينشئ صفاً واحداً فيoperations_rooms_calيحمل غرفة العملية وغرفة الإقامة معاً مع أوقاتهما والتكلفة والتعليمات والطبيب والمساعد. - التعديل/الحذف:
getOperation()/updateOperation()/removeOperation()(حذف فعلي عبرR::trash). - التعبئة التلقائية:
getOperationTime()يجلب من نوع العملية مدّتها ومدّة الإقامة والتكلفة والتعليمات لملء النموذج.
دورة حياة الحجز (المحرك القديم — الساعات)
index(): اختيار نوع العملية والتاريخ.search(): بناء شبكة ساعات (خانات نصف ساعة) لكل غرفة عملية ضمن طابقها؛ الأخضر متاح، الأحمر محجوز (موجود فيdoctors_reserves)، الرمادي خارج ساعات الغرفة.residence(): شبكة ساعات لغرف الإقامة بعد ساعة نهاية العملية مباشرة، مع فحصresidence_reserves.reserve(): ينشئ رأساً فيoperations_mainثم سطراً لكل ساعة فيdoctors_reservesولكل ساعة إقامة فيresidence_reservesمربوطة بـoperation_main_id.removeRoom(): تفريغ الساعات المحجوزة (R::trash).
الإشغال اللحظي والتقارير
roomsreport: لوحة إشغال غرف الإقامة الآن — يربطresidence_roomsبـvisitsحيثfor_department=13وres_enterance_date IS NOT NULLوres_p_exit IS NULL(مريض داخل الغرفة حالياً)، ويعرض المريض/الطبيب/نوع العملية وأوقات الدخول/الخروج.operationreport.operation_data(): شاشة طوابق غرف العمليات لحظياً (تحديث ذاتي كل 300 ثانية) تُظهر الغرفة المشغولة بزيارة جارية حسبenterance/p_exitضمن وقت الآن.operations_reports: تقارير العمليات (roomsلغرف العمليات بطابقي 8 و6،resReportلغرف الإقامة بطوابق 8/7/6) موزّعة على 24 خانة ساعة، مع تقرير قائمة (listReport/opReport) يجمع حسب نوع العملية والطبيب، وتقرير متابعة الاتصال بالمريض وإرسال SMS عبر بوابة smsmisr.today_list: قائمة مرضى اليوم موزّعة على غرف العيادات (clinic_rooms) مع سحب وإفلات للترتيب وتتبّع «المريض الحالي» داخل العيادة عبرin_clinic/clinic_entered، والطبيب المناوب عبرclinic_reserves.operationreport.search/showprint: تقرير عمليات بفترة زمنية يربطvisitsبأسماء الغرف والطبيب ونوع العملية مع طباعة.
التسعير
التسعير يُحمل من نوع العملية: detections.detectionval (التكلفة) مع cost_details النصية وoperation_time/residence_time (المدد). عند الحفظ في التقويم تُنسخ القيم إلى operations_rooms_cal.cost وcost_details. لا يوجد محرك فوترة مستقل داخل هذه الوحدة — التكلفة وصفية ومرتبطة بنوع العملية فقط (استنتاج).
ملاحظات أمنية وتقنية
- حقن SQL: استعلامات خام كثيرة تبني
WHEREبدمج نصي مباشر للمدخلات (مثلfloor_no IN (...)،doctor_id = $doctorId،operations_rooms_id in (...)) — خطر حقن واضح يجب معالجته في الترحيل. - سر مكشوف: مفتاح بوابة الرسائل smsmisr (
password) مكتوب صراحةً داخلoperations_reports.sendSmsMisr()— يجب نقله إلى متغيّر بيئة وتدويره. - تجاوز مصادقة:
operation_details()يضبط$_SESSION['user_id']=123ويعطّل فحص الصلاحيات — منفذ تشخيصي خطر. - ثوابت سحرية:
for_department=13،awrole id=13، أرقام طوابق 6/7/8، ومرشّحdetections.id in (55,152,217,228)مكتوبة في الكود. - ازدواجية المحرّكين:
operations_reserve(الساعات) وoperations_calendar(التقويم) يكتبان في جداول مختلفة (doctors_reserves/operations_mainمقابلoperations_rooms_cal) — مصدران غير متزامنين لنفس مفهوم الحجز.
التأثير على خطة الـ ERP/HIS
- هذه الوحدة هي البذرة الجاهزة لوحدة التنويم/إدارة الأسرّة (IPD) في الـ HIS: يلزم نمذجة كيانات أولية مستقلة Room / Bed / Admission / OR-Slot بدل الاعتماد على توسعة
visitsوdetections. - يجب توحيد محرّكي الحجز في كيان حجز واحد (Reservation) بحالة (مجدول/جارٍ/منتهٍ/ملغى) ومنع التعارض على مستوى قاعدة البيانات بدل الفحص في PHP.
- فصل «نوع العملية» إلى كيان
OperationTypeمستقل بدل ركوب جدولdetections، مع جدول تسعير حقيقي مربوط بالفوترة. - نمذجة الإقامة (Residence/Bed occupancy) ككيان زمني صريح بسجلّ دخول/خروج مرتبط بالمريض والطبيب، بدل أعمدة
res_enterance_date/res_p_exitعلى الزيارة. - إضافة كيان طاقم العملية (جرّاح/مساعد/تخدير/تمريض) — موجود جنينياً في
operation_dataوassistant_idويجب توسعته. - قائمة اليوم وتقارير الإشغال اللحظي تثبت الحاجة لـ لوحة إشغال أسرّة/غرف لحظية في الـ HIS مع تتبّع موقع المريض.
- معالجة الديون الأمنية (حقن SQL، الأسرار المكشوفة، منافذ تجاوز المصادقة) شرط قبول قبل أي ترحيل.
ملحق: معمل الأجنة والتجميد (MED: Embryology Lab & Cryo)
يوثّق هذا الملحق منظومة معمل الأجنة الكاملة (Full IVF wet-lab) المكتشفة في نسخة المركز/المستشفى med.greennature.com.sa، والتي كانت غائبة تمامًا عن النسخة الأصلية المحلّلة (312 جدولًا). النسخة الأصلية اكتفت بورقة سريرية مسطّحة واحدة ivfsheet وجداول السائل المنوي semen/icsisemen، بينما تضيف نسخة المركز سلسلة عمليات معمليّة متكاملة: سحب البويضات، زراعة الأجنة وتقييمها (Grading يوم 2→6)، تجميد الأجنة والحيوانات المنوية وإذابتها، ومخزون خزّانات النيتروجين (Tanks/Canisters/Positions) مع سجل سلسلة عُهدة (Chain of Custody) وشهادة طرفين (Witnessing).
نطاق الملف ومصادر التحليل (Source Controllers)
tanks.php— تعريف الخزّانات وإنشاء شبكة الخلايا تلقائيًا + سجل العُهدةtankcellhistory.embryoslab.php— الورقة المعمليّة الرئيسية (~1670 سطرًا): السائل المنوي، البويضات، التقييم يوم2→يوم6، الإرجاع، التجميد، اختيار الجنس، مواقع الخزّان.embryofreezing.php— تقرير تجميد الأجنة + تفاصيل الأجنة (6 مراحل/درجات) + إذابةembryothawing.spermfreezing.php— تقرير تجميد الحيوانات المنوية + الوسط/البروتوكول + موقع الخزّان ولون القلم.ovumpickupembryotrans.php— سحب البويضات (OPU) + إرجاع الأجنة + تقرير متابعة العملية.embryology.php— تقرير تحليل السائل المنوي المعملي (Andrology).ivf_reports.php— طباعة/تجميع تقارير الـ IVF (قراءة فقط).
نموذج مخزون الخزّانات (Cryo Tank Inventory)
يوجد نموذجان متوازيان للتخزين الكرايو يتحكّم في اختيارهما الإعداد programesetting.tanks_view (القيمة 1 أو 2)؛ ويُظهر الإعداد awusers.tanks_settings أزرار الخزّان لكل مستخدم.
النموذج الأول: شبكة ثلاثية المستوى لكل خزّان (tanks / tankcells)
عند إنشاء خزّان في tanks.php يُولِّد النظام كل الخلايا مسبقًا داخل حلقة ثلاثية حسب tank_type:
| tank_type | المستوى الأول up_level_name | المستوى الثاني cell_name | الموضع cell_part_name | إجمالي الخلايا |
|---|---|---|---|---|
| 1 (Cane) | 1..10 | 1..20 | 1..5 | 1000 (يُعرض كـ 20) |
| 2 | 1..10 | 1..20 | 1..5 | 1000 (يُعرض كـ 100) |
| 3 | 1..10 | 1..30 | 1..10 | 3000 (يُعرض كـ 300) |
كل خلية tankcells تحمل patient_id؛ القيمة 0 تعني خلية فارغة. الحجز يتم بـ saveTankLabCell() الذي يضبط patient_id ويُسجّل في سجل العُهدة. العرض في cells() يجمع الامتلاء على ثلاثة مستويات (Level → Canister → Position).
النموذج الثاني: مواقع ثابتة بالألوان (tanks_general / embryoslab_tank_cells)
نموذج بديل (عندما tanks_view = 1) يقسّم الخزّان إلى موقعين location = "A"/"B"، كل موقع 21 زرًّا btn_no، وكل زر شبكة row_no/col_no/cell_no. تُخزَّن الخلية المحجوزة في embryoslab_tank_cells بمعرّف نصّي مركّب tank_cell = location_btn_row_col_cell (مثال A_3_2_1_4). جدول tanks_general يحمل 9 ألوان لكل صف (row1_color..row9_color) مرتبطة بجدول colors (الاسم color_name والحرف color_letter) لترميز المرضى بصريًا.
سلسلة العُهدة والشهادة (Chain of Custody & Witnessing)
- عُهدة جدول
tankcellhistoryيسجّل كل حركة:tank_id, cell_id, patient_id, action_type ('Add patient'/'Remove patient'), done_date, by_user_id. - شهادة طرفين في تجميد الحيوانات المنوية حقلان
embryologist1وembryologist2(مُوقِّع + شاهد). كذلك في الورقة المعمليّة حقول مُجمَّعة للحاقن:injection_embrologistومراجعicsi_by,embryologist_id,freeze_embryologist_id. - تتبّع تعديل صفوف
embryoslab_tank_cellsتحملuser_id, date_add, userid_edit, date_editوالحذف منطقيdeleted=1(لا حذف فعلي للحفاظ على الأثر). - إلغاء موثّق الورقة المعمليّة تسجّل
cancelled_userوcancelled_reverse_userعند الإلغاء والتراجع عنه. - دور أخصائي الأجنة موحّد عبر
awusers.role_id = 11(Embryologist) وrole_id = 4(Clinician)، مع جدول إضافيembryologistللأسماء خارج المستخدمين (مرجعية بـ بادئة*).
سير العمل من البداية للنهاية (End-to-End Workflows)
- سحب البويضات OPU —
ovumpickup: التاريخ، الاستشاريconsultant، طبيب التخديرanaesthetist، التمريضnurse، العملية، علاج ما بعد العملية، المضاعفات. يصاحبه تقرير متابعةfollowup_operation(ut_cx, avf_rvf, easy_difficult, postoperative, complications). - تحليل/معالجة السائل المنوي —
embryologyreport(count, motility, morphology, sperm_source) ومراجعsperum_source,semen_process. - إنشاء الورقة المعمليّة —
embryoslabبرأس واحد لكل مريض (not_confirm=0مسودّة →1مؤكَّدة)، مع وسط الزراعةmedia/oil/incubator(قوائم مفصولة بفواصل) وvisit_id. - التقييم اليومي Grading —
embryoscoringصف لكل جنين (itr) وأعمدة لكل يوم 1..6:media1..6, oil1..6, incubator1..6, embrologist1..6+ المرحلةstageوالدرجةgrade. عدد الصفوف يُشتق من عدد المخصّباتfertilizedData(). - اختيار الجنس/الانتقاء —
embryoselection(مرتبط بـembryoslab_id، مراجعembryo_result,embryo_emb). - الإرجاع ET —
embryotransfer(صف واحد لكل ورقة):clinician_id, embryologist_id, et_day+ قسطرة/صعوبة/دم/مكان (embryocathetertype, embryodifficulty, embryoblood, embryojetplace, embryolah, embryotype). كما يوجد إرجاع مستقلembryotransferovum. - تجميد الأجنة —
embryofreezingreport(no_of_straws, no_of_embryos, day_of_freezing, kit, device, lot_no, location) + صفوفembryo(6 مراحل/درجات لكل قشّة) + إذابةembryothawing(recovered, lost, e_t_date, cathetr). - تجميد الحيوانات المنوية —
spermfreezingreport(count, motility, a_plus_b, morphology_abn, samples_no, freezing_media_id, freezing_protocol_id, purpose_of_freezing, color_of_pen, embryologist1/2, location). - الحجز في الخزّان — ربط أي تقرير بموقع كرايو عبر أحد نموذجي التخزين، وتسجيل الحركة في
tankcellhistory.
جدول الكيانات المستنتَجة (Inferred Entities)
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
tanks | جديد | خزّان نيتروجين | name, tank_type (1/2/3) | 1→N tankcells |
tankcells | جديد | خلية تخزين مُولَّدة مسبقًا | tank_id, up_level_name, cell_name, cell_part_name, patient_id, created_at | N→1 tanks, → patients |
tankcellhistory | جديد | سجل عُهدة الخلايا | tank_id, cell_id, patient_id, action_type, done_date, by_user_id | → tankcells, awusers |
tanks_general | جديد | مواقع الخزّان البديلة بالألوان | location(A/B), btn_no, rows_letter, row1_color..row9_color | → colors |
embryoslab_tank_cells | جديد | حجز خلية لورقة معمليّة | embryoslab_id, location, btn_no, row_no, col_no, cell_no, tank_cell, user_id, date_add, userid_edit, date_edit, deleted | N→1 embryoslab, → tanks_general |
colors | جديد | ترميز لوني للمرضى | color_name, color_letter | مرجع لـ tanks_general |
embryoslab | جديد | الورقة المعمليّة الرئيسية | patient_id, visit_id, not_confirm, clinician_id, referred_dr_id, media, oil, incubator, injection_embrologist, icsi_by, embryologist_id, freeze_embryologist_id, cancelled, cancelled_user, date | أب لمعظم جداول المعمل |
embryoscoring | جديد | تقييم الجنين يوم2→يوم6 | embryoslab_id, itr, stage/grade, media1..6, oil1..6, incubator1..6, embrologist1..6, deleted | N→1 embryoslab, → stage,grade |
embryoselection | جديد | انتقاء/اختيار الجنين | embryoslab_id, deleted | → embryo_result, embryo_emb |
embryotransfer | جديد | إرجاع الأجنة ET (من الورقة) | embryoslab_id, clinician_id, embryologist_id, embryologist_id_tb, et_day, catheter/difficulty/blood/jet | 1→1 embryoslab |
embryotransferovum | جديد | إرجاع مستقل (OPU flow) | patientid, date, day, consultant, nurse, embryologist, no_of_embryos, quality, notes | → patients |
ovumpickup | جديد | سحب البويضات OPU | patientid, date, consultant, anaesthetist, nurse, operation, postoperative, complications | → patients |
followup_operation | جديد | متابعة عملية الـ OPU | patient_id, nurse_id, anaesthetist_id, clinician_id, embryologist_id, ut_cx, avf_rvf, easy_difficult, postoperative, complications, date | → patients, awusers |
embryofreezingreport | جديد | تقرير تجميد الأجنة | patient_id, date, embryologist, ref_by_prof_dr, no_of_straws, no_of_embryos, day_of_freezing, kit, device, lot_no, location, completed, deleted | 1→N embryo, embryothawing |
embryo | جديد | قشّة جنين مُجمَّدة | embryofreezing_id, stage1..6, grade1..6 | N→1 embryofreezingreport |
embryothawing | جديد | إذابة الأجنة | embryofreezing_id, no_of_embryos, thawing_date, recovered, lost, e_t_date, embryos, grades, embryol_oigist, clinician, cathetr | N→1 embryofreezingreport |
spermfreezingreport | جديد | تقرير تجميد الحيوانات المنوية | patient_id, date, sperm_source, count, motility, a_plus_b, morphology_abn, samples_no, freezing_media_id, freezing_protocol_id, purpose_of_freezing, color_of_pen, embryologist1, embryologist2, location | → freezingmedia, freezingprotocol |
embryologyreport | جديد | تحليل السائل المنوي المعملي | patient_id, date, sperm_source, count, motility, morphology | → patients |
freezingmedia / freezingprotocol | جديد | قوائم وسط/بروتوكول التجميد | media / protocol | مرجع لـ spermfreezingreport |
stage / grade | جديد | مراحل ودرجات الجنين | stage / grade, deleted | مراجع للتقييم والتجميد |
growthmedia, growthoil, growthincubator, growthco2 | جديد | قوائم بيئة الزراعة | name, deleted | مراجع لـ embryoslab/embryoscoring |
oocytequality, oocytezona, oocytecytoplasm, oocytepvs, oocyteother | جديد | قوائم تقييم البويضة | name, deleted | مراجع لـ embryoslab |
embryocathetertype, embryodifficulty, embryoblood, embryojetplace, embryolah, embryotype | جديد | قوائم الإرجاع ET | name | مراجع لـ embryotransfer |
embryo_device, embryo_result, embryo_emb, embryo_lot_select, embryo_catheter_select, embryo_tank, embryo_kit_type | جديد | قوائم مساعدة للمعمل | name, deleted | مراجع متفرّقة |
embryologist | جديد | أخصائيو أجنة خارج المستخدمين | name, deleted | يُدمج مع awusers role 11 |
sperum_source, semen_process | جديد | قوائم مصدر/معالجة السائل المنوي | name, deleted | مراجع لـ embryoslab |
kit, device, cathetr | جديد | مستهلكات التجميد/الإرجاع | kit / device / cathetr, deleted | مراجع للتقارير |
detections | جديد | تصنيف زيارات الأجنة (for_embryo) | for_embryo, del | يربط embryoslab.visit_id |
ivfsheet, semen, icsisemen | معروف | أوراق IVF السريرية الأصلية المسطّحة | — | بديلة/سابقة لمنظومة المعمل الجديدة |
ملاحظات على جودة البيانات والأمان (Data Quality & Security)
- حقن SQL غالبية الاستعلامات تدمج المتغيّرات مباشرة في النص (مثل
... where id = ' . $idو"select * from awusers where user_id=$ref_dr_id->refer_doctor") دون معاملات مُهيّأة — خطر حقن عالٍ يجب معالجته عند أي ترحيل. - قيم مفصولة بفواصل الوسط/الزيت/الحاضنة/الحاقن تُخزَّن كنص مفصول بفواصل داخل عمود واحد (CSV-in-column) بدل جداول ربط، ما يعقّد الاستعلام والتقارير.
- سعة الخزّان حلقة الإنشاء تُولّد فعليًا 1000–3000 خلية لكل خزّان بينما تعرض الواجهة 20/100/300؛ تباين بين السعة المنطقية والمعروضة يحتاج توحيدًا.
- الحذف منطقي (
deleted=1/del=1) في معظم الجداول، وهو مناسب للحفاظ على سلسلة العُهدة في بيئة منظّمة.
التأثير على خطة الـ ERP/HIS (ERP/HIS Impact)
- إضافة وحدة مستقلّة «معمل الأجنة (Embryology & IVF Lab)» إلى مخطط الترحيل لم تكن ضمن الـ312 جدولًا الأصلية؛ هي توسعة جوهرية لإصدار المركز.
- نمذجة مخزون الكرايو ككيان أول-درجة:
Tank → Canister/Cane → Positionمع جدول حركات عُهدة (tankcellhistory) كنواة لمتطلب Chain of Custody المطلوب اعتماديًا (CAP/JCI/ESHRE). - توحيد نموذجي التخزين المتوازيين (
tankcellsالشبكي مقابلembryoslab_tank_cellsاللوني) في نموذج واحد قبل الترحيل لتجنّب ازدواجية مصدر الحقيقة لموقع العيّنة. - اعتماد الشهادة المزدوجة (Double Witnessing) كحقل إلزامي في كل عملية حرجة (تجميد/إذابة/إرجاع/نقل خزّان) بدل الحقلين الاختياريين
embryologist1/2الحاليين. - تطبيع قوائم البحث (~30 جدول قائمة:
growth*, oocyte*, embryo*, freezing*, stage, grade, kit, device, cathetr) في جدول مرجعي موحّدlookup(type,value)لتقليل تضخّم المخطط. - ربط الورقة المعمليّة
embryoslab.visit_idبدورة العلاج/الزيارة في الـ HIS لإغلاق حلقة المسار السريري ← المعملي ← التقارير (ivf_reports.php). - معالجة مخاطر حقن SQL وتفكيك حقول CSV-in-column كشرط مسبق للترحيل الآمن إلى قاعدة الـ ERP الجديدة.
- الربط مع المخزون/المشتريات لمستهلكات المعمل (
kit, device, cathetr, lot_no) لتتبّع الأرصدة والصلاحية ضمن وحدة المخزون في الـ ERP.
ملحق: جناح المناظير الموسع (MED: Extended Endoscopy Suite)
يوثّق هذا الملحق وحدة المناظير في نسخة المركز/المستشفى المكتشفة على med.greennature.com.sa. هذه النسخة توسّع نطاق نظام النساء والولادة الأصلي ليشمل مناظير الجهاز الهضمي (تنظير المعدة endoscopy وتنظير القولون colonoscopy) إلى جانب مناظير النساء (تنظير الرحم hystroscopic وتنظير البطن laparoscopic). الأهم أنها تعتمد محرّك «قوالب تقارير» (Template Engine) جديد كلياً يحل محل أسلوب جداول البحث المجزّأة (lapar* / copy*) المستخدم في النسخة الأصلية.
نظرة عامة على المكوّنات (Controllers)
تتكوّن الوحدة من سبعة Controllers تنقسم إلى ثلاثة أنماط معمارية مختلفة، جميعها يبني على إطار awframework ومكتبة RedBeanPHP (نمط R::dispense / R::findAll / R::getRow) مع عرض عبر Smarty.
- نمط «القالب الواحد + سجلّ المريض» (GI Endoscopy):
endoscopy.php+endoscopy_template.phpوcolonoscopy.php+colonoscopy_template.php. لكل نوع جدول قالب يحوي صفاً واحداً افتراضياً (id = 1) يُملأ مسبقاً في نموذج الإدخال، وجدول سجلّات مرتبط بالمريض، وجدول صور. - نمط «بنك القوالب المتعددة» (Gyne scopes – legacy templates):
laparoscopic.phpوhystroscopic.phpيديران مكتبة قوالب مُسمّاة (template_name) قابلة للاختيار، تُحقَن في الفورم عبر AJAX (ac=render→ JSON). - نمط «التقرير الموحّد للمريض» (Patient Oscopic Report):
oscopic.php(الأكبر، 691 سطراً) يربط قوالب التنظير ببيانات المريض الفعلية، ويضيف قوائم بحث ديناميكية قابلة للتحرير (Operations / Examinations / Specimens) وتقرير عمليات موحّد.
محرّك القوالب: كيف يختلف عن النسخة الأصلية
في النسخة الأصلية (obgy ذات الـ312 جدولاً) كان كل حقل تشريحي في تقرير المنظار مرتبطاً بجدول بحث مستقل صغير (مثل laparpelvis, laparro, laparrt, copycavity, copycx, copyrostium ... عشرات الجداول)؛ أي «جدول لكل قائمة منسدلة». نسخة المركز تستبدل هذا النهج بثلاث آليات قوالب أنظف:
- قالب افتراضي واحد (GI): الجدول
endoscopy_template/colonoscopy_templateيحوي صفاً واحداً (id = 1) فيه نص افتراضي لكل قسم تشريحي. عند فتح نموذج الإضافة يُمرَّرtemplate_dataإلى Smarty فتُملأ الحقول مسبقاً بالقيمة الطبيعية، ويعدّلها الطبيب عند الحاجة. القالب يدير أيضاً ترويسة/تذييل الطباعة (header_print,footer_printعبرuploadupdate). - بنك قوالب مُسمّاة (Gyne):
laparoscopic/hystroscopicيخزّنان عدة صفوف، كل صف قالب كامل باسمtemplate_name. واجهةoscopicتعرضها في قائمةselect؛ وعند تغيير الاختيار يستدعيoscopic.jsالإجراءac=renderالذي ينفّذR::getRow('select * from laparoscopic where id = ?')ويعيد JSON، فيُحقَن في حقول الفورم عبر jQuery.val(). - قوائم بحث ديناميكية بدلاً من جداول ثابتة: في
oscopic.phpتوجد دوال عامة (addToTable,editModal,updateModal,deleteModelItem) تستقبل اسم الجدول كمعامل (table_nameمن POST) وتدير صفوفoscopic_operations/oscopic_required_examinations/oscopic_specimensمع حذف منطقي (deleted = 1). هذا يحوّل «عشرات جداول البحث الثابتة» إلى جداول قليلة قابلة للإدارة من الواجهة.
ملاحظة أمنية دوال addToTable / updateModal / deleteModelItem تمرّر اسم الجدول واسم العمود مباشرة من POST إلى RedBean دون قائمة بيضاء — يجب تقييدها عند الترحيل (خطر تعديل جداول غير مقصودة). خطأ مرصود في oscopic.js (السطور 19-20) يُملأ left_ovary وleft_ovary_procedures من response.right_ovary بدل القيم اليسرى (خطأ نسخ-لصق).
مسار العمل الكامل (تنظير المعدة كمثال) (end-to-end flow)
- إعداد القالب: المدير يفتح
endoscopy_template.php?ac=index→ يحرّر النصوص الافتراضية وترويسة/تذييل الطباعة →update()يخزّن فيendoscopy_template(id=1). - إنشاء تقرير:
endoscopy.php?ac=index&patientid=يحمّل بيانات المريض + يحسب العمر منdateofbirth+ يجلب الطبيب المُحوِّل منawusers+ يمرّرtemplate_dataفتُملأ الحقول التشريحية مسبقاً. - الحفظ:
ac=add→R::dispense('endoscopy')يخزّن كل الأقسام (esophagus, stomach, pylorus, duodenum ...) معpatient_idوexam_date. - الصور:
ac=uploadImageثمac=uploadيرفع إلىupload/endoscopy/ويخزّن فيendoscopy_images(مرتبط بـendoscopy_id+patient_id). - العرض/التعديل/الحذف:
show / edit / update / delعلى الجدولendoscopy. - الطباعة:
ac=printReportيدمج سجلّ المريض + بيانات القالب (ترويسة/تذييل) + الصور فيprint.html.tpl.
جدول الكيانات المستنتجة (inferred from RedBeanPHP & raw SQL)
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
endoscopy | جديد | تقرير تنظير معدة لمريض | patient_id, exam_date, indication, anesthesia, procedure, esophagus, cardio_esophageal_junction, stomach, pylorus, duodenum, conclusion, signature, created_at, updated_at | ← patients (patient_id) |
endoscopy_template | جديد | قالب افتراضي واحد (id=1) لتنظير المعدة + ترويسة/تذييل طباعة | نفس الأقسام التشريحية + header_print, footer_print, updated_at | مصدر القيم المسبقة لـ endoscopy |
endoscopy_images | جديد | صور المنظار | image, patient_id, endoscopy_id, create_date | ← endoscopy, patients |
colonoscopy | جديد | تقرير تنظير قولون لمريض | patient_id, exam_date, indication, consent, preparation, instrument, anesthesia, procedure, preparation_2, withdrawal_time, dre, findings, plan, signature, created_at, updated_at | ← patients |
colonoscopy_template | جديد | قالب افتراضي واحد (id=1) لتنظير القولون | نفس حقول colonoscopy (بلا patient) + header_print, footer_print | مصدر القيم المسبقة لـ colonoscopy |
colonoscopy_images | جديد | صور تنظير القولون | image, patient_id, colonoscopy_id, create_date | ← colonoscopy, patients |
laparoscopic | جديد | بنك قوالب مُسمّاة لتنظير البطن (نساء) | template_name, entry(_procedures), uterus(_procedures), right_tube(_procedures), left_tube(_procedures), right_ovary(_procedures), left_ovary(_procedures), uterosacrals(_procedures), peritoneum(_procedures), recommendations | قالب يُحقَن في patient_laparoscopic |
hystroscopic | جديد | بنك قوالب مُسمّاة لتنظير الرحم (نساء) | template_name, entry(_procedures), external_os, cervical_canal, internal_os, uterine_cavity, endometrium, right_ostium, left_ostium, other (+ *_procedures), recommendations | قالب يُحقَن في patient_hystroscopic |
patient_laparoscopic | جديد | تقرير تنظير بطن مطبَّق على مريض فعلي | حقول laparoscopic + patient_id, created_at, template_id, diagnosis (CSV), diagnosis_text | ← patients, laparoscopic (template_id), diagnosis |
patient_hystroscopic | جديد | تقرير تنظير رحم مطبَّق على مريض فعلي | حقول hystroscopic + patient_id, created_at, template_id, diagnosis (CSV), diagnosis_text | ← patients, hystroscopic, diagnosis |
oscopic_report | جديد | تقرير عمليات/منظار موحّد للمريض (يدعم الزوج أيضاً) | patient_id, created_at, diagnosis (CSV), operation_id, operation_text, required_examination_id, required_examination_text, specimen_id, specimen_text, diagnosis_text, husband | ← patients, diagnosis, جداول البحث الثلاثة |
oscopic_operations | جديد | قائمة بحث ديناميكية للعمليات | name, deleted | تُدار عبر addToTable/editModal |
oscopic_required_examinations | جديد | قائمة بحث ديناميكية للفحوص المطلوبة | name, deleted | تُدار عبر الدوال العامة |
oscopic_specimens | جديد | قائمة بحث ديناميكية للعيّنات | name, deleted | تُدار عبر الدوال العامة |
diagnosis | معروف | قائمة التشخيصات المشتركة (تُفلتر بـ conditions = 0) | name, conditions | مشترك مع باقي النظام |
patients / awusers | معروف | المرضى والمستخدمون/الأطباء | dateofbirth, refer_doctor, doctor1, h_doctor1, husbanddateofbirth / user_id | مرجع لكل التقارير |
مقارنة: النهج القديم مقابل نهج المركز
| المحور | النسخة الأصلية (obgy) | نسخة المركز (med) |
|---|---|---|
| تخزين القوائم التشريحية | جدول لكل حقل: laparpelvis, laparro, laparrt, copycavity, copycx, copyrostium ... (عشرات الجداول) | صف قالب واحد كامل (template_*) أو بنك قوالب مُسمّاة + 3 جداول بحث ديناميكية |
| التخصص | نساء وولادة فقط (laparoscopy, hysteroscopy) | نساء + جهاز هضمي (معدة endoscopy، قولون colonoscopy) |
| تعبئة الفورم | قوائم منسدلة من جداول بحث ثابتة | تعبئة مسبقة من القالب (Smarty) أو حقن AJAX (ac=render → JSON) |
| الطباعة | قوالب طباعة ثابتة | ترويسة/تذييل قابلة للرفع لكل نوع منظار (header_print/footer_print) |
التأثير على خطة الـ ERP/HIS
- إضافة 14 جدولاً جديداً غير موجود في الـ312 جدولاً الأصلية إلى مخطط الترحيل، موزّعة على 3 أنماط قوالب.
- توسيع نطاق الـ HIS من نظام نساء/ولادة بحت إلى جناح مناظير متعدد التخصصات يشمل مناظير الجهاز الهضمي — يستلزم وحدة Endoscopy Suite مستقلة في الـ ERP مع ربطها بسجلّ المريض الموحّد (EMR).
- اعتماد محرّك قوالب موحّد في الـ ERP الجديد بدل عشرات جداول البحث المجزّأة في النسخة الأصلية — يقلّل الجداول ويسهّل الصيانة (استنتاج).
- توحيد إدارة القوائم الديناميكية (Operations/Examinations/Specimens) عبر آلية CRUD عامة مع حذف منطقي (
deleted) بدل جداول ثابتة. - أولوية أمنية: دوال
addToTable/updateModal/deleteModelItemتمرّر اسم الجدول/العمود من المستخدم مباشرة إلى ORM؛ يجب فرض قائمة بيضاء عند إعادة البناء. - تخزين
diagnosisكسلسلة مفصولة بفواصل (CSV) داخل التقارير — يُنصح بتطبيعه إلى جدول ربط (many-to-many) في الـ ERP الجديد. - توحيد أرشيف الصور (
endoscopy_images,colonoscopy_images) ضمن خدمة PACS/مرفقات مركزية بدل مجلدات رفع منفصلة لكل وحدة. - إصلاح خطأ تعبئة المبيض الأيسر في
oscopic.jsعند الترحيل لتجنّب انتقال أخطاء سريرية إلى النظام الجديد.
ملحق: عيادة الذكورة وقسم الأشعة (MED: Andrology Clinic & Radiology Dept.)
يوثّق هذا الملحق ما رصدناه في النسخة الأحدث المنشورة على med.greennature.com.sa (مجلد /med) والمهيّأة كمركز/مستشفى، وهي مكوّنات غير موجودة في النسخة الأصلية ذات الـ312 جدولًا. تُقدّم هذه النسخة عيادة ذكورة مستقلة بالكامل لها زياراتها وتاريخها المرضي وفحصها السريري الخاص (بخلاف النسخة الأصلية التي اقتصرت على تحاليل السائل المنوي والهرمونات داخل شيت العقم فقط)، إضافة إلى قسم أشعة مركزي يعمل بمسار طلب ← تنفيذ ← تقرير ورفع صور. كل أسماء الجداول المذكورة هنا تمّت مطابقتها مع قائمة الجداول الأصلية وتأكّد أنها جديدة ما لم يُذكر خلاف ذلك. كل ما لم نتمكّن من تأكيده من الكود مباشرة موسوم بـ«(استنتاج)».
أولًا: عيادة الذكورة المستقلة (Dedicated Andrology Clinic)
في النسخة الأصلية كان الجانب الذكوري مجرد جداول لتحاليل السائل المنوي (semen, semen2, icsisemen, ssemen) والهرمونات داخل شيت العقم. أما هنا فقد أصبحت عيادة ذكورة كاملة بثلاث شاشات سريرية مرتبطة بنفس المريض (patientid) عبر ثلاثة كنترولر: and_visits, and_history, and_examination، تُكتب جميعها عبر RedBeanPHP في جداول جديدة بادئتها and*.
- زيارة الذكورة (
and_visits← جدولandvisits): تسجّل لكل زيارة الشكوى والتشخيص بنظام قوائم متعددة (complaintid/diagnosisidكقيم CSV من جدوليandcomplaintوanddiagnosisالقابلين للإضافة أثناء العمل عبر AJAXadddiagnosis). كما تدمج الشاشة من داخلها: طلب أشعة (andvisitsrays)، طلب تحاليل (andvisitsinvestigation)، روشتة دوائية (andvisitsdrugs)، سونار ذكوري مع بصيلات (andvisitsus+andvisitsficils)، تحليل سائل منوي (andvisitssemen)، وفحص جيني (andvisitsgenetictesting). - التاريخ المرضي للذكورة (
and_history): يضم خمسة جداول فرعية مستقلة لكل مريض: تاريخ عام (andhistory: مدة العقمdurationid، نوع الخصوبةfertiletype، التدخينsmoking/smokinglevel، التهاباتinflammation، رضوضtrauma، الزواجmarriage، عدد حالات الإجهاضabortionnoالمحسوبة آليًا منphobstetric)، المشاكل الطبية (andmedicalproblems←medicaldisease)، الانتصاب (anderection←erectiondisease)، القذف (andejaculation←ejaculationdisease)، ومنع الحمل (andcontraception←andcontratype). كل قائمة مرجعية قابلة للإضافة من الشاشة عبر دوال AJAX مخصّصة (addduration,adddmdisease,addderectiondisease,addejaculationdisease,addcontraception). - الفحص السريري للذكورة (
and_examination←andexamination): فحص ثنائي الجانب (يمين/يسار) للأعضاء: الخصيتانtestesl/testesr، البربخepidl/epidr، الحبل المنويcordl/cordr، الأسهرvasl/vasr، إضافة إلى ملاحظاتnotes. - طلب الأشعة/التحاليل لكل من الزوج أو الزوجة: كل جداول الطلب تحمل العمود
forhusband(1=الزوج، 0=الزوجة)، فعيادة الذكورة قادرة على إصدار طلبات لطرفي العلاقة معًا، وتُطبع نتائجها عبر قوالبgyna/printinv.htmlوgyna/print.htmlالمشتركة. - السونار الذكوري بالبصيلات: نفس بنية سونار النساء أُعيد استخدامها هنا (نوع
uscompleteAnd/ussimpleAnd) مع جدول بصيلاتandvisitsficilsيخزّن لكل بصيلة الاسم/الطول/العرض/الحجم وجانبها (type0=يسار/1=يمين) مرتبطة بـandvisitsusid. - الفحص الجيني (
andvisitsgenetictesting): يخزّن نتيجة الخريطة الكروموسوميةchromosome(1=طبيعي، 2=غير طبيعي) وحذف كروموسوم Y الدقيقazf(1=طبيعي، 2=حذف Deletion)، وتُترجم القيم عند الطباعة فيprintselected.
مسار عمل زيارة الذكورة (نهاية لنهاية)
- اختيار المريض ثم فتح
and_visits.php?patientid=…← تحميل كل التشخيصات/الشكاوى والأشعة والتحاليل المرجعية. - إضافة صف زيارة جديد (
newrow→R::dispense('andvisits')) ثم تحرير الحقول inline عبرupdate(تحديث عمود واحد لكل نداء). - طلب أشعة (
addray→ صفوف فيandvisitsrays) و/أو تحاليل (addinvestigation→andvisitsinvestigationمع دعم باقات الفحوصاتinvoffer/invofferdetails) و/أو روشتة (andvisitsdrugs). - إدخال سونار/سائل منوي/فحص جيني كصفوف منفصلة، ثم الطباعة لكل من الزوج/الزوجة حسب
forhusband. - حذف منطقي لأي سجل عبر
del(تعيينdeleted = 1).
ثانيًا: قسم الأشعة المركزي (Radiology Department Workflow)
كنترولر raysdept يمثّل قسم أشعة قائمًا بذاته (for_department = 5) يعمل بمنطق طابور عمل المستشفى عبر جدول visits المشترك. الطلب يُنشأ كزيارة موجّهة للقسم، ثم تُنشأ صفوف نتائج في الجدول الجديد raysresults، يُنفّذها فنّي القسم بإدخال النتيجة ورفع الصور، ثم تُؤرشَف.
- الطلب (Order):
newvisit←savenewvisitيُنشئ صفvisitsبـfor_department = 5ثم يستدعيsendToDeptالذي يولّد صفًا فيraysresultsلكل أشعة مختارة (rayid,visitid,patientid,doctorid = 0,status = 0,forhusband). يدعم أيضًا «الطلب الداخلي» (raytype = 1) الذي يربط نتيجة الأشعة بسجل في جدول داخلي آخر عبرinternaltable/internalrequestid. - قائمة العمل (Worklist):
indexيجلب طلبات اليوم غير المنجَزة (status = 0) عبر JOIN بينraysresultsوvisitsوpatientsوpatients_childs، ويميّز المستفيد: زوج/زوجة/طفل (for_husband= 1/0/2). - التنفيذ والتقرير (Perform & Report):
showdetailsيعرض صفوف الأشعة للزيارة، وupdateيكتب نص التقرير فيrayresultويضبط تاريخ النتيجة وdoctorid؛ وإذا كان طلبًا داخليًا يُحدِّث الجدول الداخلي المرتبط أيضًا. - الصور:
upload(صورة واحدة فيraysresults.rayimg) وuploadMulti(عدة صور في الجدول الجديدraysresults_imgالمرتبط بـraysresults_id)، مع حذف فعلي للملفات منupload/rayimg. - الإنهاء والأرشفة:
finishRequestيضبطstatus = 1لكل صفوف الزيارة، وarchiveيعرض المؤرشف، وprintresultsيطبع التقرير النهائي مع تحديد الطبيب المُحوِّل (refer_doctorأوfor_doctorمن آخر زيارة).
- إدارة كتالوج الأشعة (
addrays): يدير فئات الأشعةrayscats(معdisplayorderالذي يُستعمل لتجميع العرض في خمس مجموعات) وعناصر الأشعةrays(الاسم، السعرprice، المدى الطبيعيrange، علم المفضلةfavorite). جداولrays/rayscats/raysresults/raysresults_imgكلها جديدة (لا مقابل لها في النسخة الأصلية). - التماثل مع قسم التحاليل:
sendToDeptيعالج القسم 12 بنفس النمط لكن في جدولinvestigationresults(نظيرraysresultsللتحاليل) — ما يؤكد أن المعمارية الأحدث تعتمد نمط «قسم خدمي» موحّد يقوم علىvisits.for_department.
ثالثًا: ملاحظة حول radiation.php
رغم اسمه، فإن كنترولر radiation.php ليس قسم علاج إشعاعي بل اسمه الداخلي instruction ويعمل على جدول instruction (معروف من النسخة الأصلية) لإدارة تعليمات المرضى وخطابات التحويل بين المستشفيات. يستخدم جداول operationinstructions (جديد) وhospitalnames (معروف) ويولّد خطاب تحويل يجمع التاريخ الولادي/المرضي/الجراحي للمريضة. أُدرج هنا للتوضيح أنه لا علاقة له بقسم الأشعة التشخيصية أعلاه.
جدول الكيانات (Entities)
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
andvisits | جديد | زيارة عيادة ذكورة (شكوى/تشخيص متعدد) | patientid, doctorid, date, complaint, complaintid (CSV), diagnosisid (CSV), diagnosistxt, deleted | patients عبر patientid، awusers عبر doctorid، anddiagnosis/andcomplaint عبر CSV |
andhistory | جديد | التاريخ العام لمريض الذكورة | patientid, doctorid, durationid, fertile, fertiletype, marriage, smoking, smokinglevel, inflammation, trauma, stopped, abortionno, notes, deleted | patients، infertileduration عبر durationid |
andexamination | جديد | الفحص السريري الثنائي الجانب | patientid, doctorid, date, testesl/testesr, epidl/epidr, cordl/cordr, vasl/vasr, notes, deleted | patients، awusers |
andmedicalproblems | جديد | الأمراض الطبية المصاحبة | patientid, diseaseid, date, deleted | medicaldisease (معروف) عبر diseaseid |
anderection | جديد | مشاكل الانتصاب | patientid, diseaseid, date, deleted | erectiondisease عبر diseaseid |
andejaculation | جديد | مشاكل القذف | patientid, diseaseid, date, deleted | ejaculationdisease عبر diseaseid |
andcontraception | جديد | وسائل منع الحمل المستخدمة | patientid, typeid, date, deleted | andcontratype عبر typeid |
andcontratype | جديد | قائمة مرجعية لأنواع منع الحمل | name, deleted | تُقرأ من andcontraception.typeid |
infertileduration | جديد | قائمة مرجعية لمدد العقم | name, deleted | تُقرأ من andhistory.durationid |
erectiondisease | جديد | قائمة مرجعية لأمراض الانتصاب | name, deleted | تُقرأ من anderection.diseaseid |
ejaculationdisease | جديد | قائمة مرجعية لأمراض القذف | name, deleted | تُقرأ من andejaculation.diseaseid |
anddiagnosis | جديد | قائمة مرجعية لتشخيصات الذكورة | name, deleted | تُقرأ من andvisits.diagnosisid (CSV) |
andcomplaint | جديد | قائمة مرجعية لشكاوى الذكورة | name, deleted | تُقرأ من andvisits.complaintid (CSV) |
andvisitssemen | جديد | تحليل سائل منوي مرتبط بزيارة الذكورة | patientid, doctorid, date, conc, nf (حركة), ph, viscosity, aggl, vol, pus, deleted (استنتاج للأسماء من العرض) | patients، awusers |
andvisitsgenetictesting | جديد | فحص جيني (كروموسومي + AZF) | patientid, doctorid, date, chromosome (1/2), azf (1/2), deleted | patients، awusers |
andvisitsus | جديد | سونار ذكوري | patientid, doctorid, date, lfolliclesno/rfolliclesno, حقول الرحم/المبيض المُعاد استخدامها, deleted | andvisitsficils عبر andvisitsusid |
andvisitsficils | جديد | بصيلات السونار الذكوري | andvisitsusid, name, length, width, volume, type (0/1), sysdate | andvisitsus عبر andvisitsusid |
andvisitsdrugs | جديد | روشتة دوائية لزيارة الذكورة | patientid, doctorid, date, drugid, forhusband, deleted | drugs عبر drugid |
andvisitsrays | جديد | طلب أشعة من زيارة الذكورة | patientid, doctorid, date, rayid, forhusband, deleted | rays عبر rayid |
andvisitsinvestigation | جديد | طلب تحاليل من زيارة الذكورة | patientid, doctorid, date, investid, offer_id, forhusband, deleted | invests، invoffer عبر offer_id |
rays | جديد | كتالوج عناصر الأشعة | name, rayscatid, price, range, favorite, deleted | rayscats عبر rayscatid |
rayscats | جديد | فئات الأشعة | name, displayorder, deleted | أب لـ rays |
raysresults | جديد | سجل تنفيذ/تقرير طلب الأشعة (قلب طابور القسم) | visitid, patientid, rayid, raytype, internaltable, internalrequestid, rayresult, rayimg, doctorid, status (0/1), forhusband, date, deleted | visits عبر visitid، rays عبر rayid، raysresults_img |
raysresults_img | جديد | صور متعددة لنتيجة الأشعة | raysresults_id, rayimg, deleted | raysresults عبر raysresults_id |
investigationresults | جديد | نظير raysresults لقسم التحاليل (department 12) | visitid, patientid, investid, invtype, internaltable, internalrequestid, doctorid, forhusband, date, deleted | visits، invests |
patients_childs | جديد | أبناء المريضة كمستفيد ثالث للطلب | child_name, gender (استنتاج) | تُربط بـvisits.child |
operationinstructions | جديد | تعليمات العمليات لخطاب التحويل | insttext, deleted | تُستخدم في radiation.php (instruction) |
invoffer / invofferdetails | جديد | باقات الفحوصات وتفاصيلها | active, del / invoffer_id, inv_id, price, del | invests عبر inv_id |
medicaldisease, instruction, hospitalnames, visits, invests, investcats, detections | معروف | جداول أصلية أُعيد استخدامها (المرض المرجعي، التعليمات، المستشفيات، الزيارات، التحاليل، الكشوف) | — | موجودة في النسخة الأصلية ذات الـ312 جدولًا |
التأثير على خطة الـ ERP/HIS
- توسعة مخطط الهجرة: يجب إضافة دومين «عيادة الذكورة» ككيان مستقل في المخطط، لا كملحق لشيت العقم كما في التقرير الأصلي. هذا يضيف 17+ جدولًا جديدًا (
and*) إلى نطاق الهجرة لم تُحصَ في تحليل الـ312 جدولًا. - نموذج «القسم الخدمي» الموحّد: ظهور
raysresultsوinvestigationresultsالعاملين عبرvisits.for_departmentيؤكد أن النسخة الأحدث تتبنّى معمارية أقسام مستشفى (Order→Perform→Report). ينبغي تصميم وحدة Orders/Results عامة في الـHIS بدل ربط النتائج بشيتات محددة. - دعم ثلاثة مستفيدين للطلب الواحد: أعمدة
forhusband+visits.for_husband(زوج/زوجة/طفل عبرpatients_childs) تستلزم نموذج «المريض الفعلي للطلب» (Subject) في الـERP يفصل بين حساب الملف ومستفيد الخدمة. - الطلب الداخلي (Internal Request): آلية
raytype/internaltable/internalrequestidتمثّل ربطًا متعدد الأشكال (polymorphic) بين النتيجة وأي جدول مصدر؛ يجب نمذجتها كعلاقة Order↔SourceRef مرنة في تصميم قاعدة البيانات الجديدة. - كتالوج خدمات بأسعار:
rays/rayscatsوinvoffer/invofferdetailsتحملان أسعارًا وباقات، ما يربط الأشعة/التحاليل بوحدة الفوترة في الـERP مباشرة. - قوائم مرجعية قابلة للنمو من الواجهة: كثرة جداول الـlookup القابلة للإضافة الفورية (AJAX) تستوجب وحدة «إدارة القوائم المرجعية» مركزية في الـHIS لمنع تشظّي البيانات.
- توضيح تسمية مضلّلة:
radiation.php= تعليمات/تحويلات وليس علاج إشعاعي؛ يجب عدم إدراجه ضمن نطاق الأشعة في خطة الهجرة. - إدارة المرفقات:
raysresults_imgورفع صور متعددة إلىupload/rayimgيستلزم تخطيط وحدة تخزين/PACS مصغّرة (أو تكامل DICOM) ضمن الـHIS المستهدف (استنتاج).
ملحق: الفروع والمناطق ومزامنة الـ ERP (MED: Branches, Regions & ERP Sync)
هذا الملحق يوثّق النسخة الأحدث (نمط "مركز/مستشفى") المكتشفة في موقع med.greennature.com.sa. النسخة الأصلية المنشورة (312 جدولاً) كانت عيادة نسائية مفردة؛ أمّا هذه النسخة فتُحوّل النظام إلى منظومة متعدّدة الفروع والمناطق، مع طبقة مزامنة قواعد بيانات (syncstructure)، وجسر ربط مع نظام Moon ERP (erp_common عبر localhost/erp/controllers/api_web.php)، وواجهة خارجية (api_web) تخدم أجهزة المعمل والجهات المتعاقدة (Organizations). كل ما يلي مُستخرَج من الكود قراءةً فقط (RedBeanPHP و SQL الخام) دون أي استعلام لقاعدة البيانات الحيّة.
1. معمارية الفروع والمناطق (Multi-Branch / Multi-Region Core)
التفعيل يتم عبر ثلاثة مفاتيح في programesetting: branches (موجود أصلاً) وregions وorganizations (كلاهما عمودان جديدان أضيفا في programesetting.php). عند تفعيل الفروع تُحدَّد صلاحية المستخدم على الفروع عبر العمود الجديد awusers.related_branches (قائمة معرّفات مفصولة بفواصل).
- المناطق هرمية:
regions←sub_regions(عبرsub_regions.region_id).regions.phpيبني الشجرة فيshow()ويستعمل تحريراً مباشراً عبرaddRow/update/delبأسلوبR::xdispense($tableName)الديناميكي (الجدول يُمرَّر من الواجهة — استنتاج). - منطق الصلاحية على الفروع مُركَّز في
branch_common.phpبثلاث دوال:branchInfos()(شاشات التقارير)،branchInfosVisit()(شاشات الزيارات/الإدخال)،showBranchCol()(إظهار عمود الفرع في الجداول). القاعدة المستنتجة:related_branches = 0/فارغ⇐ كل الفروع؛ قيمة مفردة ⇐ قفل على فرع واحد دون قائمة اختيار؛ عدّة قيم ⇐ إظهار قائمة اختيار مُقيَّدة بـid IN (...). - فلترة التقارير حسب الفرع: دوال
branchSql()وbillBranchSql()(فيfinancialreport.phpوfinanciallab.phpوcashtransferdectorreport.php) تُلحقand visits.branch_id = ?أوand bill_paying.branch_id = ?. القيمة-1تعني "كل الفروع". - إدارة الفروع (Beauty Branches):
beauty_branches.phpيوفّر CRUD كامل علىbranchesمع حقن اختياري لموقع خارجي (sendToSite()إلىroyal-fc.net/appv/visit_details/branches— معطّل حالياً بالتعليق).
2. الجهات المتعاقدة (Organizations)
كيان جديد كلياً يُمثّل الجهات/الشركات المتعاقدة (تأمين/مؤسسات). يُربط بالزيارة عبر العمود الجديد visits.organization_id، ويُحفظ رقم المريض الخاص بكل جهة في جدول الربط organizations_patient_no. وضع التفعيل programesetting.organizations له ثلاث درجات مستنتجة (1/2/3) تتحكّم بإلزامية ربط الجهة وكشف الديون.
- تسجيل دخول الجهة خارجياً عبر
api_web.php?ac=orglogin(تحقّقpassword_verifyضدorganizations.user_password_hash). - استعلام زيارات/نتائج المريض للجهة عبر
api_web.php?ac=orgpatientinfo(يربطvisits.organization_id+organizations_patient_noويحسب عدد النتائج المُسلَّمة).
3. جسر مزامنة بنية القاعدة (syncstructure)
أداة DBA لمواءمة بنية قاعدة قديمة مع قاعدة جديدة مع الحفاظ على البيانات (تشغيل وحيد، ليست مزامنة مستمرة). تضيف اتصالين R::addDatabase("old"/"new") وتمرّ على جداول القاعدة الجديدة: إن لم يوجد الجدول تُنشئه عبر SHOW CREATE TABLE، وإن اختلفت الأعمدة تُنشئ جدولاً مؤقتاً _temp وتنسخ البيانات عمودياً ثم تُعيد التسمية.
- قراءة جداول القاعدة الجديدة من
information_schema.tables. checkTableExist()⟶ موجود؟compareTables()يكشف فروق الأعمدة عبرinformation_schema.columns.- عند الفرق:
copyTable()ينشئ{table}_temp LIKE new.{table}، يدرج الصفوف القديمة بالأعمدة المشتركة فقط، ثمDROP+RENAME. - غير موجود:
createTable()ينفّذ DDL الجديد على القاعدة القديمة.
تحذير تشغيلي الكود يحوي شرط if ($i == 203) الذي يقصُر التنفيذ على جدول واحد فقط (الترتيب 203) — أثر تصحيح يدوي، يجب إزالته قبل أي تشغيل فعلي. كما توجد دوال صيانة خام: check_missing()، check_auto_increment()، set_auto_increment()، calcBalanceAll() (إعادة حساب أرصدة المرضى)، improve() (نقل أعمدة محدّدة بين قاعدتين). جميعها تحتوي أسماء قواعد بيانات مكتوبة صراحةً (dr_app_old, obgy_app, obor_db, alielhad_obgy) تكشف بيئات نشر متعدّدة (استنتاج).
4. جسر Moon ERP (erp_common)
erp_common.php هو طبقة الربط مع نظام ERP منفصل عبر cURL إلى localhost/erp/controllers/api_web.php?do={endpoint} برأس مصادقة Open-Key (توكن JWT مكتوب صراحةً في الكود — مخاطرة أمنية). الاستدعاء الفعلي الوحيد المُفعَّل هو جلب ديون العميل من الـ ERP:
- في
visits.phpدالةgetrestvaluesP()تتفرّع: إن كانprogramesetting.erpdbمضبوطاً ⟶getrestvaluesPErp()تستدعيorderFromErp('clientdept&id=0&royalid='.$patientId)؛ وإلا تُحسب الديون محلياً منvisits(getrestvaluesPRoyal()). - الـ ERP المقصود هو "Moon ERP" بدلالة المسار
localhost/erp/...ونمطclientdept(ديون العميل) — استنتاج.
erp_common.php يضمّ أيضاً تكاملاً مع مختبر تشريحي خارجي NasLab (api.naslab.gt4it.com/api/patient) عبر getPatientLink() الذي يخزّن رابط النتيجة في patients.inv_link، إضافةً إلى مولّد PDF (TCPDF) ودالة رفع ملفات sendFileWithData().
5. الواجهة الخارجية (api_web) — جسر أجهزة المعمل
api_web.php واجهة JSON خارجية (مصادقة JWT مُعطّلة بالتعليق حالياً). تخدم محورين: تبادل نتائج أجهزة المعمل، وبوابة الجهات المتعاقدة. نتائج الأجهزة تمرّ عبر جدول جسر جديد lab_devices_ranges (يربط investid ↔ device_id برموز send_code/receive_code) وتُسجَّل كل عملية في saveresultslog.
ac=databysample: يُرجع قائمة الفحوص المطلوبة لجهاز ما بحسبsample_id+device_idمع بيانات المريض.ac=saveresults/ac=saveresultsMulti: استقبال نتائج الجهاز وتوجيهها إلى جدول النتائج المناسب حسبspecial_inv_type(16 نوعاً: دم، بول، براز، دهون، eGFR، سائل منوي... إلخ) مع حسابات مشتقة (Lipid، eGFR).ac=orglogin/ac=orgpatientinfo: بوابة الجهات المتعاقدة (انظر القسم 2).
6. استيراد Excel (excelread)
سكربت تحميل دفعي لمرة واحدة (excelread.php) يقرأ excel_backups/newcases.xlsx عبر PHPExcel ويُنشئ سجلات patients، مع إنشاء الأطباء تلقائياً في awusers (checkDrTable/addToDrTable) والجنسيات في nationality. عدد الصفوف مكتوب صراحةً (row <= 8789) — سكربت ترحيل لمرة واحدة وليس واجهة تشغيلية.
7. جدول الكيانات (Entities)
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
branches | معروف (مُوسَّع) | الفروع | الأصلية: id, name, created_at, updated_at + الجديدة: phone1, phone2, location | مرجع لـ visits.branch_id, patients.branch_id, bill_paying.branch_id |
regions | جديد | المناطق الجغرافية | id, name, deleted | أبٌ لـ sub_regions |
sub_regions | جديد | المناطق الفرعية | id, name, region_id, deleted | region_id → regions.id |
organizations | جديد | الجهات المتعاقدة | id, org_id, organization_name, user_name, user_password_hash, deleted | مرجع لـ visits.organization_id وorganizations_patient_no |
organizations_patient_no | جديد | رقم المريض لدى كل جهة | id, organization_id, patient_id, patient_no, deleted | جسر organizations ↔ patients |
lab_devices_ranges | جديد | ربط الفحص بجهاز المعمل ورموز التبادل | id, investid, device_id, invest_child, special_inv_type, send_code, receive_code, deleted | investid → invests.id, device_id → devices.id |
saveresultslog | جديد | سجل نتائج الأجهزة الواردة عبر API | sample_id, device_id, device_name, result, receiving_code, sending_code, lab_devices_ranges_id, investigationresults_id, element_name, element_table_name, element_table_id, create_date | يشير إلى investigationresults وlab_devices_ranges |
investigationresults_* | جديد | نتائج مفصّلة حسب نوع الفحص (blood/urine/stool/lipid/egfr/semen/pt/esr/...) | أعمدة عناصر متخصّصة لكل نوع (مثل hgb, rbc, cholesterol, gfr, sperm_count...) | investigationresults_id → investigationresults.id |
bill_paying | جديد | سندات الدفع (تقارير مالية متعدّدة الفروع) | id, branch_id, ... (استنتاج من billBranchSql) | branch_id → branches.id |
knownfrom | جديد | مصادر معرفة المريض بالمركز (تقرير "Center's Knowledge") | id, name, deleted | مرجع لـ patients.knownfrom |
nationality | جديد | الجنسيات (يُنشأ تلقائياً عند الاستيراد) | id, name | مرجع لـ patients.nationality |
awusers.related_branches | عمود جديد | تقييد صلاحية المستخدم على الفروع | قائمة معرّفات CSV (0=الكل) | قيم تشير إلى branches.id |
awrole.custom_detections / is_doctor | عمود جديد | كشوف فحص مخصّصة للقسم + علامة طبيب | custom_detections CSV، is_doctor 0/1 | custom_detections → detections.id |
programesetting.regions / organizations | عمود جديد | مفاتيح تفعيل نمط المركز | regions 0/1، organizations 1/2/3 | — |
visits.organization_id | عمود جديد | ربط الزيارة بجهة متعاقدة | organization_id | → organizations.id |
patients.branch_id / inv_link | عمود جديد | فرع المريض + رابط نتيجة NasLab | branch_id, inv_link | branch_id → branches.id |
8. التأثير على خطة الـ ERP/HIS
- المخطّط الأصلي (312 جدولاً) ناقص: النسخة الحيّة تحوي على الأقل 7 كيانات جديدة + أكثر من 5 أعمدة جديدة على جداول معروفة لم تُرصد في تقرير obgy؛ يجب توسيع نموذج ترحيل Modules/Obgy ليشمل طبقة المركز متعدّد الفروع.
- وحدة Multi-Tenant/Branch إلزامية في الـ HIS: الفرع والمنطقة والجهة يجب أن تكون أبعاداً أساسية (dimensions) في الزيارات والمرضى والفواتير، مع نموذج صلاحيات مبني على
related_branches. - طبقة الجهات المتعاقدة (Organizations) = وحدة التأمين/الشركات: تتطلّب نمذجة "رقم المريض لدى الجهة" وبوابة API خارجية للجهات؛ تُربط مباشرة بدورة الفوترة والديون.
- تكامل Moon ERP موجود فعلاً (مالي): جلب ديون العميل (
clientdept) من الـ ERP عبرorderFromErp— خطة الـ ERP يجب أن تعتمد الـ ERP مصدراً للحقيقة المالية لا الحساب المحلي، وأن توحّد المصادقة (إزالة التوكنات المكتوبة في الكود). - جسر أجهزة المعمل (LIS):
lab_devices_ranges+saveresultslog+ جداولinvestigationresults_*تشكّل وحدة LIS كاملة بربط ثنائي الاتجاه مع الأجهزة؛ يجب اعتمادها كوحدة مستقلة في الـ HIS. - مخاطر أمنية للتصحيح قبل الإنتاج: توكنات JWT مكتوبة صراحةً في
erp_common.php/api_web.php، مصادقة API معطّلة بالتعليق، وأسماء قواعد بيانات وبيئات نشر صريحة فيsyncstructure.php— يجب نقلها إلى متغيّرات بيئة وتفعيل المصادقة. - أدوات الترحيل لمرة واحدة (
syncstructure,excelread) ليست واجهات تشغيلية: تحوي قيوداً مكتوبة يدوياً (if($i==203),row<=8789)؛ يجب فصلها عن قاعدة الكود الإنتاجية في الـ HIS الجديد.
ملحق: تشغيل العيادات وخدمة العملاء والرضا (MED: Clinic Ops, Customer Service & Vote)
هذا الملحق يوثّق وحدات لم تكن موجودة في النسخة المُحلَّلة (312 جدولاً) وظهرت في النسخة الأحدث المنشورة على med.greennature.com.sa والمُهيّأة كمركز/مستشفى متعدد العيادات والفروع. يغطّي: تشغيل العيادات (الغرف والجداول الأسبوعية وشاشة استقبال المرضى)، وحدة خدمة العملاء (قياس أداء الأطباء وزمن الانتظار والشكاوى)، حملات الرسائل النصية SMS والروابط المختصرة، إقرارات وموافقات المرضى، تتبّع الأرشيف بالأجهزة (دخول/خروج الملفات)، ملخّص الحالة، وتطبيق التصويت/قياس رضا العملاء عبر أكشاك بلوحة مفاتيح عربية. كل الاستنتاجات مبنية على قراءة الكود فقط (RedBeanPHP وعبارات SQL وقوالب Smarty) دون أي اتصال بقاعدة البيانات الحيّة.
نطاق الملف والتغيّر عن النسخة القديمة (Scope & delta)
النسخة الجديدة تحوي ~70 متحكّماً (controller) غير موجود في النسخة المُحلَّلة، وأُزيل منها ~20 متحكّم قديم من نوع «الشيتات» (sheet controllers). الوحدات المغطّاة هنا جديدة بالكامل وتعتمد على جداول لم ترد في الـ dump الأصلي. تظهر هذه الوحدات إضافة طبقة «تشغيل المركز» و«تجربة العميل» فوق نواة OB/GYN الأصلية.
١. تشغيل العيادات والحجز (Clinic Ops & Reservation)
المتحكّم reserve_clinic.php يبني جدولاً أسبوعياً (٧ أيام × ساعات بين programesetting.start_hour وend_hour) لربط الأطباء بالغرف. الغرف في clinic_rooms والحجوزات المتكرّرة أسبوعياً في clinic_reserves (يوم في الأسبوع reserve_day_no 1=السبت..7=الجمعة + ساعة reserve_hour + طبيب doctor_id). يدعم وضعَين أفقي/رأسي (h_version/v_version) وتعدّد الفروع branches حسب programesetting.branches/rooms. الإلغاء منطقي عبر cancel_date+deleted.
المتحكّم clinic_visits.php هو شاشة استقبال المريض داخل العيادة: لكل غرفة نشطة يعرض الأطباء المحجوزين لليوم وزياراتهم اليوم، ويسمح بتسجيل دخول المريض للعيادة (visits.clinic_entered=1) وخروجه (visits.clinic_out=1).
المتحكّم visits00.php هو نسخة موسّعة من تدفّق الزيارة: يوجّه الزيارة إلى قسم/طبيب (for_department/for_doctor) ويربطها بحجز عيادة (reserveId عند القسم 13)، ويرسلها لقوائم أقسام محدّدة (sendToDept/removeFromDept للأقسام 5 و12). هذه الحقول (clinic_entered, clinic_out, arrived_time, arrived_userid, enc_id, visit_order, visit_time, rfc, branch_id) أعمدة جديدة أُضيفت إلى جدول visits المعروف (استنتاج من الاستعلامات).
- الحجز الأسبوعي: تعيين طبيب لغرفة في يوم/ساعة عبر
reserveClinic()← صف فيclinic_reserves. - إنشاء زيارة وتوجيهها لقسم/طبيب (وربما حجز عيادة) عبر
visits00.php. - وصول المريض: تسجيل
arrived_time(من خدمة العملاء) ثم دخول العيادةclinic_entered. - الخروج:
clinic_outويُحتسب زمن الانتظار = الفرق بينarrived_timeوkashf_enterance.
٢. خدمة العملاء (Customer Service)
المتحكّم customer_service.php يخدم ثلاث وظائف: (أ) عرض الأسعار (دمج detections+invests/investcats+rays/rayscats)؛ (ب) لوحة أداء الأطباء: عدّ الزيارات والمؤكَّدة (customer_add!=1) والمحضورة (view=1) لكل طبيب/قسم/فرع مع متوسّط زمن الانتظار؛ (ج) تسجيل وصول المريض arrivedHos() (arrived_time/arrived_userid). يدعم تقييد الطبيب المرتبط (related_dr للدور 19) وطباعة يومية مفصّلة.
إدارة الشكاوى عبر جدول جديد patients_complaints: نص الشكوى complaiv والرد reply ووقت الاتصال call_date_time والموظّف user_id والمريض patientid، مع حذف منطقي deleted وصلاحيات أزرار (awrolebtn btn 5/6).
- مؤشّرات: إجمالي الزيارات، المؤكَّد، الذي حضر فعلاً (
view=1)، ومتوسّط زمن الانتظار بالساعات/الدقائق. - الأقسام المعتمدة تُحدَّد بـ
awrole.doctor_visit_show=1(الأقسام الطبية الظاهرة في تقارير خدمة العملاء). - استثناء كشوف داخلية:
detectionid not in (999, 9999, -88).
٣. حملات الرسائل النصية والروابط المختصرة (SMS Campaigns & Short URLs)
المتحكّم sms_control.php يُعرّف قوالب الرسائل في جدول جديد sms_control (الاسم، نوع الرسالة message_type 1..5، مكان الإرسال message_place، اسم المرسِل sender_name، الرابط الثابت/الإنجليزي fixed_link/en_link، الأقسام المستهدَفة for_depts بقيمة -1 = الكل). الإعدادات العامة في sms_control_setting (server_type). المنطق الفعلي في visits_common.php:
sendSms($sourceId, $messagePlace)يُستدعى منvisits.php/patients.php/operations_reports.phpعند أحداث (تسجيل مريض/حجز زيارة).- يجلب هاتف المريض (
patients.phone/mobile/hus_mobile) والقوالب المفعّلة لمكان الإرسال، ويتحقق من القسم المسموح به (allowedDept). - يبني النص حسب النوع: رسالة فقط / + رابط / + اسم المريض / + رابط مختصر للزيارة (يولّد
enc_idفريداً للزيارة وshort_urls). - الإرسال عبر مزوّد
sms.naslab.gt4it.com(دالةsendItSmsApi) أو القديمsmsmisr.com(دالةsendItSms). - عند
server_type=1يدفع تفاصيل الزيارة إلى موقع خارجي عبرprepareToSite/sendToSite(royal-fc.net/appv/visit_details).
تنبيه أمني الملف sms_sample.php يحوي بيانات اعتماد SMS مكتوبة بشكل ثابت (username/password/sender لـ smsmisr)، كما يوجد توكن Bearer ثابت لمزوّد naslab داخل visits_common.php. يجب نقلها إلى أسرار بيئية وتدويرها.
٤. الإقرارات وموافقات المرضى (Declarations & Consents)
decleration.php يدير قوالب الإقرارات/الموافقات (جدول جديد decleration: title, content, doctor_id/doctor_name, husband/wife/reception). وpatientdecleration.php يربط إقراراً موقَّعاً بمريض (جدول جديد patientdecleration: decleration_id, patientid, uploadfile = ملف ممسوح ضوئياً في upload/decleration_files, user_id, date) مع طباعة منسّقة لبيانات المريض والطبيب وإعدادات المركز.
٥. ملخّص الحالة (Case Summary)
المتحكّم case_summary.php هو مجمِّع للقراءة فقط: يدمج عشرات الجداول السريرية (سجلّ النساء/الولادة والتاريخ المرضي ph*) في تقرير حالة واحد. معظم مصادره جداول معروفة، لكنه يستدعي جداول جديدة في النسخة الموسّعة مثل obstetric_case/obstetric_case_ex, summary_obstetric/summary_obstetric_abortion, previous_pregnancies, previous_puerperium, pre_anaesthetic, blood_transfusion, complaint_analysis, recommend, symptoms (استنتاج — تنتمي لشيتات سريرية موسّعة خارج هذا النطاق).
٦. تتبّع الأرشيف بالأجهزة (Archive Tracking by Devices)
المتحكّم archive.php يستخدم دوال visits_common.php لتتبّع حركة ملفات/مرضى المركز عبر أجهزة قراءة موزّعة. عند مسح رقم المريض على جهاز (devices.location: 4=دخول، 5=خروج) يُسجَّل صف في جدول جديد archive_tracking (patient_id, in_date/in_time/in_device_id, out_date/out_time/out_device_id, receiver, notes, control) مع موقع الطابق من floors عبر devices.floor_no. يوازيه تتبّع عام في device_tracking (معروف). يوفّر بحثاً بالمريض أو بالتاريخ، وقائمة «خرج ولم يعد».
٧. تطبيق التصويت / رضا العملاء (Vote / Satisfaction Kiosk)
تطبيق مستقل تحت /med/vote يعمل كأكشاك رضا بلوحة مفاتيح عربية (kioskboard 2.2 + jQKeyboard). كل جهاز vote_devices (name, local_ip) مرتبط باستبيان votes، ويُنسَب التصويت إلى الموظّف المسجَّل دخوله من نفس الـ IP عبر login_tacking (جلب آخر user_id بـ login_ip وstatus=1). الإدارة في النواة عبر vote.php وvote_devices.php.
- تهيئة جهاز (
vote_devices) ثم بناء استبيان (votes) بأسئلة (vote_questions) وإجابات (vote_answersتحمل وجهاً تعبيرياًfaceوعلَمsend_mail). - المريض/العميل على الكشك يفتح
?ac=vote&device=IDفيُتحقَّق من وجود الجهاز وتسجيل دخول الموظّف. - يُدخِل اسمه/هاتفه (إن كان
votes.voter_required) ويختار الوجوه/الإجابات. - الحفظ في
clients_votes(الجهاز، الاستبيان، الموظّف، اسم/هاتف المُصوِّت، IP المحلي/البعيد، user_agent) وتفاصيل كل إجابة فيclients_votes_answers(question_id,answer_id,answer_face,answer_text). - إعادة التوجيه إلى صفحة شكر
thank_you.
- تقارير الرضا لكل موظّف (
report/reportDetails/empReport): عدد الأسئلة/الإجابات وتوزيع نصوص الإجابات بين تاريخين. - متابعة الشكاوى: تحديث
clients_votes.is_contactوclients_votes.reply(هل تم التواصل + رد إداري). - قابلية إرسال بريد عند إجابة معيّنة (
vote_answers.send_mail+votes.email) ربطاً بدورvotes.role_id.
جدول الكيانات المستنتجة (Entities)
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
clinic_rooms | جديد | غرف/عيادات المركز | name, clinic_no, today_list, branch_id, dept_id, is_active, deleted | ← branches |
clinic_reserves | جديد | جدول حجز الأطباء أسبوعياً للغرف | room_id, doctor_id, reserve_day_no, reserve_hour, start_date, cancel_date, is_active, deleted | ← clinic_rooms, awusers |
visits (أعمدة جديدة) | معروف+ | أعمدة تشغيل العيادة على جدول الزيارات | clinic_entered, clinic_out, arrived_time, arrived_userid, kashf_enterance, enc_id, visit_order, visit_time, rfc, branch_id, customer_add, view, for_department, for_doctor | ← patients, awrole, awusers |
patients_complaints | جديد | شكاوى/ردود خدمة العملاء | patientid, complaiv, reply, call_date_time, user_id, deleted | ← patients, awusers |
sms_control | جديد | قوالب رسائل SMS وحملاتها | name, message, message_type, message_place, sender_name, fixed_link, en_link, for_depts, status, deleted | ← awrole (for_depts) |
sms_control_setting | جديد | إعدادات بوابة SMS العامة | server_type | — |
short_urls | جديد | روابط مختصرة لروابط الرسائل | origin_url, short_url, create_date | ← يُستخدم في رسائل الزيارة |
visits_site | جديد (استنتاج) | دفع تفاصيل الزيارة لموقع خارجي | عبر API royal-fc.net (لا يُخزَّن محلياً غالباً) | ← visits |
decleration | جديد | قوالب الإقرارات/الموافقات | title, content, doctor_id, doctor_name, husband, wife, reception, date | ← awusers |
patientdecleration | جديد | إقرار موقَّع لمريض | decleration_id, patientid, uploadfile, user_id, date | ← decleration, patients |
fastoptions | جديد | روابط سريعة في الواجهة | label, link | — |
archive_tracking | جديد | تتبّع دخول/خروج ملف المريض بالأجهزة | patient_id, in_date/in_time/in_device_id, out_date/out_time/out_device_id, target_id, target_table, receiver, notes, control, user_id, deleted | ← patients, devices→floors |
vote_devices | جديد | أجهزة أكشاك التصويت | name, local_ip, created_at, updated_at | ← login_tacking.login_ip |
votes | جديد | استبيان رضا لكل جهاز | vote_device_id, voter_required, email, role_id, created_at, updated_at | ← vote_devices, awrole |
vote_questions | جديد | أسئلة الاستبيان | vote_id, question, created_at, updated_at | ← votes |
vote_answers | جديد | خيارات الإجابة بوجوه تعبيرية | vote_question_id, answer, face, send_mail, created_at, updated_at | ← vote_questions |
clients_votes | جديد | تصويت العميل المُسجَّل | vote_device_id, vote_id, user_id, voter_name, voter_phone, ip/local_ip/remote_ip, user_agent, is_contact, reply, created_at | ← votes, vote_devices, awusers |
clients_votes_answers | جديد | إجابات تصويت العميل | client_vote_id, question_id, answer_id, answer_face, answer_text, user_id, created_at | ← clients_votes, vote_questions/vote_answers |
login_tacking | جديد | تتبّع جلسات الدخول بالـ IP (لنسبة التصويت للموظّف) | login_ip, user_id, status, id | ← awusers |
التأثير على خطة الـ ERP/HIS (ERP/HIS impact)
- إضافة وحدة «إدارة العيادات والغرف والجدولة الأسبوعية» (
clinic_rooms/clinic_reserves) إلى مخطط الترحيل — لم تكن ضمن الـ 312 جدولاً ويجب نمذجتها كـ Scheduling/Roster مع دعم الفروع. - اعتماد «تجربة المريض/خدمة العملاء» كنطاق مستقل: مؤشّرات زمن الانتظار، حضور/تأكيد الزيارة، والشكاوى (
patients_complaints) — تُربط بلوحات KPI في الـ HIS. - توحيد طبقة الإشعارات: مزوّدا SMS مختلفان (smsmisr الجديم + naslab الحالي) وأسرار مكتوبة بالكود — يجب توحيدها في خدمة Notification واحدة بأسرار بيئية وتدوير فوري للتوكنات المكشوفة.
- محرّك الروابط المختصرة ودفع تفاصيل الزيارة لموقع خارجي (
royal-fc.net) = تكامل بوّابة مرضى خارجية؛ يلزم توثيقه كواجهة Integration في الـ ERP. - الموافقات الرقمية (
decleration/patientdeclerationمع ملفات مرفوعة) تُدرَج ضمن Document/Consent Management في الـ HIS. - تتبّع الأرشيف بالأجهزة (
archive_tracking+devices.location+floors) = نظام Medical Records Tracking مادي يجب تضمينه في وحدة MRD. - تطبيق التصويت (٦ جداول vote) = وحدة Patient Satisfaction مستقلة تُنسَب نتائجها للموظّفين عبر
login_tacking؛ تتطلّب نمذجة Surveys + Employee Performance + متابعة الشكاوى (is_contact/reply). - أعمدة
visitsالموسّعة (enc_id, arrived_*, clinic_*, rfc, branch_id) تؤكّد أن جدول الزيارات في النسخة الجديدة أوسع من المخطط الأصلي ويجب تحديث blueprint وحدة الزيارات.
ملحق: المخازن والمالية الموسعة والأجهزة (MED: Stores, Extended Finance & Devices)
هذا الملحق يوثّق إصدار «المركز/المستشفى» المنشور على med.greennature.com.sa، وهو نسخة أحدث وأوسع من نظام النساء والولادة الذي تم تحليله سابقاً (312 جدولاً). يغطي هذا القسم وحدات المخازن والمستهلكات المعملية، باقات الفحوصات (العروض)، التسعير التعاقدي للجهات (التأمين/الشركات)، تقارير تحويل النقدية للأطباء وتقارير مالية المعمل، إدارة الخدمات (Detections) مع مزامنتها الحيّة مع نظام ERP خارجي، وسجلّات الأجهزة (أجهزة المعمل، أجهزة الكشك/التصويت، الأجهزة الطبية بالغرف). جميع الاستنتاجات مأخوذة من قراءة الكود فقط (استدعاءات RedBeanPHP وجُمل SQL الخام وقوالب Smarty) دون أي اتصال بقاعدة البيانات الحيّة.
نظرة عامة على الوحدات والملفات
تمت قراءة 14 وحدة تحكم بالكامل تحت /med/core/controllers/. أبرز المسارات: المخازن والفحوصات عبر invsdept.php (4061 سطراً) وinvsdept_common.php (4842 سطراً)؛ التطبيق المحمول للمعمل عبر invsdeptapp.php وinvsdeptapp_1.php؛ باقات العروض عبر invoffers.php؛ إدارة الخدمات والتسعير التعاقدي عبر detection.php (2297 سطراً)؛ تقارير المالية عبر financiallab.php وcashtransferdectorreport.php وfinancialreport_old.php وfinancialreport_new_old.php؛ الصيدلية عبر pharmacy.php؛ والأجهزة عبر labdevices.php وadddevices.php (3038 سطراً) وvote_devices.php.
1) المخازن والمستهلكات المعملية (Stores / Lab Supplies)
تُدير وحدة الفحوصات استهلاك المستهلكات لكل تحليل. الأصناف تُصنّف في suppliescats ثم تُسجّل في supplies، ويُربط كل صنف باستهلاكه الفعلي في جدول الوصل invests_supplies الذي يحمل supply_id وsupply_no (الكمية) وusedate. تقرير الاستهلاك في invsdept.php::suppliesPrint() يجمع الكميات بين تاريخين ويُفصّلها حسب الفئة والصنف. كما يربط كل تحليل بنوع العيّنة عبر sampletype.
- تجميع الاستهلاك زمنياً:
SELECT sum(invests_supplies.supply_no) ... WHERE usedate BETWEEN ? AND ?مع الحذف الناعمdeleted = 0. - نموذج النتائج المعملية أُعيد تطبيعه:
investigationresults+ جداول فرعية متخصصة (investigationresults_blood,_culture,_urine,_stool,_semen,_cross,_pt,_esr,_egfr,_lipid,_aborh,_custom,_times) بدلاً من جداول*sheet*القديمة. - المعدلات المرجعية في
inv_ranges(حسب العمر/الجنس/الوحدة)، وإعدادات المعمل فيprogramesettinglabمنفصلة عنprogramesettingالعام. - توليد الباركود لكل عيّنة عبر
createbarcode($statusno)، مع حقلinvestigationresults.sample_idللبحث بالعيّنة.
2) باقات الفحوصات / العروض (invoffers)
يسمح invoffers.php بإنشاء باقة فحوصات (invoffer) تضم عدة تحاليل مسعّرة في invofferdetails (invoffer_id, inv_id, price). سعر الباقة يُحسب ديناميكياً بـ SUM(price) من التفاصيل. العرض يُستخدم لاحقاً في فاتورة الزيارة وفي التسعير التعاقدي للجهات.
- إنشاء العرض في
addit()→R::dispense('invoffer')ثم إدراج صفوفinvofferdetailsلكل تحليل. - التعديل في
updateit()يحذف نعومةً كل التفاصيل (set del=1) ثم يعيد إدراج المختار. - الربط بنتائج الزيارة عبر
investigationresults.offer_id، حيث يُجمَع سعر الباقة منcontract_price - patient_hold.
3) التسعير التعاقدي للجهات (Organizations / Price Lists / Insurance)
إضافة محورية في إصدار المركز: نظام جهات تعاقدية كامل في detection.php. تُعرّف قوائم الأسعار في price_lists، وتُسجَّل الجهات في organizations (مع credit_limit, vat_no, price_list/list_id, sales_persons, contract_start, وحتى بيانات دخول بوابة user_name/user_password_hash). الخصم/السعر التعاقدي لكل خدمة يُخزَّن في organization_discount حسب list_id وdetect_id وdetect_cat (1=كشف، 2=تحليل، 3=أشعة، 4=باقة) ويحمل contract_price وpatient_hold وdiscount_type. ربط المريض برقمه لدى الجهة في organizations_patient_no، والهيكل الهرمي للجهات في organizations_parents.
- عند احتساب فاتورة الزيارة تُربط كل خدمة بـ
organization_discountعبرLEFT JOIN ... ON detections.id/invests.id/rays.id = organization_discount.detect_id. - نتائج الزيارة (
investigationresults) تحملcontract_priceوpatient_holdوoffer_idلتقسيم القيمة بين الجهة والمريض. (استنتاج:patient_hold= الجزء الذي يتحمله المريض). - حقول VAT و
credit_limitتدل على بُعد محاسبي/ضريبي صريح غير موجود في النسخة الأصلية.
4) إدارة الخدمات ومزامنة ERP الحيّة (Detections + erpProduct)
يُدير detection.php كتالوج الخدمات (detections: title, detectionval, create_date, del). أهم اكتشاف هو وجود تكامل ثنائي الاتجاه مع نظام ERP خارجي: عند إنشاء/تعديل أي خدمة تُستدعى erpProduct() التي تفتح اتصال قاعدة بيانات ثانٍ باسم erpDB المخزَّن في programesetting->erpdb، تبحث عن المنتج المقابل في جدول product الخارجي عبر product.obygyDetectionId، ثم تُنشئ/تُحدّث المنتج بنداء cURL إلى ملفات ERP (buyBillControllerAjax.php وproductControllerAjax.php على HOST_URL_ERP) مع تصنيف ثابت Services وisservice=1.
- حفظ الخدمة محلياً في
detections. R::addDatabase('erpDB', ...)ثمR::selectDatabase('erpDB')واختبار الاتصال.- البحث في
product WHERE obygyDetectionId = detection.id. - إن لم يوجد →
curlAddProduct()(إنشاء)؛ وإن وُجد →curlupdateProduct()(تحديث)؛ والحذف عبرerpProductDel()/curlDelProduct(). - العودة إلى
R::selectDatabase('default').
حرج للـ ERP هذا يعني أن قاعدة الخدمات في النظام الطبي هي «مصدر الحقيقة» ويُسقَط منها كتالوج المنتجات/الخدمات في الـ ERP المالي تلقائياً، مع ربط ثابت obygyDetectionId ↔ productId.
5) التقارير المالية وتحويل نقدية الأطباء (Financial Reports / Cash Transfer)
cashtransferdectorreport.php وfinanciallab.php يبنيان تقريراً مالياً موحّداً عبر UNION ALL بين زيارات (visits) ومدفوعات الصيدلية (bill_paying). جدول visits يحمل الحقول المالية: detectionvalue_cash, detectionvalue_visa, totaldetectionvalue, restdetectionvalue, discount, detectionid, dr_salary, refer_doctor/refer_doctor_tb, contract_price, branch_id. تُستخدم قيم خاصة لـ detectionid: 999 = دفع متبقٍ، و9999 = مرتجع العملاء.
- صلاحيات العرض تُحكم بأعمدة على الأدوار/المستخدمين:
awrole.financial_visits(1=قصر على القسم، 2=قصر على الطبيب)، وawusers.financial_user/awusers.cashtransferdoctor_user. - التجميع حسب الفرع (
branch_id) والطبيب المُحوِّل (refer) مع تفصيل الفحوصات/الأشعة (investigationresults/raysresults) ومواعيد الحجز (visit_hours). bill_paying(مدفوعات الصيدلية):type,user_id,patient_id,pay_date,discount,printserial,branch_id؛ والنوعtype=1يُعامَل كمرتجع.financialreport_old.phpنسخة قديمة تعتمد جداول الصلاحياتawcontroll/awmenu/awrole*ولا تضيف كياناً جديداً جوهرياً.
6) الصيدلية وصرف الوصفات (Pharmacy)
pharmacy.php يبحث في الوصفات (prescription) حسب التاريخ/الطبيب/المريض، ويتتبّع حالتي prepared وdelivered مع تدقيق المستخدم (prepared_userid, delivered_userid). الوصفة مرتبطة بـ patient_id وdoctor_id وpres_date وfor_husband.
7) سجلّات الأجهزة (Device Registries)
ثلاثة سجلّات أجهزة منفصلة الأغراض:
- أجهزة المعمل (
labdevices.php):lab_devices(completed,user_id,deleted,delete_userid,delete_date) مع نسخ المعدلات المرجعية لكل جهاز فيlab_devices_ranges(مُشتقّة منinv_ranges:range_low/high,agefrom/ageto,gender,invest_units). - أجهزة الكشك/التصويت (
vote_devices.php):vote_devices(name,local_ip,created_at,updated_at)، مرتبط بجدولvotesعبرvotes.vote_device_id(يمنع الحذف إن وُجدت أصوات). - الأجهزة الطبية بالغرف (
adddevices.php):devices(device_name,location,deleted) موزّعة علىfloors/locations/operations_rooms. (ملاحظة:devices/floors/locationsموجودة مسبقاً في الـ 312 جدولاً.)
8) المعامل الخارجية والأرشيف الطبي (External Labs & Records Archive)
إضافة لإصدار المستشفى داخل adddevices.php: تحويل العيّنات للمعامل الخارجية (external_labs) مع تتبّع الحالة على نتيجة التحليل (investigationresults.external_lab, receive_userid, receive_date, delivered_userid, delivered_date)، ونتائج فحص البنوة (dna_results). كما يوفّر سير عمل طلب السجلات الطبية في archive_request بحالات متعددة وتدقيق كامل: request_userid/date → ready_userid/date → receive_userid/date → return_userid/date مع ملاحظات وإلغاء (cancel_userid). وmanual_operation للعمليات اليدوية.
جدول الكيانات المستنتجة
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
supplies | جديد | أصناف المستهلكات المعملية | name, catid | catid→suppliescats |
suppliescats | جديد | فئات المستهلكات | name | — |
invests_supplies | جديد | استهلاك المستهلكات لكل تحليل | supply_id, supply_no, usedate, deleted | supply_id→supplies |
sampletype | جديد | أنواع العيّنات | name | invests.sampletype→sampletype |
investigationresults | جديد | نتائج التحاليل (نموذج مُطبَّع بديل لـ *sheet*) | visitid, investid, offer_id, contract_price, patient_hold, sample_id, external_lab, receive/delivered_userid+date, deleted | →visits, →invests, →invoffer, →external_labs |
inv_ranges | جديد | المعدلات المرجعية للتحاليل | investid, range_low/high, agefrom/ageto, gender, invest_units, active | investid→invests |
programesettinglab | جديد | إعدادات المعمل | (صف مفرد) | — |
invoffer | جديد | باقات/عروض الفحوصات | name, active, del | 1‑M مع invofferdetails |
invofferdetails | جديد | تفاصيل تحاليل الباقة | invoffer_id, inv_id, price, del | →invoffer, →invests |
price_lists | جديد | قوائم أسعار الجهات | name, deleted | — |
organizations | جديد | الجهات التعاقدية/التأمين | organization_name, org_type, parent_id, list_id/price_list, sales_persons, contract_start, vat_no, credit_limit, user_name, user_password_hash | list_id→price_lists, parent_id→organizations_parents |
organizations_parents | جديد | المجموعات الأم للجهات | name, deleted | 1‑M مع organizations |
organizations_patient_no | جديد | رقم المريض لدى الجهة | patient_id, organization_id, patient_no, deleted | →patients, →organizations |
organization_discount | جديد | السعر/الخصم التعاقدي لكل خدمة | list_id, detect_id, detect_cat(1-4), offer_id, contract_price, patient_hold, discount_type, deleted | →price_lists, →detections/invests/rays/invoffer |
sales_persons | جديد | مندوبو المبيعات للجهات | name (استنتاج) | organizations.sales_persons→ |
detections | معروف | كتالوج الخدمات | title, detectionval, create_date, del | يُزامَن مع product (ERP) |
product | جديد (قاعدة ERP خارجية) | منتج/خدمة في الـ ERP المالي | productId, obygyDetectionId, productName, isservice | obygyDetectionId↔detections.id |
bill_paying | جديد | مدفوعات الصيدلية (POS) | type, user_id, patient_id, pay_date, discount, printserial, branch_id, notes | →patients, →branches |
prescription | جديد | الوصفات الدوائية وصرفها | patient_id, doctor_id, pres_date, for_husband, prepared(+_userid), delivered(+_userid) | →patients, →awusers |
visit_hours | جديد | مواعيد/ساعات حجز الزيارة | visit_id, visit_hour, deleted | visit_id→visits |
lab_devices | جديد | سجل أجهزة المعمل | completed, user_id, deleted, delete_userid, delete_date | 1‑M مع lab_devices_ranges |
lab_devices_ranges | جديد | معدلات الجهاز لكل تحليل | device_id, investid, range_low/high, agefrom/ageto, gender, invest_units, special_inv_type, deleted | →lab_devices, →invests |
vote_devices | جديد | أجهزة كشك تقييم/تصويت | name, local_ip, created_at, updated_at | 1‑M مع votes |
votes | جديد | أصوات/تقييمات الكشك | vote_device_id | vote_device_id→vote_devices |
external_labs | جديد | المعامل الخارجية المرجعية | name, deleted | investigationresults.external_lab→ |
dna_results | جديد | نتائج فحص البنوة (DNA) | receivername, delivered_userid+date | →patients/visits (استنتاج) |
archive_request | جديد | طلب السجلات الطبية | patient_id, doctor_id, visit_id, branch_id, request/ready/receive/return _userid+_date, request_note, receive_note, cancel_userid, deleted | →patients, →awusers, →visits |
operations_rooms | جديد | غرف العمليات/مواقع الأجهزة | name, deleted | devices.location→ (استنتاج) |
manual_operation | جديد | عمليات يدوية | deleted | →patients (استنتاج) |
devices | معروف | الأجهزة الطبية بالغرف | device_name, location, deleted | location→operations_rooms/locations |
التأثير على خطة الـ ERP/HIS
- تكامل قائم يوجد تكامل ERP حيّ فعلي عبر cURL ورابط
obygyDetectionId ↔ product.productId؛ مخطط الترحيل يجب أن يعتمد كتالوجdetectionsكمصدر للخدمات ويستبدل نداءات cURL القديمة بواجهة API نظيفة بدل الكتابة المباشرة في قاعدة الـ ERP. - محاسبة نموذج الجهات التعاقدية (
organizations+price_lists+organization_discount+organizations_patient_no+ VAT/credit_limit) يوفّر أساس وحدة «العقود/التأمين» في الـ ERP الجديد ويجب ترحيله كوحدة مستقلة عن النساء والولادة. - فوترة توحيد مصادر الدخل (
visits+bill_payingعبر UNION) يدل على غياب دفتر أستاذ مركزي؛ يُوصى ببناء جدول «حركات مالية» موحّد في الـ HIS بدل قيمdetectionid=999/9999السحرية للمتبقي والمرتجع. - مخزون
supplies/suppliescats/invests_suppliesتمثّل استهلاكاً فقط دون أرصدة/توريد؛ خطة الـ ERP تحتاج طبقة مخزون كاملة (وارد/منصرف/رصيد/موردين) فوق هذا الاستهلاك. - تطبيع استبدال نموذج
*sheet*القديم بـinvestigationresults*+inv_rangesيبسّط ترحيل المختبر؛ يجب تحديث خرائط الجداول في تقرير الـ 312 لتعكس النموذج الجديد. - أجهزة ثلاثة سجلّات أجهزة منفصلة (
lab_devices,vote_devices,devices) ينبغي توحيدها تحت سجل أصول/أجهزة واحد في الـ HIS مع تصنيف بالنوع. - تتبّع سير عمل
archive_requestوالمعامل الخارجية بحالات وتدقيق كامل (userid+date لكل مرحلة) نموذج جاهز لوحدة «تتبّع الطلبات/سير العمل» في الـ HIS. - تدقيق أعمدة الصلاحيات الجديدة (
financial_visits,financial_user,cashtransferdoctor_user,external_lab) علىawrole/awusersيجب تمثيلها في نموذج الأدوار الجديد بدل الأعلام المتناثرة.
ملحق: ماذا تغيّر في النواة المشتركة — إعدادات أم نسخة أحدث؟ (MED: Shared-Core Diff — Settings or Fork?)
يجيب هذا الملحق على سؤال المالك المباشر: هل نسخة med.greennature.com.sa هي «نفس البرنامج بإعدادات مختلفة»، أم نسخة أحدث (Fork) فيها تباعد فعلي في الكود؟ تمت المقارنة آليًا عبر diff -qr بين obgy/core/controllers وmed/core/controllers، مع مقارنة تفصيلية لخمسة كنترولرات أساسية وفحص ملف الإعدادات aw_config.php ومنظومة programesetting والقوائم، لتحديد ما هو مدفوع بالإعدادات (config-driven) وما هو مكتوب صلبًا في الكود (hard-coded).
الحكم النهائي بالأرقام
النتيجة: نسخة أحدث (Fork) وليست مجرد إعدادات. نعم النواة الإطارية (framework core) واحدة، ونعم MED تعتمد بكثافة على مفاتيح إعدادات لإظهار/إخفاء الوظائف — لكن تلك المفاتيح تتحكم في مسارات كود جديدة كليًا غير موجودة في OBGY إطلاقًا. التباعد بنيوي وليس تجميليًا.
دليل «نسخة أحدث» قاطع: تبعيات Composer جديدة
OBGY لا يحتوي إطلاقًا على composer.json ولا مجلد vendor/. أما MED فيبدأ ملف إعداداته بـ require_once __DIR__ . '/../vendor/autoload.php' ويستورد Monolog\Logger وPsr. هذه تبعيات مُدارة عبر Composer لا يمكن «تفعيلها بإعداد» — وجودها يثبت أن MED بُنيت على سلسلة أدوات (toolchain) أحدث. كما تغيّر R::freeze والمنطقة الزمنية (Cairo بدل Los Angeles) وقاعدة البيانات (medgreennatureco_med).
أين هو «نفس البرنامج» فعلًا (تطابق أو فروق تجميلية)؟
_controll.php: متطابق 100% (303 سطر = 303 سطر) — قلب نظام الكنترولرات لم يتغيّر.examination.php: الفرق+2/-2أسطر فراغات فقط (whitespace) — نفس المنطق حرفيًا._header.php: فروق مسافات وتنسيق فقط._menu.php: الفرق+6/-6فقط — تم تعطيل (تعليق) إعادة التوجيه عند انتهاك الصلاحيات وإعادة تفعيل حذفawrolemenu؛ تغيير سلوكي صغير لا أكثر.
أين هو «التباعد الحقيقي» (Fork)؟
الملفات المشتركة الكبيرة تضخّمت ضِعفيًا إلى خمسة أضعاف، وهذا انفجار في حجم الكود لا يفسّره أي إعداد:
| الملف المشترك | OBGY أسطر | MED أسطر | أسطر مضافة / محذوفة | الدلالة |
|---|---|---|---|---|
visits.php | 1946 | 9660 | +8599 / -885 | 65 → 220 دالة؛ +155 دالة جديدة (مختبر، باركود، فوترة PDF، تكامل ERP) |
patients.php | 2259 | 4157 | +2332 / -434 | 77 → 127 دالة (فروع، منظمات، أرقام ملفات تنظيمية) |
_member.php | 356 | 1018 | كبير | مزامنة الأطباء مع ERP (addAllDoctorsToERP, curlAddDoctor) |
_role.php | 598 | 991 | كبير | صلاحيات أوسع (قوائم مستخدم منفصلة) |
antenalvisit.php | 1361 | 1756 | +395 | حقول/مسارات إضافية للزيارة قبل الولادة |
_sidebar.php | 160 | 361 | +241 / -40 | قائمة جانبية ثانية (userMenuSidebar) وفلترة بنمط النموذج |
programesetting.php | 296 | 376 | +177 / -97 | +44 مفتاح إعداد جديد + جدولا إعدادات جديدان |
setup.php | 225 | 354 | +149 | دوال ERP (geterpVisaAccounts, saveERPDBVisaAccount) وtablesToClean |
الجزء «المدفوع بالإعدادات» — لكنه يقود كودًا جديدًا
منظومة programesetting في MED أصبحت مركز تحكّم بالميزات: أضافت 44 عمودًا/مفتاحًا جديدًا لم يكن لها أي أثر في OBGY، إضافة إلى جدولي إعدادات جديدين programesettingex وprogramesettinglab وجدول أعمدة ديناميكي programesetting2. أمثلة على المفاتيح: system_type، branches، regions، organizations، advance_payment، surgeon، rooms، ovum_tab، embro_tab، tanks_view، whatsapp_sms، national_id_req، barcode_print، refer_doctor، printserial. كل مفتاح يُظهر/يُخفي وظيفة، لكن الوظيفة نفسها كود جديد لا وجود له في النسخة المُحلَّلة. أي: «config-driven» نعم، لكن فوق قاعدة كود مُتفرّعة.
القوائم الجانبية تبقى مدفوعة من قاعدة البيانات عبر awmenu (مع فلترة بـ programesetting.simpleview ونمط النموذج form in (0,1,2))، أي إن البنية الإطارية للقوائم لم تتغيّر — لكن MED أضافت فوقها قائمة مستخدم ثانية.
الكنترولرات الـ21 المُزالة واستبدالاتها (تحوّل من «أوراق» إلى وحدات)
المنطق المعماري المُزال: استُبدلت «الأوراق» أحادية الصفحة (single-page clinical sheets) بكنترولرات وحدات مستقلة (modular controllers):
| أُزيل من MED | البديل في MED | الملاحظة |
|---|---|---|
ancsheet / ancsheet00 | antenalvisit.php (مُوسَّع) + mainantenental* | ورقة ANC ذابت في تدفق الزيارة |
gynasheet / gynasheet00 | gyna.php + ultrasoundgyna.php | فُصلت أمراض النساء عن السونار |
infertilitysheet / 00 | infertility.php | — |
ivfsheet / ivfsheet00 | embryology.php, embryoslab.php, embryofreezing.php, spermfreezing.php, ovumpickupembryotrans.php, ivf_reports.php | ورقة IVF واحدة → 6 وحدات معملية |
iui, monitoring, edd, epc | مدمجة في تدفق الزيارة/التقارير | أُلغيت ككنترولرات مستقلة |
Deliveries | إشعارات الولادة عبر birth_notify + التقارير | — |
operations | operations_reserve.php, operations_calendar.php, operations_rooms.php, operations_reports.php, operation_types.php | وحدة عمليات/غرف كاملة |
mobileservices, sh, addpresenthistory, Completesreport, Ivfstatistics | — | أُزيلت / استُبدلت بتقارير المركز |
قدرات «المركز/المستشفى» الجديدة (لا توجد في OBGY)
- تكامل ERP حيّ:
erp_common.phpيستدعيlocalhost/erp/controllers/api_web.phpبرمز JWT؛ وvisits.phpيزامن فواتير البيع (erpSellbill,erpSellbillUpdate,erpSellbillDel) و_member.phpيزامن الأطباء. - تعدد الفروع/المناطق:
branches,regions,governorate,residence_rooms+ كنترولراتregions.php,branch_common.php,beauty_branches.php. - أقسام إكلينيكية جديدة: مناظير (
endoscopy,colonoscopy,laparoscopic,hystroscopic)، أشعة (raysdept,radiation,addrays)، مختبر (invsdept,labdevices,financiallab)، صيدلية (pharmacy)، ذكورة (and_visits,and_examination,and_history). - باركود/QR للعينات (
createbarcode,createSampleBarCode)، دفعات مقدمة (advance_payment)، أرشفة (archive.php,archive_request).
الكيانات (الجداول) المستنتجة من النواة المشتركة المُعدَّلة
الجداول التالية مُشار إليها في الكنترولرات المشتركة المُعدَّلة في MED، وتمت مقارنتها بقائمة الـ312 جدولًا الأصلية. الأغلبية جديدة (استنتاج من استدعاءات RedBeanPHP والـ SQL الخام):
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
programesettingex | جديد | إعدادات ميزات إضافية (أعمدة ديناميكية) | revisioned + أعمدة من programesetting2 (استنتاج) | يُملأ من programesetting2.colum_name |
programesettinglab | جديد | إعدادات وحدة المختبر | lab_style | 1:1 مع المنشأة |
programesetting2 | معروف | تعريف أعمدة الإعدادات الديناميكية | colum_name | يُسقَط على programesettingex |
organizations | جديد | الجهات/الشركات المتعاقدة | name, discount (استنتاج) | ↔ organizations_patient_no, organization_discount |
organizations_patient_no | جديد | أرقام ملفات المريض حسب الجهة | patient_id, org_id, no (استنتاج) | → patients, organizations |
advance_payment | جديد | الدفعات المقدمة للمريض | patient_id, amount (استنتاج) | → patients / visits |
archive_request | جديد | طلبات أرشفة الملفات | patient_id, status (استنتاج) | → patients, archive_tracking |
patients_childs | جديد | أبناء المريضة (ربط أسري) | patient_id, child_id (استنتاج) | → patients |
governorate / governorate_centers / regions / sub_regions | جديد | التقسيم الجغرافي/الفروع | name, parent_id (استنتاج) | هرمية مناطق ↔ فروع |
operations_main / operation_room / operations_rooms / operationotherth | جديد | وحدة العمليات والغرف | operation_id, room_id, date (استنتاج) | → patients, residence_room |
residence_room / residence_rooms | جديد | غرف الإقامة/التنويم | room_no, status (استنتاج) | ↔ العمليات والحجوزات |
clinic_rooms / day_times / visit_hours / visit_period | جديد | جدولة العيادات والمواعيد | room, start_hour, end_hour (استنتاج) | → visits, الأطباء |
rays / raysresults / raysresults_img / gynarays / mainantenentalrays / andvisitsrays | جديد | قسم الأشعة ونتائجه | visit_id, result, img (استنتاج) | → visits, patients |
investigationresults (+ سلالة _culture/_blood/_urine...) | جديد | نتائج التحاليل المخبرية المفصّلة | visit_id, value (استنتاج) | → visits, أنواع التحاليل |
invoffer / invofferdetails | جديد | باقات/عروض التحاليل | name, price, items (استنتاج) | ↔ التحاليل |
refer / refer_doctor | جديد | تحويل/إحالة الطبيب | doctor, patient_id (استنتاج) | → patients |
sellbill / returnsellbill / bank / bankaccount / client / clientdebtchange | جديد | جسور تكامل ERP (فواتير/عملاء/بنوك) | عبر erp_common.php (استنتاج) | مزامنة مع نظام ERP منفصل |
and_visits / and_examination / and_history (andvisits*) | جديد | وحدة الذكورة (Andrology) | visit_id, حقول إكلينيكية (استنتاج) | → patients |
visits_follows / visit_hours | جديد | متابعات الزيارة والمواعيد | visit_id, date (استنتاج) | → visits |
patients / visits | معروف | الكيانات الأساسية (نفسها بنيويًا) | موسّعة بحقول فروع/جهات | قلب النظام |
إجمالًا تشير قائمة setup.php → tablesToClean إلى نحو 171 كيانًا في عالم MED، منها ~91 كيانًا جديدًا غير موجود في تفريغ الـ312 جدولًا الأصلي.
التأثير على خطة الـ ERP/HIS
- المخطط (blueprint) الأصلي المبني على OBGY/Obgy يغطي «النواة الإكلينيكية» فقط؛ MED تمثّل تطوّر النظام إلى HIS لمركز/مستشفى — يجب تبنّي MED كخط الأساس (baseline) للترحيل، لا OBGY.
- أضِف وحدات جديدة كاملة للخطة: العمليات والغرف، الإقامة/التنويم، المناظير، الأشعة، المختبر المتقدّم، الصيدلية، الذكورة، وحدة IVF المعملية (6 كنترولرات).
- تعدد الفروع والمناطق والجهات (
branches/regions/organizations) يفرض نموذج بيانات متعدد المنشآت (multi-tenant/branch) في الـ ERP الهدف. - تكامل ERP قائم بالفعل عبر
api_web.php(فواتير بيع، عملاء، أطباء) — يجب توثيق هذا الجسر وعدم تكراره؛ ويُوصى بمعالجة رمز JWT المضمّن فيerp_common.phpأمنيًا (استنتاج: سرّ مكتوب صلبًا). - منظومة
programesetting(الآن +44 مفتاحًا + جدولان) يجب أن تُرحَّل كطبقة «تهيئة المنشأة/الميزات» (feature-flags) في الـ ERP، لأنها تحدد المسارات النشطة. - ~91 كيانًا جديدًا يجب إضافتها إلى قاموس بيانات الـ ERP/HIS، مع التحقق من المخطط الحيّ لاحقًا (هذا التحليل من الكود فقط).
- الانتقال من «أوراق» إلى «وحدات» يبسّط الترحيل: كل قسم بات كنترولرًا/خدمة مستقلة قابلة للتعيين على وحدة ERP.
ملحق: الجداول الجديدة المستخرجة من الكود (MED: New Tables Extracted from Code)
تحليل النسخة الثانية المكتشفة من النظام (med.greennature.com.sa) المنشورة على المسار /home/medgreennatureco/public_html/med. هذه نسخة أحدث وأوسع مهيأة كـ«مركز/مستشفى» وليست عيادة نسائية واحدة. تم استخراج معرفة المخطط (الجداول والحقول) من الكود فقط — عبر استدعاءات RedBeanPHP (R::dispense / R::find / R::load / R::getAll) وجمل SQL الخام داخل المتحكمات والقوالب — دون أي اتصال بقاعدة البيانات الحية. تمت مقارنة كل جدول بقائمة الـ 312 جدولاً الأصلية في obgy_12-7-2024.sql لتصنيفه «جديد» أو «معروف».
الأرقام الإجمالية (Quantification)
المصدر: مسح grep على المتحكمات والقوالب في المسارات med/{core,board,pharmacy,vote}/controllers وmed/core/views، ثم تطبيع الأسماء ومقارنتها بمخرجات grep CREATE TABLE من ملف obgy_12-7-2024.sql. ملاحظة: الوحدتان board (مجلس الإدارة) وpharmacy (الصيدلية) تستخدمان جداول معروفة بالكامل (bsession, brequests, councilstaff, drugs, importbill, pharmacystore…) — التوسّع الحقيقي يتركّز في وحدة core الخاصة بالمركز/المستشفى.
اكتشاف معماري: قاعدة بيانات ERP مخصّصة وربط متعدد القواعد (Multi-DB Federation)
الكود يربط عدة قواعد بيانات عبر R::addDatabase() وR::selectDatabase()، أبرزها قاعدة باسم erpDB يُقرأ اسمها من إعداد programesetting->erpdb (استنتاج: تكامل مالي/مخزني مع نظام ERP منفصل)، إضافة إلى قواعد old وnew وobor وroyalDb (استنتاج: ترحيل بيانات بين نشرات/فروع متعددة). هذا يؤكد أن MED ليست تطبيقاً بقاعدة واحدة بل طبقة موحِّدة فوق عدة قواعد.
الجداول الجديدة مجمّعة حسب النطاق (New Entities by Domain)
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
التصويت / استبيان رضا العملاء (Kiosk Voting) — وحدة vote | ||||
votes | جديد | تعريف استبيان/تصويت | id, title, status (استنتاج) | ← vote_questions |
vote_questions | جديد | أسئلة الاستبيان | vote_id, question_text | votes ← vote_answers |
vote_answers | جديد | إجابات/خيارات السؤال | question_id, answer_text, answer_face | → vote_questions |
vote_devices | جديد | أجهزة الكشك (Kiosk) | id, name (استنتاج) | → clients_votes |
clients_votes / client_votes | جديد | سجل تصويت العميل | vote_id, vote_device_id, user_id, voter_name, voter_phone, ip, local_ip, remote_ip, user_agent, created_at | → votes, vote_devices |
clients_votes_answers | جديد | تفاصيل إجابات العميل | client_vote_id, question_id, answer_id, answer_text, answer_face, user_id, created_at | → clients_votes |
| الهيكل التنظيمي والجغرافي (Center / Organizations / Geo) | ||||
organizations | جديد | الجهات/الشركات المتعاقدة (تأمين/شركات) | id, name, deleted, patient_no | ← organization_discount, organizations_patient_no, visit |
organization_discount | جديد | خصومات الجهة المتعاقدة | organization_id, discount_type, value (استنتاج) | → organizations |
organizations_patient_no | جديد | أرقام منتسبي الجهة | organization_id, patient_no | → organizations |
governorate / governorate_centers | جديد | المحافظات والمراكز التابعة | id, name | ← regions / sub_regions |
regions / sub_regions | جديد | المناطق والمناطق الفرعية | id, name, region_id, deleted | → visit.subregion |
nationality / hnationality / religion / hreligion / husstatus | جديد | قوائم مرجعية للمريضة والزوج (h = husband) | id, name | → بيانات المريض |
| الزيارة المركزية والحجز (Visit / Reception / Reservation) | ||||
visit | جديد | سجل الزيارة المركزي للمركز (يحل محل أوراق العيادة القديمة) | patientid, branch_id, branch_name, for_department, for_doctor, for_husband, visitdate, visit_time, original_price, contract_price, discount, organization_id, organization_discount, center_discount, detectionvalue_cash, detectionvalue_visa, dr_salary, is_redirect, enc_id, user_id, printserial | → organizations, patients, branches |
visit_services | جديد | خدمات الزيارة (بنود فاتورة) | visit_id, service, price (استنتاج) | → visit |
visit_hours / day_times | جديد | ساعات/أوقات العمل للحجز | day_no, hour, room_id (استنتاج) | → clinic_rooms |
clinic_reserves / doctors_reserves / reserve_clinic | جديد | حجوزات العيادات والأطباء | visit_id, doctor_id, room_id, reserve_day_no, reserve_hour, start_date, is_active, cancel_date, user_id | → clinic_rooms, visit |
clinic_rooms / operation_room | جديد | غرف العيادات والعمليات | id, name, floor_no | ← الحجوزات |
advance_payment | جديد | دفعات مقدّمة | patient_id, amount, date (استنتاج) | → patients/visit |
| التنويم والإقامة (Residence / Admission) | ||||
residence_rooms / residence_room | جديد | غرف التنويم/الإقامة | name, floor_no, start_time, end_time, create_date, deleted | ← residence_reserves |
residence_reserves | جديد | حجوزات التنويم | room_id, patient_id, start, end (استنتاج) | → residence_rooms |
exit_summary | جديد | ملخص الخروج (Discharge) | visit_id/patient_id, summary (استنتاج) | → visit/patients |
| مختبر الأجنّة والحقن المجهري (IVF / Embryology Lab) — أكبر نطاق جديد | ||||
embryoslab | جديد | دورة معمل الأجنة | date, visit_id, patient_id, clinician_id, embryologist_id_tb, referred_dr_id, create_date | ← embryo, tankcells |
embryo | جديد | الجنين المفرد | embryoslab_id, embryologist_id_tb, icsi_by_tb, freeze_embryologist_id_tb, cancelled_user | → embryoslab, embryotype |
embryofreezing / embryothawing / embryofreezingreport | جديد | تجميد/إذابة الأجنة والتقارير | embryofreezing_id, embryologist, date, protocol | → embryo, tankcells |
embryotransfer / embryotransferovum / ovumpickup | جديد | الإرجاع وسحب البويضات | clinician_name, embryologist_name, date | → embryoslab |
embryologist / embryologyreport / embryoscoring / embryotype / embryodifficulty / embryojetplace | جديد | قوائم مرجعية ودرجات الأجنة | id, name, grade | → embryo |
oocytequality / oocytecytoplasm / oocytezona / oocytepvs / oocyteother | جديد | تقييم جودة البويضات | id, name | → ovumpickup |
tanks / tanks_general / tankcells / tankcellhistory / embryoslab_tank_cells | جديد | خزانات النيتروجين وخلايا التخزين وسجل حركتها | embryoslab_id, tank_cell, cell_no, row_no, col_no, btn_no, color_name, location, date_add, user_id, deleted | → tanks, embryofreezing |
growthmedia / growthincubator / growthco2 / growthoil / freezingmedia / freezingprotocol | جديد | قوائم مرجعية لبيئة الزراعة والتجميد | id, name | → embryoslab |
ivf_records / ivf_report | جديد | سجلات وتقارير دورات الحقن المجهري | patient_id, date (استنتاج) | → embryoslab |
الحيوانات المنوية والذكورة (Andrology / Semen) — وحدة and* | ||||
andvisits | جديد | زيارة عيادة الذكورة | patientid, doctorid, doctorname, date, complaintid, diagnosisid | ← andvisits* |
andvisitssemen / andvisitsus / andvisitsrays / andvisitsinvestigation / andvisitsficils / andvisitsgenetictesting / andvisitsdrugs | جديد | تفاصيل زيارة الذكورة (سائل منوي/سونار/أشعة/تحاليل/أدوية/فحص جيني) | andvisitsusid, azf, chromosome, length, width, volume, name, type, sysdate | → andvisits |
andexamination / andhistory / andejaculation / anderection / andcontraception / andmedicalproblems / anddiagnosis / andcomplaint | جديد | الفحص والتاريخ الذكوري وقوائمه | id, name, deleted | → andvisits |
andcontratype / erectiondisease / ejaculationdisease | جديد | قوائم مرجعية للذكورة | id, name | قوائم |
semen_analysis / semen_process / semen_processing / semen_cryopreservation / sperm_extract / spermfreezingreport / sperum_source | جديد | تحليل ومعالجة وتجميد السائل المنوي | patient_id, source, date (استنتاج) | → andvisits/embryoslab |
| المنظار (Endoscopy / Colonoscopy) | ||||
endoscopy / colonoscopy | جديد | تقرير منظار علوي/سفلي | patient_id, exam_date, indication, findings, conclusion, plan, esophagus, stomach, duodenum, pylorus, cardio_esophageal_junction, dre, anesthesia, instrument, preparation, consent, signature, created_at | ← *_images, *_template |
endoscopy_images / colonoscopy_images | جديد | صور المنظار | endoscopy_id / colonoscopy_id, image | → التقرير الأب |
endoscopy_template / colonoscopy_template | جديد | قوالب جاهزة للتقارير | name, findings, conclusion (استنتاج) | قوالب |
oscopic_report / oscopic_operations / oscopic_specimens / oscopic_required_examinations | جديد | تقارير وعمليات وعينات المنظار العامة | patient_id, specimen, date (استنتاج) | → التقارير |
| العمليات وغرفها والتخدير (Operations / OR / Anaesthesia) | ||||
operations_main / operation_data / operation_form / operationgyna | جديد | سجل العمليات وبياناتها | patient_id, operation_type, date, room_id (استنتاج) | → operation_room, operations_rooms |
operations_rooms / operations_rooms_cal | جديد | غرف العمليات وتقويم حجزها | room_id, date, status (استنتاج) | → operation_room |
operationinstructions / operationotherth / followup_operation / manual_operation / manual_operation_updates | جديد | تعليمات ومتابعة العمليات | operation_id, text (استنتاج) | → العمليات |
pre_anaesthetic / intra_anaesthetic / anasthesa | جديد | تقييم التخدير قبل/أثناء العملية | operation_id, notes (استنتاج) | → العمليات |
| نتائج المختبر التفصيلية (Lab Investigation Results) | ||||
investigationresults | جديد | رأس نتيجة تحليل | patient_id, invest_id, sampletype, date, value (استنتاج) | ← الجداول الفرعية أدناه |
investigationresults_blood / _urine / _stool / _semen / _culture / _cross / _cross_donners / _lipid / _egfr / _esr / _pt / _aborh / _custom / _times | جديد | نتائج مفصّلة حسب نوع العينة | investigationresults_id, parameter, value, normal_range (استنتاج) | → investigationresults |
stool_rbc / stool_rbc2 / stool_wbc / stool_wbc2 / urine_pus / urine_pus2 / urine_pbcs / urine_pbcs2 | جديد | قوائم خيارات نتائج البول والبراز (مجهري) | id, name | قوائم |
invest_elements / inv_ranges / sampletype / esr_ | جديد | عناصر التحاليل والمعدلات الطبيعية وأنواع العينات | invest_id, element, min, max, sampletype (استنتاج) | → investigationresults |
lab_devices / lab_devices_ranges / saveresultslog / external_labs | جديد | أجهزة المختبر ومعدلاتها وسجل الحفظ والمختبرات الخارجية | device, range_min, range_max (استنتاج) | → النتائج |
| الأشعة (Radiology) | ||||
rays / rayscats / raysresults / raysresults_img / gynarays / mainantenentalrays | جديد | طلبات وفئات ونتائج وصور الأشعة | name, patient_id, result, image (استنتاج) | → visit/patients |
| الصيدلية والوصفات والمخزن (Pharmacy / Prescriptions / Store) | ||||
prescription / prescription_details | جديد | وصفة طبية وتفاصيلها | patient_id, drugname, drugtype, drugdos | → patients |
prepared_prescriptions / prepared_prescriptions_drugs | جديد | الوصفات المُحضّرة بالصيدلية | prescription_id, drug_id, qty (استنتاج) | → prescription, drugs |
stores / storedrugs / storedrugsvalidation | جديد | المخازن وأدويتها وصلاحياتها | store_id, drug_id, qty, expiry (استنتاج) | → drugs |
drugmovements / recorddrugs / importdrugs / followupdrugs | جديد | حركة وتوريد ومتابعة الأدوية | drug_id, amountbefore, amountafter, amountvary, optype, opdate | → drugs, stores |
drug_sensitivity / drug_therapy / antibiotic_sensitivity | جديد | حساسية الأدوية والمضادات والعلاج | drug_id, result (استنتاج) | → drugs |
supplies / suppliescats / invests_supplies / invoffer / invofferdetails | جديد | المستلزمات والعروض المرتبطة بالتحاليل | id, name, cat, price (استنتاج) | → المخزن/التحاليل |
| تاريخ المريض والنماذج العامة (Patient History / Forms / Misc) | ||||
pasthistorymedical / pasthistorysurgical / pasthistoryart / pasthistorygynencological | جديد | التاريخ المرضي/الجراحي/المساعد على الإنجاب/النسائي | patient_id, text (استنتاج) | → patients |
phpersonal / phsexual / phsexualtypes / phpasthx / phpasthxtypes / phpastartresult / phdrugs | جديد | ملف العقم الشخصي/الجنسي/التاريخ السابق | patient_id, type, result (استنتاج) | → patients |
obstetric_case / obstetric_case_ex / obstetrichistorydetails / summary_obstetric / summary_obstetric_abortion / previous_pregnancies / previous_puerperium | جديد | التاريخ الولادي وملخصاته | patient_id, pregnancy_no, outcome (استنتاج) | → patients |
menstural*: mensturalhistory / mensamount / mensdysmo / mensregularity | جديد | تاريخ الدورة الشهرية وقوائمها | patient_id, amount, regularity (استنتاج) | → patients |
patientinformation / patientdecleration / patients_childs / patients_complaints / patients_notify / relative | جديد | بيانات وأقارب وأبناء وشكاوى وإشعارات المريض | patient_id, name, relation, complaint (استنتاج) | → patients |
patient_hystroscopic / patient_laparoscopic / hystroscopic / laparoscopic | جديد | مناظير الرحم والبطن للمريضة | patient_id, findings (استنتاج) | → patients |
vital_sign / fetal_pulse / blood_transfusion / bltype / dna_results / complaint_analysis / decleration / patientdecleration | جديد | علامات حيوية ونقل دم وفحوص متفرقة وإقرارات | patient_id, value, type, date (استنتاج) | → patients/visit |
| المتابعة والأرشيف والإعدادات والبنية التحتية (Follow-up / Archive / Settings / Infra) | ||||
follow_drugs / follow_drain / follow_post / follow_pre / follow_rout / follow_semen / follow_uop / follow_vpack / follow_instruction / visits_follows | جديد | بطاقات متابعة ما بعد العملية/الزيارة | visit_id/patient_id, note, date (استنتاج) | → visit |
archive_request / archive_tracking | جديد | طلب وتتبّع ملفات الأرشيف الورقي | patient_id, in_date, out_date, in_time, out_time, deleted | → patients |
programesetting2 / programesettingex / programesettinglab | جديد | إعدادات إضافية للنظام والمختبر والـERP (erpdb, tanks_view, visit_phones…) | key, value, erpdb | إعدادات عامة |
sms_control / sms_control_setting / login_tacking | جديد | تحكم الرسائل النصية وتتبّع تسجيلات الدخول | user_id, ip, date, sms_template (استنتاج) | → المستخدمين |
short_urls / index_redirect | جديد | اختصار الروابط وإعادة التوجيه (للروابط المرسلة بالرسائل) | code, target_url (استنتاج) | عام |
awusermenu / device / visibility / colors / fastoptions / custom_select / doc_instruction / recommend / refer / knownfrom / symptoms / disease / diseasefamily / medicaldisease | جديد | قوائم مرجعية وإعدادات واجهة وقوائم تشخيصية | id, name, deleted | قوائم/إعدادات |
beauty_visits | جديد | زيارات التجميل (وحدة beauty في المركز) | patient_id, date (استنتاج) | → patients |
ملاحظة منهجية: الحقول الموسومة «(استنتاج)» مُستنبطة من سياق الكود (أسماء الأعمدة في جمل SQL أو خصائص beans في RedBeanPHP) دون رؤية تعريف الجدول الفعلي، إذ لم يتم الاتصال بقاعدة البيانات الحية. القوائم المرجعية الكثيرة (id, name, deleted) موحّدة النمط في كامل النظام.
التأثير على خطة الـ ERP/HIS (Impact on ERP/HIS Plan)
- المخطط الأصلي ناقص: النسخة المنشورة (312 جدولاً) تمثّل عيادة نسائية فقط؛ نشرة MED أضافت 276 جدولاً جديداً تحوّل النظام إلى مركز/مستشفى متعدد التخصصات. يجب توسيع مدوّنة الترحيل (Migration Blueprint) لتغطي هذه الكيانات.
- وحدات كاملة غائبة عن التحليل الأصلي: مختبر الأجنة (IVF) المتكامل بخزانات النيتروجين والتتبّع الخلوي، الذكورة (Andrology)، المنظار (Endoscopy/Colonoscopy)، غرف العمليات وتقويمها، التنويم/الإقامة، نتائج المختبر التفصيلية حسب نوع العينة، والأشعة — كلها تحتاج وحدات مستقلة في خطة الـ HIS.
- تكامل ERP موجود مسبقاً: الكود يربط قاعدة
erpDBمنفصلة (اسمها منprogramesetting->erpdb) مع علامات مثلiserppaymentوenterorderedفي جدولvisit— أي أن جسر مالي/مخزني نحو نظام ERP قائم بالفعل ويجب استيعابه بدل إعادة بنائه من الصفر. - طبقة قواعد بيانات متعددة: وجود
old/new/obor/royalDbعبرR::addDatabaseيعني سيناريوهات ترحيل/دمج بين فروع ونشرات. خطة الـHIS يجب أن تتعامل مع توحيد هذه القواعد (Master Patient Index) لا قاعدة واحدة. - محور الزيارة الجديد: جدول
visitأصبح القلب المالي والتشغيلي (تسعير، خصومات جهات تعاقد، تحويل بين أقسام/أطباء، توجيه استقبال). يجب أن يكون كيان الـ Encounter المركزي في نموذج الـHIS. - الجهات المتعاقدة والتأمين:
organizations + organization_discount + organizations_patient_noتضيف بُعد التأمين/الشركات المتعاقدة المفقود من المخطط الأصلي — أساسي لوحدة الفوترة (Billing/Claims). - تتبّع المخزون الدوائي بالحركات:
drugmovements / storedrugs / storedrugsvalidationبحقولamountbefore/after/vary, optype, opdateتوفّر دفتر أستاذ حركي للمخزون يجب ربطه مباشرة بوحدة المخزون في الـERP. - قبل أي ترحيل: يجب التحقق من البنية الفعلية لهذه الـ276 جدولاً عبر
SHOW CREATE TABLEعلى قاعدة MED الحية (بإذن وخارج نطاق هذا التحليل القائم على الكود فقط) لتأكيد الأنواع والمفاتيح قبل تصميم خرائط الترحيل.
ملحق: تعديلات مطلوبة على خطة النقل بعد اكتشاف MED (ERP Plan Amendments)
مخطط الهجرة المنشور (§95) بُني على النسخة العيادية ذات الـ312 جدولًا، وقرار المعمارية النهائي (Platform-First) صمّم Modules/HIS كمنصة سريرية عامة وModules/Obgy كأول تخصص. اكتشاف نسخة MED (~276 جدولًا جديدًا، 9 مجالات وظيفية) لا يقلب هذا القرار — بل يؤكده — لكنه يفرض تعديلات نطاق محددة: ما يذهب إلى HIS، وما يذهب إلى Obgy، وما يُغطّيه ERP القائم أصلًا، وما يُسحب ويُتقاعد. الجدول التالي هو قائمة التعديلات الملزمة على المخطط.
جدول التعديلات على مخطط §95
| الإضافة المكتشفة في MED | الوجهة في الخطة | الجداول المقترحة / آلية الاستيعاب | الحجم |
|---|---|---|---|
التنويم وغرف العمليات (operations_rooms, residence_rooms, operations_rooms_cal, operations_main, أعمدة التنويم على visits) |
Modules/HIS — المرحلة 4 (تنويم) + جراحة P1 |
التصميم المعتمد يستوعبها كما هو: his_wards/his_rooms/his_beds/his_bed_assignments/his_encounter_movements + his_surgical_bookings. التعديل المطلوب: إضافة تقويم شرائح غرف العمليات (his_or_slots) بمنع تعارض على مستوى قاعدة البيانات (MED تكتشف التعارض في PHP فقط)، وترقية «نوع العملية» من جدول detections المشترك إلى كتالوج إجراءات حقيقي، وتوحيد محرّكي الحجز المتوازيين في كيان حجز واحد بحالة صريحة. لوحة الإشغال الحيّة وقوائم اليوم (today_list) تثبت الحاجة لشاشة أسرّة لحظية |
M |
معمل الأجنة + خزانات النيتروجين (~40 جدولًا: embryoslab, embryoscoring, embryo, tanks/tankcells/tankcellhistory…) |
Modules/Obgy — توسعة كبرى للمرحلة 2 |
المخطط الأصلي خصّص obgy_cryopreservations واحدًا فقط؛ يلزم الآن نطاق فرعي كامل: obgy_embryology_sheets، obgy_embryo_records، obgy_embryo_scorings (يوم 2–6 كصفوف his_observations حيث أمكن)، obgy_cryo_tanks، obgy_cryo_positions، obgy_cryo_custody_events (سجل عهدة على نمط tankcellhistory)، obgy_thaw_events. شرطان إلزاميان: توحيد نموذجي التخزين المتوازيين قبل الهجرة، وجعل الشاهد الثاني (double-witnessing) حقلًا إجباريًا على كل تجميد/إذابة/نقل. ~30 جدول قوائم مرجعية تذوب في his_lookups |
L |
| قوالب المناظير (14 جدولًا: معدة/قولون/بطن/رحم + قوالب + صور) | Modules/Obgy + محرّك النماذج في HIS |
أنماط القوالب الثلاثة في MED تُستبدل بمحرّك النماذج المعتمد (his_form_templates/his_form_versions غير القابلة للتعديل/his_form_responses بحالة توقيع)؛ بنك القوالب المسمّاة يصبح محتوى نسخ نماذج. obgy_endoscopy_procedures المخطط يبقى للنساء؛ مناظير الجهاز الهضمي تُسجَّل كمحتوى نماذج عام (لا جداول صلبة) تمهيدًا لبوابة «التخصص الثاني». أرشيف الصور → مكتبة الوسائط الموحّدة. يُصحَّح عيب حقن «المبيض الأيسر» في oscopic.js ولا يُنقل |
M |
عيادة الذكورة (~17 جدول and*) |
Modules/Obgy (عيادة رفيعة) + كتالوج LIS |
وفق قرار المجلس: تحاليل السائل المنوي والهرمونات تصبح فحوصات في كتالوج LIS بمدًى مرجعية WHO (andvisitssemen → نتائج LIS، لا جدول خاص). يبقى في Obgy: obgy_andrology_visits وobgy_andrology_exams (فحص سريري ثنائي الجانب) والتاريخ المرضي كمحتوى محرّك أسئلة؛ القوائم المرجعية (anddiagnosis، erectiondisease…) → his_lookups. الزيارة نفسها = his_encounters عادي |
M |
قسم الأشعة (rays/rayscats/raysresults/raysresults_img) |
ملاحظة RIS مستقبلية — المرحلة 5 عبر عقد D3 | لا جداول الآن. نمط MED (طلب → قائمة عمل → أداء → صور → إنهاء) يؤكد صلاحية عقد D3 المعتمد (Action + encounter_id + FolioChargePosted) للأشعة كما للمختبر. الكتالوج المُسعّر (rays) يدخل كتالوج الخدمات في Core عند التنفيذ؛ الصور → خدمة وسائط/PACS-lite. تنبيه توثيقي: radiation.php ليس أشعة بل خطابات تحويل/تعليمات — يُستثنى من نطاق RIS |
S الآن / L لاحقًا |
الفروع والمناطق والمنظمات (regions/sub_regions, organizations* , awusers.related_branches) |
Modules/Core القائم + توليدة التأمين في HIS P1 |
الفروع أصلًا أولّية في المنصة (company_id/branch_id على BaseModel + DataScope) — يُستبدل نطاق CSV في related_branches بربط مستخدم↔فرع القائم. regions/sub_regions → قوائم جغرافية في Core. المنظمات المتعاقدة = وحدة التأمين/B2B القائمة: organizations → شركاء أعمال + عقود، organization_discount/price_lists → قواعد قوائم الأسعار المعتمدة في HIS P1، organizations_patient_no → أرقام مرضى لكل جهة على نمط ext_scope_key، وبوابة المنظمات الخارجية تُعاد كتابتها على Sanctum |
M |
جسر أجهزة المختبر والنتائج التفصيلية (lab_devices, lab_devices_ranges, investigationresults_* ×13, saveresultslog) |
Modules/LIS القائم — تخطيط فقط |
لا جداول جديدة: LIS في Moon ERP يغطي واجهات الأجهزة وأنواع النتائج أصلًا. العمل = جدول تخطيط في الـETL يربط investid القديم وأكواد الإرسال/الاستقبال بكتالوج LIS، ويستوعب الأنواع الـ16 الخاصة (دهون/eGFR…) كنتائج محسوبة. saveresultslog → تدقيق LIS القائم. قاعدة D5 تبقى: لا تغيير في سلوك LIS |
S |
كشك تقييم رضا المرضى (6 جداول vote* + clients_votes*) |
ملاحظة CRM/جودة — خارج HIS v1 | لا يدخل نطاق الهجرة الأساسي؛ يُوثَّق كمتطلب لوحدة جودة/تجربة مريض مستقبلية (استبيانات لكل جهاز، إسناد للموظف، متابعة شكوى is_contact/reply). شكاوى المرضى (patients_complaints) ومؤشرات الانتظار تُشتق لاحقًا من طوابع his_encounters الزمنية |
ملاحظة |
الرسائل النصية والروابط القصيرة (sms_control, short_urls, مزوّدا smsmisr/naslab) |
خدمة إشعارات موحّدة في Core | قوالب الرسائل (أنواع 1–5 لكل قسم) → خدمة Notification واحدة متعددة القنوات (SMS/WhatsApp) ببيانات اعتماد في .env مع تدوير فوري للأسرار المكشوفة المكتوبة صلبًا في الكود الحالي. محرّك الروابط القصيرة يُستبدل بنمط بوابة المريض المعتمد /p/:token |
S |
طبقة مزامنة ERP القديمة (erp_common.php, api_web.php, قاعدة erpDB, مزامنة فواتير/أطباء/مديونية عبر cURL وJWT صلب) |
تُسحب وتُتقاعد | التكامل يصبح أصليًا بالكامل وفق العقود المعتمدة: المريض هو سجل lab_patients، والمال عبر his_folio_charges → ChargePostingService → CreateJournalEntry، والطبيب عبر سلسلة lab_doctors → employees → users. قيمة وحيدة تُحفظ من الطبقة القديمة: خرائط المعرّفات (obygyDetectionId/obygyVisitId/obygyPatientId) تُستخدم مرة واحدة في تسوية الـETL ثم تُهمل |
S (تفكيك) |
الإقرارات والموافقات الموقّعة (decleration/patientdecleration + ملفات مرفوعة) |
محرّك نماذج HIS + مكتبة وسائط | قوالب الإقرار → his_form_templates (نسخ غير قابلة للتعديل)، والإقرار الموقَّع → his_form_responses بحالة signed، والمسح الضوئي → مرفق وسائط موثّق |
S |
جدولة العيادات وتتبّع الملفات (clinic_rooms/clinic_reserves, archive_tracking/archive_request) |
Modules/HIS P1 (جدولة) + ملاحظة سجلات طبية |
الجدولة الأسبوعية طبيب×غرفة×ساعة تؤكد صواب قرار «أعمدة الموارد من اليوم الأول» على his_appointments — تُستوعب دون جداول إضافية. تتبّع حركة الملفات الورقية بالماسحات يبقى ملاحظة تصميم لوحدة السجلات الطبية (كما كان مقررًا لجداول devices/floors)، مع الاحتفاظ بنمط سير العمل رباعي المراحل بتدقيق لكل مرحلة كقالب لوحدة تتبّع الطلبات |
S |
ملاحظة ETL المنقّحة: قاعدتا إنتاج الآن، لا واحدة
كل خطة الـETL في §95 افترضت قاعدة إنتاج واحدة. أصبح لدينا نشرتان إنتاجيتان بمخططين متباعدين: قاعدة العيادة الأصلية (312 جدولًا) وقاعدة MED (medgreennatureco_med، +276 جدولًا وأعمدة إضافية كثيرة على الجداول المعروفة مثل visits الموسّع). التعديلات الملزمة:
- تشغيل خط الـETL لكل نشرة على حدة بعمودي تتبّع
legacy_dbإلى جانبlegacy_id/legacy_table، مع قاموسي تخطيط أعمدة منفصلين (مخططvisitsوحده يختلف جوهريًا بين النسختين). - تمرير دمج فهرس مرضى رئيسي (MPI) عبر النشرتين قبل الإدخال في
lab_patients: نفس المريض قد يوجد في القاعدتين (أداةsyncstructure.phpوأسماء القواعد المتعددة فيها تثبت تاريخ نقلٍ بين النسخ) — إلغاء التكرار بالهوية الوطنية/الهاتف/الاسم+الميلاد مع طابور مراجعة بشرية (توسعة R10). - تصدير إنتاجي حديث من القاعدتين قبل كل بروفة ETL (توسعة بوابة R7)، لأن مخطط MED بأكمله مستنتج من الكود فقط ولم تُستعلم قاعدته الحيّة إطلاقًا.
- قواعد أسبقية أجيال إضافية داخل MED نفسها: محرّكا حجز العمليات المتوازيان، ونموذجا تخزين الخزانات، والنموذج المعملي القديم/المُطبَّع — كلها تحتاج قرارات دمج موقَّعة من الأطباء (توسعة R3).
سطور المخاطر المحدثة (تُضاف إلى سجل §95)
- R13 — المخطط مستنتج من الكود فقط: جداول MED الـ276 وأعمدتها استُخرجت من نداءات RedBean وSQL الخام دون لمس القاعدة الحيّة؛ بوابة إلزامية:
SHOW CREATE TABLEعلى قاعدة MED (بتصريح) قبل اعتماد أي تخطيط نهائي. - R14 — مصادر حقيقة متوازية داخل MED: حجوزات عمليات بمحرّكين غير متزامنين، وخزانات بنموذجين، ولا قيود تعارض في القاعدة — خطر ازدواج/فقد سجلات أثناء الدمج؛ المعالجة: تقارير تصادم لكل مريض/غرفة/خزان قبل الترحيل.
- R15 — دَين أمني أوسع (توسعة R12): مفاتيح JWT وكلمات مرور SMS مكتوبة صلبًا، تجاوز مصادقة في
operation_details، بوابة API خارجية بمصادقة معطّلة، وكتابة جداول/أعمدة بأسماء قادمة من المستخدم — تُعالج في المرحلة 0b على نشرة MED أيضًا، ولا يُنقل أي endpoint قديم. - R16 — أدوات نقل يدوية مزروعة في الكود الحي: سكربتات لمرة واحدة بمحدِّدات معدّلة يدويًا (
syncstructure،excelread) موجودة في مسار الإنتاج — تُستبعد من أي نقل وتُعطَّل فورًا. - تحديث R8: جرد الوسائط يجب أن يشمل شجرة رفع MED أيضًا (صور مناظير وأشعة وإقرارات ممسوحة) وليس 4.8GB الأصلية فقط.
الخلاصة الإدارية: لا تغيير في المعمارية المعتمدة ولا في تسلسل المراحل — التغيير في النطاق والحجم: المرحلة 2 (Obgy) تكبر بمعمل الأجنة والذكورة، والمرحلة 4 (تنويم) تكتسب نموذجًا مرجعيًا حيًا من MED، والـETL يصبح ثنائي المستأجر. اكتشاف MED يرفع كلفة الترحيل قليلًا لكنه يرفع اليقين كثيرًا: المورّد القديم أثبت بالفعل أن طريق «العيادة → المستشفى» هو ما يطلبه السوق.