lab_investigations فيه ١٧ حقل أساسي + جدول منفصل للنطاقات الطبيعية + جدول للـ panel membersresult_type): numeric, text, selection, formula, memo, file, culture, histopathologyunit نصي حر — ٢٠٠ تحليل بـ ٣٠ وحدة مختلفة (موجود تنوع كبير)lab_investigation_normal_ranges فيه: age_from, age_to, gender, normal_min/max, critical_low/high, unit, text_normalالباك اند مضبوط دلوقتي: name_en required و name_ar اختياري. لكن الفرونت يطلب name_ar بدل name_en.
المسار:
src/app/features/lis/investigations/lis-investigations.component.ts:507// الموجود:
name_ar: ['', Validators.required],
name: [''],
// المطلوب:
name_en: ['', Validators.required],
name_ar: [''],
name: [''], // داخلي — يتعبأ تلقائياً من name_en
كذلك: في الـ HTML، علامة * تنتقل من NAME_AR إلى NAME_EN.
الفرق المطلوب:
| الحقل | الغرض | مثال |
|---|---|---|
name_en | الاسم الداخلي للنظام (للبحث، الكود) | Complete Blood Count |
name_ar | الاسم الداخلي بالعربي | صورة دم كاملة |
display_name (جديد) | الاسم اللي يظهر في التقارير المطبوعة | CBC |
display_name_ar (جديد) | اسم العرض بالعربي | تعداد دم كامل |
الحل التقني:
add_display_name_to_lab_investigations تضيف العمودين على الجدول.$fillable + الـ Request + الـ Resource.display_name لو موجود، وإلا name_en.الفكرة: كل تحليل رقمي له إعداد منفصل لعدد الخانات العشرية (٠، ١، ٢، ٣، ٤). الافتراضي ٠. ولو المستخدم اختار ٢، النتائج تظهر بشكل 2.00 في الإدخال والعرض والطباعة.
الحل التقني:
decimal_places (smallint, default 0, range 0-4) على lab_investigations.$fillable + Request + Resource.result_type === 'numeric' أو 'formula'.p-inputNumber يستخدم minFractionDigits + maxFractionDigits = decimal_places.decimal_places خانة قبل التخزين.decimal_places.decimal_places.الوضع الحالي: حقل نصي حر. ٢٠٠ تحليل، ٣٠ وحدة فريدة. أكتر الوحدات استخداماً: mg/dL (22), % (15), ng/mL (11), U/L (9), إلخ.
الخيارات:
lab_units (id, code, name, sort_order)lab_investigations: unit_id (foreign key) + الإبقاء على unit string للتوافقp-select filterable + زر "+" لإضافة وحدة جديدة inlineالتوصية: خيار أ — لأنك ممكن تضيف وحدات بنفسك من شاشة بسيطة.
الوضع الحالي: age_from و age_to عبارة عن integer بدون وحدة. النظام يفترضها سنوات.
المطلوب: لكل صف نطاق، حقل وحدة (day/week/month/year) لكل من age_from و age_to.
الحل التقني:
lab_investigation_normal_ranges: age_from_unit (enum, default 'year') و age_to_unit (enum, default 'year').مثال: نطاق "من ٢٠ إلى ٣٠" يبقى:
الفكرة: لو التحليل نتيجته بـ "+" أو "-"، يكون "-" مثلاً هو الافتراضي. عند إدخال نتيجة جديدة، يُملأ تلقائياً وممكن المستخدم يغير.
الحل التقني:
default_value (string, nullable) على lab_investigations.text أو memo: input نصي حر.selection: dropdown يقرأ من selection_options.numeric أو formula: input عددي (نادر بس مفيد).الفكرة: تعليق بنصين (عربي وإنجليزي) موجود على التحليل نفسه، يظهر دائماً في تقرير النتيجة المطبوع (تحت قيمة النتيجة مباشرة).
الحل التقني:
static_comment و static_comment_ar (text, nullable) على lab_investigations.الفكرة: radio button بسيط في شاشة التحليل: "اطبع هذا التحليل في صفحة منفصلة". لو نعم، التحليل (مع التعليق الثابت تحته) يُطبع في صفحة لوحدها في تقرير النتائج.
الحل التقني:
print_on_separate_page (boolean, default false) على lab_investigations.LisReportPdfService):
doc.addPage().Schema::table('lab_investigations', function (Blueprint $table) {
// REQ 2 — display name
$table->string('display_name', 255)->nullable()->after('name_en');
$table->string('display_name_ar', 255)->nullable()->after('display_name');
// REQ 3 — decimal precision
$table->unsignedTinyInteger('decimal_places')->default(0)->after('reporting_unit');
// REQ 4 — unit FK (link to new lab_units table)
$table->unsignedBigInteger('unit_id')->nullable()->after('unit');
$table->foreign('unit_id')->references('id')->on('lab_units')->nullOnDelete();
// REQ 6 — default value
$table->string('default_value', 500)->nullable()->after('selection_options');
// REQ 7 — static comments
$table->text('static_comment')->nullable();
$table->text('static_comment_ar')->nullable();
// REQ 8 — print on separate page
$table->boolean('print_on_separate_page')->default(false);
});
Schema::table('lab_investigation_normal_ranges', function (Blueprint $table) {
// REQ 5 — age unit per range row
$table->string('age_from_unit', 10)->default('year')->after('age_from');
$table->string('age_to_unit', 10)->default('year')->after('age_to');
});
Schema::create('lab_units', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('company_id');
$table->string('code', 30); // mg/dL, %, etc
$table->string('name', 100); // Display name
$table->string('name_ar', 100)->nullable();
$table->boolean('is_active')->default(true);
$table->unsignedInteger('sort_order')->default(0);
$table->timestamps();
$table->softDeletes();
$table->unique(['company_id', 'code']);
});
| الترتيب | التاسك | الجانب | الأولوية | التقدير |
|---|---|---|---|---|
| B-1 | مهاجرة + موديل + سيدر لجدول lab_units | باك | عالٍ | ٣٠ د |
| B-2 | مهاجرة الأعمدة الجديدة على lab_investigations (display_name، decimal_places، unit_id، default_value، static_comment، print_on_separate_page) | باك | عالٍ | ٢٠ د |
| B-3 | مهاجرة age_from_unit و age_to_unit على lab_investigation_normal_ranges | باك | متوسط | ١٠ د |
| B-4 | تحديث Models، Requests، Resources بالحقول الجديدة | باك | عالٍ | ٣٠ د |
| B-5 | كنترولر + ريسورس + ريكوست لـ Units (CRUD) | باك | متوسط | ٢٠ د |
| B-6 | تقريب النتائج عند الحفظ حسب decimal_places | باك | حرج | ١٥ د |
| F-1 | تعديل name_en مطلوب + إضافة display_name fields في الـ form | فرونت | عالٍ | ١٥ د |
| F-2 | حقل decimal_places في الـ form (يظهر للـ numeric/formula بس) | فرونت | حرج | ١٥ د |
| F-3 | خدمة + موديل + شاشة بسيطة لإدارة الوحدات (CRUD) | فرونت | عالٍ | ٤٥ د |
| F-4 | تحويل حقل unit إلى p-select مع زر "+" inline | فرونت | عالٍ | ٢٠ د |
| F-5 | في tab الـ Ranges: select وحدة بجوار age_from و age_to | فرونت | عالٍ | ١٥ د |
| F-6 | حقل القيمة الافتراضية (يتأقلم حسب result_type) | فرونت | متوسط | ١٥ د |
| F-7 | حقلَي التعليق الثابت (عربي + إنجليزي) كـ textarea | فرونت | متوسط | ١٠ د |
| F-8 | radio/toggle لـ print_on_separate_page | فرونت | متوسط | ٥ د |
| F-9 | شاشة الـ Results: استخدام decimal_places في الإدخال + استخدام default_value كقيمة ابتدائية | فرونت | حرج | ٢٠ د |
| F-10 | خدمة الـ PDF: استخدام display_name + decimal_places + static_comment + print_on_separate_page | فرونت | حرج | ٤٠ د |
| F-11 | محرك الـ Formula: تقريب الناتج حسب decimal_places | فرونت | عالٍ | ١٠ د |
| F-12 | i18n: مفاتيح الترجمة الجديدة | فرونت | بسيط | ١٠ د |
الإجمالي: ~٥ ساعات شغل (٣٢٠ دقيقة).
local-deploy.sh للتأكد.has_static_comment (boolean, default false). لو true يظهر حقل التعليق ويُطبع.
decimal_places = 0. المستخدم يقدر يعدل اللي محتاجه.
year) لكل نطاقات العمر الموجودة والجديدة.
has_static_comment على الجدول (radio yes/no) — تنفيذ سهل.print_on_separate_page=true: ينقل لصفحة جديدة، يطبع التحليل، يطبع التعليق الثابت في آخر الصفحة (لو موجود)، الصفحة التالية تبدأ بعده.print_on_separate_page=false و has_static_comment=true: التحليل ثم التعليق الثابت ثم التحليل التالي على نفس الصفحة.Moon ERP — LIS Module | Add Investigation Revamp Plan | جاهز للمراجعة