تحليل ميزة تأجيل التحاليل — مرحلة التجميع
Deferred Tests Feature Analysis — Collection Worklist — 2026-04-05
1. ملخص الحالة الحالية
الميزة مطبقة بالكامل في مرحلة التجميع (Collection Worklist) باستخدام الـ API الأصلي للتأجيل.
الباك إند جاهز 100% — الفرونت إند يحتاج تحسينات بسيطة فقط.
مكتمل ✓
Backend API
POST /lis/samples/defer
ينشئ عينة جديدة بباركود منفصل للتحاليل المؤجلة
مكتمل ✓
حقول الموديل
is_deferred, deferred_reason, deferred_investigation_ids
حقول أصلية في جدول العينات
مكتمل ✓
واجهة التأجيل
ديالوج اختيار التحاليل + سبب التأجيل
زر التأجيل يظهر فقط عند وجود أنابيب معلقة
مكتمل ✓
الطباعة
printDeferredLabel() يطبع باركود منفصل
يظهر اسم العينة كـ "مؤجل" باللون البرتقالي
مكتمل ✓
الاستلام (Receiving)
يفصل التحاليل المؤجلة تلقائياً عند استلام العينة العادية
يتعرف على العينات المؤجلة ويعرض فقط تحاليلها
مكتمل ✓
التحقق (Validation)
يعرض التحاليل المؤجلة كـ "مؤجل - لم يُجمع"
يمنع إدخال نتائج للتحاليل غير المُجمعة
2. تدفق العمل الحالي
طلب جديد
Request Created
→
شاشة التجميع
Collection Worklist
→
زر "تأجيل تحليل"
Defer Test Button
→
اختيار التحاليل + السبب
Select Tests + Reason
→
POST /lis/samples/defer
Backend Creates Sample
→
باركود جديد
New Barcode Generated
طباعة الباركود
Print Label
→
أنبوب برتقالي (مؤجل)
Amber Tube (Deferred)
→
عند الجاهزية: يُجمع كعينة عادية
When Ready: Collect Normally
3. الملفات المتأثرة
| الملف |
الحالة |
الوصف |
| core/models/lis-sample.model.ts |
مكتمل |
3 حقول: is_deferred, deferred_reason, deferred_investigation_ids |
| lis/collection-worklist/collection-worklist.component.ts |
مكتمل |
ديالوج التأجيل + API call + إعادة تحميل + طباعة |
| lis/collection-worklist/collection-worklist.component.html |
مكتمل |
زر التأجيل + ديالوج الاختيار + شارة المؤجل + طباعة |
| lis/collection-worklist/collection-worklist.component.scss |
مكتمل |
تنسيق الأنبوب المؤجل (برتقالي) + الديالوج + الشارة |
| lis/specimen-receiving/specimen-receiving.component.ts |
مكتمل |
فصل التحاليل المؤجلة عند الاستلام |
| lis/validation-worklist/validation-worklist.component.ts |
مكتمل |
عرض "مؤجل - لم يُجمع" + منع إدخال النتائج |
| lis/dept-worklist/dept-worklist.component.ts |
مكتمل |
exclude_deferred=true يستبعد التحاليل المؤجلة من القسم |
| core/services/lis-sample.service.ts |
ناقص |
لا يوجد defer() method — الـ component يستدعي HTTP مباشرة |
4. تفاصيل التطبيق الحالي
4.1 واجهات البيانات (Interfaces)
// TubeInfo — يمثل أنبوب عينة واحد
interface TubeInfo {
sampleId: number;
barcode: string;
specimenName: string; // "مؤجل" للعينات المؤجلة
specimenColor: string; // "#f59e0b" (amber) للمؤجل
testCodes: string[];
investigationIds: number[];
isDeferred: boolean;
deferReason: string;
// ...
}
// DeferTestItem — عنصر في ديالوج التأجيل
interface DeferTestItem {
pivotId: number;
code: string;
name: string;
requiresFasting: boolean;
selected: boolean;
}
4.2 API الأصلي للتأجيل
POST /lis/samples/defer
// Request Body
{
"lab_request_id": 123,
"patient_id": 456,
"investigation_ids": [10, 15, 22],
"reason": "مؤجل - صيام"
}
// Response
{
"data": {
"barcode": "LB-2026-00456",
"id": 789,
"is_deferred": true,
"deferred_investigation_ids": [10, 15, 22],
"deferred_reason": "مؤجل - صيام"
}
}
4.3 منطق الفصل عند التجميع
// كيف يتم فصل الأنابيب
for each sample in request.samples:
if sample.is_deferred:
// أنبوب مؤجل → يعرض فقط التحاليل المؤجلة
tubeCodes = sample.deferred_investigation_ids → map to codes
color = "#f59e0b" (amber)
name = "مؤجل"
else if sample.is_external:
// أنبوب خارجي → فقط التحاليل المُحالة
tubeCodes = outsourced investigations
color = "#9333ea" (purple)
else:
// أنبوب عادي → كل التحاليل ما عدا المؤجلة والخارجية
tubeCodes = all - deferred - outsourced
color = specimen_type.color_code
// حساب "تم التجميع"
allCollected = NO pending deferred tubes
AND all non-deferred non-rejected tubes are collected
4.4 منطق ديالوج التأجيل
openDeferDialog(card):
1. جمع الـ IDs المؤجلة مسبقاً من الأنابيب الموجودة
2. بناء قائمة التحاليل (باستثناء المؤجل والمُجمّع)
3. اختيار تحاليل الصيام تلقائياً (pre-select fasting tests)
4. فتح الديالوج
confirmDefer():
1. التحقق من وجود اختيار واحد على الأقل
2. إرسال POST /lis/samples/defer
3. عند النجاح: عرض رسالة بالباركود الجديد
4. إعادة تحميل البيانات
5. عند الفشل: عرض رسالة خطأ
5. التحسينات المطلوبة
5.1 نقل الـ API Call إلى الـ Service
حالياً confirmDefer() يستدعي HttpClient مباشرة بدلاً من استخدام LisSampleService.
الملف: core/services/lis-sample.service.ts
// إضافة method جديدة
defer(payload: {
lab_request_id: number;
patient_id: number;
investigation_ids: number[];
reason: string;
}): Observable<any> {
return this.http.post(`${environment.apiUrl}/lis/samples/defer`, payload);
}
ثم في collection-worklist.component.ts استبدال:
// قبل (مباشر)
this.http.post(`${environment.apiUrl}/lis/samples/defer`, {...})
// بعد (عبر الـ service)
this.sampleSvc.defer({...})
5.2 أسباب تأجيل جاهزة (Predefined Reasons)
حالياً المستخدم يكتب السبب يدوياً أو يتم استخدام "مؤجل" كافتراضي.
إضافة قائمة أسباب شائعة:
| الكود | العربي | English |
| fasting | المريض غير صائم | Patient not fasting |
| insufficient | كمية العينة غير كافية | Insufficient sample |
| patient_request | بطلب المريض | Patient request |
| specimen_type | نوع عينة مختلف مطلوب | Different specimen required |
| scheduling | تحليل مؤقت/مجدول | Timed/scheduled test |
| other | سبب آخر | Other reason |
مع إمكانية كتابة سبب مخصص عند اختيار "سبب آخر".
5.3 طباعة تلقائية بعد التأجيل
حالياً بعد تأجيل التحاليل، يحتاج المستخدم للضغط على زر الطباعة يدوياً.
التحسين: طباعة الباركود تلقائياً بعد نجاح التأجيل مباشرة.
// في confirmDefer() بعد النجاح
if (res?.data) {
// ... رسالة النجاح ...
// طباعة تلقائية
const label: LabelDataV2 = {
barcode: res.data.barcode,
patientNameAr: card.patientNameAr,
patientNameEn: card.patientNameEn,
// ...
};
this.barcodeSvc.printLabelsV2([label]);
this.loadData();
}
5.4 عرض تاريخ التأجيل
إضافة tooltip أو سطر صغير يعرض:
- تاريخ ووقت التأجيل
- من قام بالتأجيل (اسم الموظف)
- سبب التأجيل
هذا يساعد في المتابعة ومعرفة لماذا تم التأجيل.
5.5 تنبيه للعينات المؤجلة لفترة طويلة
إذا مرّ أكثر من X ساعات على تأجيل العينة ولم تُجمع بعد، يظهر تنبيه في الواجهة.
يمكن حسابه من created_at للعينة المؤجلة مقارنة بالوقت الحالي.
6. مقارنة: التجميع vs الاستلام
| الميزة |
التجميع (Collection) |
الاستلام (Receiving) |
| زر التأجيل |
موجود ✓ |
غير موجود ✗ |
| ديالوج اختيار التحاليل |
موجود ✓ |
غير موجود ✗ |
| فصل التحاليل المؤجلة |
تلقائي ✓ |
تلقائي ✓ |
| باركود منفصل |
يُنشأ عند التأجيل ✓ |
— (لا يُنشئ تأجيل) |
| طباعة الباركود |
زر طباعة مخصص ✓ |
— (لا يُنشئ تأجيل) |
| استبعاد المؤجل من العادي |
تلقائي ✓ |
تلقائي ✓ |
| التعرف على عينة مؤجلة عند المسح |
— |
يعرض فقط تحاليلها ✓ |
الاستلام لا يحتاج لزر تأجيل لأن التأجيل يتم في مرحلة التجميع. الاستلام فقط يستقبل العينات (سواء عادية أو مؤجلة) ويعرض التحاليل المناسبة لكل واحدة.
7. خطة التنفيذ
| # |
المهمة |
الأولوية |
الوقت المقدر |
الملفات |
| 1 |
إضافة defer() للـ Service |
HIGH |
5 دقائق |
lis-sample.service.ts + collection-worklist.component.ts |
| 2 |
أسباب تأجيل جاهزة (Dropdown) |
MEDIUM |
15 دقيقة |
collection-worklist.component.ts/html |
| 3 |
طباعة تلقائية بعد التأجيل |
MEDIUM |
10 دقائق |
collection-worklist.component.ts |
| 4 |
عرض تاريخ التأجيل + المسؤول |
LOW |
20 دقيقة |
collection-worklist.component.ts/html |
| 5 |
تنبيه العينات المؤجلة طويلاً |
LOW |
15 دقيقة |
collection-worklist.component.ts/html/scss |
8. الخلاصة
الوضع الحالي: ميزة التأجيل مطبقة بالكامل وتعمل كالتالي:
- ✅ زر "تأجيل تحليل" في شاشة التجميع
- ✅ ديالوج اختيار التحاليل المراد تأجيلها مع اختيار تلقائي لتحاليل الصيام
- ✅ إنشاء عينة جديدة بباركود منفصل عبر API أصلي
- ✅ عرض الأنبوب المؤجل باللون البرتقالي مع شارة "مؤجل"
- ✅ طباعة باركود العينة المؤجلة
- ✅ فصل التحاليل المؤجلة عن العادية في الاستلام والتحقق
- ✅ منع إدخال نتائج للتحاليل المؤجلة غير المجمعة
التحسينات المقترحة (اختيارية — النظام يعمل بدونها):
- 🔸 نقل HTTP call للـ Service (تحسين معماري)
- 🔸 أسباب تأجيل جاهزة (تحسين UX)
- 🔸 طباعة تلقائية بعد التأجيل (تسريع العمل)
- 🔹 عرض سجل التأجيل (تتبع)
- 🔹 تنبيه العينات المتأخرة (مراقبة)