هذا الملحق يوثّق النسخة الأحدث (نمط "مركز/مستشفى") المكتشفة في موقع med.greennature.com.sa. النسخة الأصلية المنشورة (312 جدولاً) كانت عيادة نسائية مفردة؛ أمّا هذه النسخة فتُحوّل النظام إلى منظومة متعدّدة الفروع والمناطق، مع طبقة مزامنة قواعد بيانات (syncstructure)، وجسر ربط مع نظام Moon ERP (erp_common عبر localhost/erp/controllers/api_web.php)، وواجهة خارجية (api_web) تخدم أجهزة المعمل والجهات المتعاقدة (Organizations). كل ما يلي مُستخرَج من الكود قراءةً فقط (RedBeanPHP و SQL الخام) دون أي استعلام لقاعدة البيانات الحيّة.
التفعيل يتم عبر ثلاثة مفاتيح في 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.php يوفّر CRUD كامل على branches مع حقن اختياري لموقع خارجي (sendToSite() إلى royal-fc.net/appv/visit_details/branches — معطّل حالياً بالتعليق).كيان جديد كلياً يُمثّل الجهات/الشركات المتعاقدة (تأمين/مؤسسات). يُربط بالزيارة عبر العمود الجديد 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 ويحسب عدد النتائج المُسلَّمة).أداة 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) تكشف بيئات نشر متعدّدة (استنتاج).
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()).localhost/erp/... ونمط clientdept (ديون العميل) — استنتاج.erp_common.php يضمّ أيضاً تكاملاً مع مختبر تشريحي خارجي NasLab (api.naslab.gt4it.com/api/patient) عبر getPatientLink() الذي يخزّن رابط النتيجة في patients.inv_link، إضافةً إلى مولّد PDF (TCPDF) ودالة رفع ملفات sendFileWithData().
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).سكربت تحميل دفعي لمرة واحدة (excelread.php) يقرأ excel_backups/newcases.xlsx عبر PHPExcel ويُنشئ سجلات patients، مع إنشاء الأطباء تلقائياً في awusers (checkDrTable/addToDrTable) والجنسيات في nationality. عدد الصفوف مكتوب صراحةً (row <= 8789) — سكربت ترحيل لمرة واحدة وليس واجهة تشغيلية.
| الجدول | جديد/معروف | الغرض | أهم الحقول المستنتجة | العلاقات |
|---|---|---|---|---|
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 |
related_branches.clientdept) من الـ ERP عبر orderFromErp — خطة الـ ERP يجب أن تعتمد الـ ERP مصدراً للحقيقة المالية لا الحساب المحلي، وأن توحّد المصادقة (إزالة التوكنات المكتوبة في الكود).lab_devices_ranges + saveresultslog + جداول investigationresults_* تشكّل وحدة LIS كاملة بربط ثنائي الاتجاه مع الأجهزة؛ يجب اعتمادها كوحدة مستقلة في الـ HIS.erp_common.php/api_web.php، مصادقة API معطّلة بالتعليق، وأسماء قواعد بيانات وبيئات نشر صريحة في syncstructure.php — يجب نقلها إلى متغيّرات بيئة وتفعيل المصادقة.syncstructure, excelread) ليست واجهات تشغيلية: تحوي قيوداً مكتوبة يدوياً (if($i==203), row<=8789)؛ يجب فصلها عن قاعدة الكود الإنتاجية في الـ HIS الجديد.