📋 LIS Structural Refactor — Detailed Task List
Reference for Codex review. كل مهمة فيها: file path دقيق، LOC الحالي، اللي يتعمل، شرط القبول (acceptance criteria). الـ surveys بنيت بناء على read فعلي للملفات.
A. ملخص الـ Code Inventory
A.1 Backend (10 controllers + 8 models + 3 services + 1 listener)
| الملف | LOC | الأثر |
| Http/Controllers/LabSampleController.php | 562 | HIGH — defer/recollect/aliquot logic |
| Http/Controllers/LabRequestController.php | 1,008 | MEDIUM — store + index counters |
| Http/Controllers/LabResultController.php | 709 | MEDIUM — retest/correct/retract |
| Http/Controllers/LabRequestInvestigationController.php | 188 | MEDIUM — bulk transitions |
| Http/Controllers/LabSectionKanbanController.php | 250 | MEDIUM — kanban shape |
| Http/Controllers/LabExternalLabReferralController.php | ~600 | MEDIUM — TAT + assigned_to |
| Http/Controllers/LabMachineResultController.php | 245 | LOW — link pivot on match |
| Http/Controllers/LabRejectionReasonController.php | 112 | DONE — no further changes |
| Services/LabSampleService.php | 450 | CRITICAL — collect/deliver/reject/recollect |
| Services/LabResultService.php | ~250 | MEDIUM — retest creates pivot rows |
| Listeners/GenerateResultsOnSampleReceived.php | 136 | CRITICAL — replace section inference |
| Models/LabSample.php | 155 | HIGH — new relation |
| Models/LabResult.php | 143 | MEDIUM — entry_source + machine_id + comments |
| Models/LabInvestigation.php | 100+ | MEDIUM — tat_hours |
| Models/LabExternalLabPricing.php | 73 | MEDIUM — tat_hours |
| Models/LabExternalLabReferral.php | 99 | MEDIUM — assigned_to_user_id |
| Enums/SampleStatus.php | 35 | NONE |
| Enums/ResultStatus.php | 14 | NONE |
| routes/api.php | ~400 | MEDIUM — new bulk endpoint + unpublish |
A.2 Frontend (5 screens + 6 services + 5 models)
| الملف | LOC | الأثر |
| features/lis/collection-worklist/collection-worklist.component.ts | 1,513 | HIGH — tubes builder |
| features/lis/dept-worklist/dept-worklist.component.ts | 1,260 | HIGH — actions + per-test status |
| features/lis/validation-worklist/validation-worklist.component.ts | 1,892 | HIGH — bulk ops + history columns |
| features/lis/kanban/lis-kanban.component.ts | 1,490 | MEDIUM — legacy kanban; لو routed يبقى نعدله، لو غير مستخدم نمسحه |
| features/lis/referrals/lis-referrals.component.ts | ~700 | MEDIUM — TAT col + assigned_to |
| features/lis/requests/lis-requests.component.ts | ~750 | LOW — minor: read counts from new field |
| features/lis/sample-reasons/lis-sample-reasons.component.ts | ~250 | DONE |
| features/lis/samples/lis-samples.component.ts | 1,243 | MEDIUM — fallback path (might delete) |
| features/lis/lis-layout/lis-layout.component.ts | ~400 | MEDIUM — nav entry للـ Reception |
| core/services/lis-sample.service.ts | 154 | MEDIUM — bulk action methods |
| core/services/lis-result.service.ts | 189 | MEDIUM — bulk actions |
| core/services/lis-utils.ts | 190 | LOW — eventually remove |
| core/services/lis-barcode-label.service.ts | 269 | LOW — show per-test status badge |
| core/models/lis-sample.model.ts | 48 | HIGH — add investigations[] |
| core/models/lis-result.model.ts | 84 | MEDIUM — entry_source + comments |
| core/models/lis-investigation.model.ts | ~70 | LOW — tat_hours field |
| core/models/lis-referral.model.ts | ~60 | MEDIUM — TAT + assigned_to |
B. Schema Changes (Migrations)
B.1 New Tables (2)
Migration M1: create_lab_sample_investigations_table
Schema::create('lab_sample_investigations', function (Blueprint $t) {
$t->id();
$t->foreignId('company_id')->constrained()->cascadeOnDelete();
$t->foreignId('lab_sample_id')->constrained('lab_samples')->cascadeOnDelete();
$t->foreignId('lab_investigation_id')->constrained('lab_investigations');
$t->foreignId('lab_request_investigation_id')->nullable()
->constrained('lab_request_investigations')->nullOnDelete();
$t->foreignId('lab_request_id')->constrained('lab_requests'); // denormalized
$t->string('status', 30)->index();
// pending, collected, received, in_progress, result_entered, validated,
// released, printed, published, deferred, rejected, cancelled,
// outsourced, retracted
$t->foreignId('lab_external_lab_id')->nullable()
->constrained('lab_external_labs')->nullOnDelete();
$t->timestamp('external_send_at')->nullable();
$t->timestamp('external_received_at')->nullable();
$t->foreignId('assigned_to_user_id')->nullable()
->constrained('users')->nullOnDelete();
$t->unsignedSmallInteger('retest_count')->default(0);
$t->timestamps();
$t->softDeletes();
$t->unique(['lab_sample_id', 'lab_investigation_id', 'deleted_at'],
'lab_sample_inv_unique');
$t->index(['company_id', 'lab_request_id', 'status']);
$t->index(['lab_investigation_id', 'status']);
});
Migration M2: create_lab_sample_investigation_logs_table
Schema::create('lab_sample_investigation_logs', function (Blueprint $t) {
$t->id();
$t->foreignId('company_id')->constrained();
$t->foreignId('lab_sample_investigation_id')->nullable()
->constrained('lab_sample_investigations')->nullOnDelete();
$t->foreignId('lab_sample_id')->constrained('lab_samples');
$t->foreignId('lab_investigation_id')->constrained('lab_investigations');
$t->string('action', 30);
// created, collected, received, started, result_entered, validated,
// released, printed, published, deferred, cancelled, outsourced,
// rejected, recollected, rerun, retracted, assigned, received_back
$t->string('from_status', 30)->nullable();
$t->string('to_status', 30)->nullable();
$t->string('reason_code', 30)->nullable();
$t->text('reason_text')->nullable();
$t->text('result_value_before')->nullable(); // for rerun
$t->json('meta')->nullable();
$t->foreignId('user_id')->nullable()->constrained();
$t->string('ip_address', 45)->nullable();
$t->string('user_agent', 255)->nullable();
$t->timestamp('created_at')->useCurrent();
$t->index(['lab_sample_investigation_id', 'created_at']);
$t->index(['lab_sample_id', 'created_at']);
$t->index(['lab_investigation_id', 'created_at']);
});
B.2 ALTER existing tables (5)
| الجدول | الإضافة | Migration name |
| lab_investigations |
tat_hours int nullable |
add_tat_hours_to_lab_investigations |
| lab_external_lab_pricing |
tat_hours int nullable |
add_tat_hours_to_lab_external_lab_pricing |
| lab_external_lab_referrals |
assigned_to_user_id FK nullable |
add_assigned_to_user_id_to_lab_external_lab_referrals |
| lab_results |
entry_source enum
printable_comment text
internal_note text
defer_comment text
machine_id FK
raw_data json
|
add_entry_source_and_comments_to_lab_results |
| lab_samples |
(Phase 5) drop is_deferred, deferred_investigation_ids, deferred_reason
|
drop_legacy_deferred_columns_from_lab_samples |
B.3 Truncate Plan (Dev only — test data)
الـ catalog tables (
lab_investigations,
lab_investigation_categories,
lab_sections,
lab_specimen_types,
lab_patients,
lab_doctors,
lab_external_labs,
lab_external_lab_pricing)
تفضل كما هي.
الـ tables اللي بنمسحها:
lab_requests
lab_request_investigations
lab_samples
lab_sample_section_processing
lab_results
lab_result_audit_logs
lab_machine_results
lab_external_lab_referrals + tests pivot
lab_invoices, lab_payments, lab_insurance_invoices (المرتبطة بـ requests)
C. Backend Tasks (٢٢ task)
Phase 1: Schema + Models (BE-1 to BE-7)
BE-1NEW · Schema
كتابة الـ migrations الـ ٢ الجديدة (M1, M2) + الـ ٤ ALTERs.
- إنشاء Modules/LIS/database/migrations/2026_05_27_000001_create_lab_sample_investigations_table.php
- إنشاء ..._000002_create_lab_sample_investigation_logs_table.php
- إنشاء ..._000003_add_tat_hours_to_lab_investigations.php
- إنشاء ..._000004_add_tat_hours_to_lab_external_lab_pricing.php
- إنشاء ..._000005_add_assigned_to_user_id_to_lab_external_lab_referrals.php
- إنشاء ..._000006_add_entry_source_and_comments_to_lab_results.php
php artisan migrate ينجح بدون warnings؛ الجداول والأعمدة موجودة بالـ شكل الموصوف.
BE-2NEW · Model
إنشاء model
LabSampleInvestigation + factory + seed-ready.
- Modules/LIS/app/Models/LabSampleInvestigation.php
- $fillable كامل + casts (status as string enum, meta as array, retest_count int)
- Relations:
sample(), investigation(), requestInvestigation(), request(), externalLab(), assignedTo(), logs()
- Scope helpers:
scopeActive() (غير cancelled/rejected/deferred)، scopeDeferred()، scopeOutsourced()
عمل LabSampleInvestigation::factory()->create() ينجح؛ الـ relations كلها تشتغل.
BE-3NEW · Model
إنشاء model
LabSampleInvestigationLog.
- Modules/LIS/app/Models/LabSampleInvestigationLog.php
- $fillable + casts (meta json, created_at)
- Relations:
sampleInvestigation(), sample(), investigation(), user()
- No
updated_at (immutable)
log row بيتعمل بـ LabSampleInvestigationLog::create([...]) ومرتبط صح.
BE-4NEW · Enum
إنشاء enum
SampleInvestigationStatus.
- Modules/LIS/app/Enums/SampleInvestigationStatus.php
- cases: pending, collected, received, in_progress, result_entered, validated, released, printed, published, deferred, rejected, cancelled, outsourced, retracted
- Helper methods:
canTransitionTo(SampleInvestigationStatus): bool, isTerminal(): bool, isActionable(): bool
enum يحدد الـ transitions الصحيحة (راجع State Machine في blueprint).
BE-5NEW · Enum
إنشاء enum
SampleInvestigationAction للـ logs.
- Modules/LIS/app/Enums/SampleInvestigationAction.php
- cases: created, collected, received, started, result_entered, validated, released, printed, published, deferred, cancelled, outsourced, rejected, recollected, rerun, retracted, assigned, received_back, unpublished
enum مستخدم في الـ logs writer service.
BE-6HIGH · Model edit
تعديل
LabSample model.
- Modules/LIS/app/Models/LabSample.php
- إضافة
investigations(): hasMany(LabSampleInvestigation)
- إضافة
activeInvestigations(): hasMany scoped to non-terminal
- إضافة
investigationLogs(): hasManyThrough
- (لا نشيل
is_deferred/deferred_investigation_ids لسة — Phase 5)
eager loading $sample->load('investigations.investigation') يشتغل.
BE-7MED · Model edit
تعديل
LabResult,
LabInvestigation,
LabExternalLabPricing,
LabExternalLabReferral models.
- Modules/LIS/app/Models/LabResult.php — إضافة
entry_source, printable_comment, internal_note, defer_comment, machine_id, raw_data للـ $fillable + cast raw_data as array
- Modules/LIS/app/Models/LabInvestigation.php — إضافة
tat_hours
- Modules/LIS/app/Models/LabExternalLabPricing.php — إضافة
tat_hours
- Modules/LIS/app/Models/LabExternalLabReferral.php — إضافة
assigned_to_user_id + relation assignedTo()
PHPUnit tests للـ models تنجح؛ الـ casts صح.
Phase 2: Writers (BE-8 to BE-16)
BE-8CRIT · Writer Service
كتابة
SampleInvestigationService مركزي.
- Modules/LIS/app/Services/SampleInvestigationService.php (NEW)
- Methods:
createForRequest(LabRequest, LabSample) — لما sample بيتعمل، يولّد rows لكل investigation تابعة (panel members ك separate rows)
transition($sampleInvestigationId, $action, $reason = null) — يحدّث status + يكتب log
moveTo(LabSample $target, $ids, $status, $reason) — ينقل rows من sample لآخر (used by defer/cancel/send-out/reject)
bulkTransition(array $ids, $action)
logAction($sampleInvestigationId, $action, $meta = [])
- كل method داخل DB transaction
- كل operation تكتب log في
lab_sample_investigation_logs
unit tests تغطي defer/cancel/send-out/reject/recollect transitions.
BE-9CRIT · Listener refactor
إعادة كتابة
GenerateResultsOnSampleReceived listener.
- Modules/LIS/app/Listeners/GenerateResultsOnSampleReceived.php (136 LOC حالياً)
- بدلاً من فلترة
LabRequestInvestigation بـ section/specimen، نقرأ مباشرة من $sample->investigations
- لكل row في
$sample->investigations اللي بـ status=received → ينشأ LabResult
- تجاهل rows اللي status
deferred/cancelled/outsourced/rejected
عند delivery لـ sample فيه TG deferred، النتيجة بتتعمل بس للـ tests الفعلية (مش TG).
BE-10CRIT · Controller edit
تعديل
LabRequestController::store().
- Modules/LIS/app/Http/Controllers/LabRequestController.php (line 146-404)
- بعد إنشاء
LabRequestInvestigation rows + الـ initial sample(s)، يستدعي SampleInvestigationService::createForRequest() ليولّد الـ pivot rows
- لكل panel: يولّد row للـ parent + rows للـ members كل واحدة بـ
investigation_id فردي
عمل request جديد بـ Lipid Panel → الـ sample يبقى عنده ٦ rows في lab_sample_investigations (LIPID + 5 members).
BE-11CRIT · Controller edit
إعادة كتابة
LabSampleController::defer().
- Modules/LIS/app/Http/Controllers/LabSampleController.php (line 513-561)
- بدلاً من إنشاء sample جديد بـ is_deferred=true + JSON، يستخدم
SampleInvestigationService::moveTo() ينقل الـ rows لـ sample جديد status=deferred
- الـ sample القديم يفضل كما هو لو في باقي tests عليه
- الـ payload الجديد:
{ source_sample_id, investigation_ids[], reason_code?, reason_text }
defer لـ TG من Lipid Panel → row واحد بس بـ investigation_id=16 ينتقل لـ deferred sample جديد.
BE-12CRIT · Controller edit
إعادة كتابة
LabSampleService::recollect().
- Modules/LIS/app/Services/LabSampleService.php (current line 130-220)
- ينشئ sample pending جديد، ينقل الـ rows من deferred sample بـ
moveTo($newSample, $ids, 'pending')
- لو الـ deferred sample بقى فاضي → soft delete
- يضيف logs بـ action=recollected
recollect لـ TG → sample جديد فيه row واحد TG بـ status=pending.
BE-13HIGH · New endpoints
إضافة endpoints جديدة في
LabSampleController.
POST /samples/{id}/cancel — يقبل investigation_ids + reason، ينقل rows لـ sample جديد بـ status=cancelled
POST /samples/{id}/send-out — يقبل investigation_ids + external_lab_id، ينقل rows لـ sample جديد بـ status=outsourced + يربط بالـ referral
- الـ routes تنضاف في Modules/LIS/routes/api.php
curl tests للـ endpoints الجديدة تشتغل.
BE-14HIGH · Service edit
تعديل
LabSampleService::aliquot().
- Modules/LIS/app/Services/LabSampleService.php
- بدلاً من ما يحسب الـ investigations من section على الـ pivots، يقرأ من
$parent->investigations ويقسمهم على الـ children بـ moveTo()
- لكل child sample، الـ pivot rows تنتقل من parent
aliquot لـ sample فيها 6 tests على 3 sections → 3 children كل واحد بياخد rows بتاعت section بتاعه.
BE-15HIGH · Service edit
تعديل
LabSampleService::collect() و
deliver() و
reject().
- collect: كل rows pending على الـ sample → collected + log
- deliver: rows collected → received + log
- reject (في الاستقبال): يقبل investigation_ids → rows → rejected (مش بنقل لـ sample جديد، rejection على نفس الـ sample) + log
كل status transition يظهر في lab_sample_investigation_logs.
BE-16HIGH · Result actions
تعديل
LabResultController +
LabResultService.
- Modules/LIS/app/Http/Controllers/LabResultController.php
enter(): عند إدخال نتيجة، يحدّث الـ pivot row → result_entered + يضع entry_source + log
retest(): ينشئ نسخة جديدة + الـ pivot row → retracted (للقديم) + result_entered (للجديد) + log فيه القيمة القديمة
- NEW:
retract()/unpublish(): الـ pivot row → retracted + log
- NEW endpoint:
POST /results/bulk-action — يقبل action + result_ids[] + يحدّث الـ pivots
unpublish لـ result بعد published → row يبقى status=retracted؛ يقدر يعمل rerun/cancel/send-out بعد كده.
Phase 3: Readers + Resources (BE-17 to BE-22)
BE-17HIGH · Resource
تعديل
LabSampleResource.
- Modules/LIS/app/Http/Resources/LabSampleResource.php
- إضافة
investigations array (whenLoaded) فيها: id, investigation_id, code, name, name_ar, status, external_lab_id, retest_count
- الـ FE يقرأ من هنا مباشرة بدون inference
GET /samples/{id} يرجع investigations: [...] بشكل كامل.
BE-18MED · Resource
تعديل
LabSectionKanbanController.
- Modules/LIS/app/Http/Controllers/LabSectionKanbanController.php (250 LOC)
- الـ kanban response بقى يقرأ الـ investigations من
sample.investigations بدل ما يحسبهم
- الـ filter بـ section بقى على
investigation.lab_section_id
GET /sections/{id}/kanban يرجع كل card فيها list الـ tests الفعلية على الـ sample.
BE-19MED · Resource
تعديل
LabExternalLabReferralResource + endpoints.
- إضافة
tat_hours (من pricing) و assigned_to للـ resource
- endpoint جديد PATCH
/referrals/{id}/assign
FE referrals يعرض TAT + Assigned To.
BE-20MED · Bulk endpoint
endpoint جديد
POST /sample-investigations/bulk-action.
- controller جديد: SampleInvestigationController.php
- actions: validate, release, print, publish, unpublish, rerun, send_out, cancel, defer
- payload:
{ action, sample_investigation_ids[], reason?, external_lab_id? }
- response:
{ succeeded: int, failed: int, errors: [] }
- يستخدم
SampleInvestigationService::bulkTransition()
bulk validate لـ ٢٤ row في request واحد ينجح في transaction واحد.
BE-21MED · Filter endpoint
endpoint جديد
GET /sample-investigations للـ smart search.
- filters:
investigation_id, lab_section_id, status, date_from, date_to, entry_source, patient_id, request_id, flag
- eager load: investigation, sample (with patient/request), result
- pagination + listAll-able
filter بـ investigation_id=16 + date=today يرجع كل الـ TG النهارده.
BE-22LOW · Machine link
تعديل
LabMachineResultController::store().
- عند match تلقائي، يحدّث pivot row → result_entered + machine_id + raw_data في الـ result
- الـ status بقى result_entered مباشرة (مش matched منفصل) — الـ machine = manual + metadata
machine بتبعت result → row pivot يبقى result_entered + lab_result جديد بـ entry_source=machine.
D. Frontend Tasks (٢٤ task)
Phase 4.A: Models + Services (FE-1 to FE-6)
FE-1NEW · Model
إنشاء
LisSampleInvestigation model.
- core/models/lis-sample-investigation.model.ts (NEW)
- interface: id, sample_id, investigation_id, investigation (nested code/name), status, lab_external_lab_id, assigned_to_user_id, retest_count, created_at, updated_at
model imported في الـ sample service.
FE-2HIGH · Model edit
تعديل
LisSample model.
- core/models/lis-sample.model.ts
- إضافة
investigations?: LisSampleInvestigation[]
- (الـ legacy
is_deferred/deferred_investigation_ids يفضلوا للـ backward compat)
tsc ينجح؛ types صح.
FE-3MED · Service
إنشاء
LisSampleInvestigationService.
- core/services/lis-sample-investigation.service.ts (NEW)
- methods:
list(filters) — GET /sample-investigations مع filters
listAll(filters)
bulkAction(payload) — POST /sample-investigations/bulk-action
updateStatus(id, status, reason?)
unit test باستخدام HttpTestingController.
FE-4MED · Service edit
تعديل
LisSampleService.
- core/services/lis-sample.service.ts (154 LOC)
- إضافة:
cancel(payload), sendOut(payload)
- تعديل defer للـ payload الجديد (source_sample_id + investigation_ids[])
- الـ recollect: نشيل الـ PUT workaround (لأن الـ BE هيخزنها صح)
callers في collection-worklist تستخدم الـ methods الجديدة.
FE-5MED · Service edit
تعديل
LisResultService.
- core/services/lis-result.service.ts (189 LOC)
- إضافة:
unpublish(id), bulkAction(payload)
- existing methods تظل كما هي
قابل للـ unit tests.
FE-6LOW · Models update
تعديل models أخرى صغيرة.
- core/models/lis-result.model.ts — إضافة
entry_source, printable_comment, internal_note, defer_comment, machine_id
- core/models/lis-investigation.model.ts — إضافة
tat_hours?
- core/models/lis-referral.model.ts — إضافة
tat_hours?, assigned_to_user_id?, assigned_to?
tsc clean.
Phase 4.B: Collection Worklist (FE-7 to FE-9)
FE-7CRIT · Component refactor
إعادة كتابة tube builder في
collection-worklist.
- features/lis/collection-worklist/collection-worklist.component.ts (1,513 LOC)
- الـ
loadData() يجلب الـ sample.investigations
- الـ
tubes تبقى مبنية من sample.investigations مباشرة (لا filterBillableTests)
- الـ test codes في كل tube = investigation codes الفعلية
- الـ defer dialog يستخدم
sample.investigations بدلاً من card.investigations لـ panel structure
tube مع TG deferred → الـ display يعرض TG فقط، مش LIPID.
FE-8HIGH · UI tabs
إضافة
Cancelled و
Sent Out tabs في collection-worklist.
- الـ tabs بنفس النمط بتاع Deferred
- كل tab فيه recollect/recreate actions حسب الـ status
4 tabs (Pending, Deferred, Cancelled, Sent Out, History) شغّالة.
FE-9HIGH · Defer dialog
تحويل defer dialog إلى shared component يستخدم في Defer/Cancel/Send Out/Reject.
- features/lis/shared/test-action-dialog/test-action-dialog.component.ts (NEW)
- inputs: mode ('defer'|'cancel'|'send_out'|'reject'), sample, investigations (نسخة من panel structure)
- output: confirmed payload
نفس الـ component يستخدم في 3 شاشات مع modes مختلفة.
Phase 4.C: Reception Screen (FE-10 to FE-11)
FE-10NEW · Screen
شاشة جديدة
/lab/reception.
- features/lis/reception/reception.component.ts (NEW)
- tabs: To Receive (collected) / Rejected / History
- scan barcode → يلاقي الـ sample → highlight
- actions per sample: Receive, Reject (shared dialog)
scan ينجح؛ receive يحدث الـ status لكل rows على الـ sample.
FE-11MED · Routing + Nav
إضافة الـ route والـ nav entry.
- features/lis/lis-standalone.routes.ts + src/app/app.routes.ts
- features/lis/lis-layout/lis-layout.component.ts — nav entry
- i18n keys
/lab/reception accessible.
Phase 4.D: Worklist + Validation (FE-12 to FE-17)
FE-12HIGH · Worklist refactor
تحديث
dept-worklist ليقرأ من sample_investigations.
- features/lis/dept-worklist/dept-worklist.component.ts (1,260 LOC)
- الـ rows تبنى من
GET /sample-investigations?status=received,in_progress
- actions: Start, Enter Result, Defer (shared), Cancel, Send Out
المعمل يشتغل بـ per-test workflow بدل sample-level.
FE-13HIGH · Rerun action
إضافة Rerun button في dept-worklist + validation.
- زرار
↻ Rerun على كل test في status result_entered/validated/released
- على click: POST /results/{id}/retest + يحدّث الـ UI
- badge
↻×N يظهر على الـ test card
Rerun يحفظ القيمة القديمة في log + يعرض history.
FE-14HIGH · Validation refactor
تحديث
validation-worklist.
- features/lis/validation-worklist/validation-worklist.component.ts (1,892 LOC)
- الـ rows تبنى من sample_investigations
- عمودين history جدد: Sample History (rerun count + previous values) و Patient History (last result for same test)
columns واضحة + قابلة للسورت.
FE-15HIGH · Smart Search bar
filters متعددة في validation + worklist.
- shared component: features/lis/shared/test-filter-bar/test-filter-bar.component.ts (NEW)
- filters: test, section, status, date_range, entry_source, flag
- output: filter object يتم استخدامه في GET sample-investigations
filter "CBC + Today" يرجع الكل صح.
FE-16HIGH · Bulk action bar
multi-select + bulk action bar.
- shared component: features/lis/shared/bulk-action-bar/bulk-action-bar.component.ts (NEW)
- actions: Validate, Release, Print, Publish, Unpublish, Rerun, Send Out, Cancel, Defer
- POST /sample-investigations/bulk-action + يعرض counts نجاح/فشل
bulk validate لـ 20 rows → toast {succeeded: 20}.
FE-17HIGH · Unpublish
زرار Unpublish في validation.
- على tests في status published → زرار
↶ Unpublish
- POST /results/{id}/retract
- بعد unpublish → كل الـ actions الباقية متاحة
unpublish ينجح؛ النتيجة تختفي من portal فوراً.
Phase 4.E: Referrals + Other (FE-18 to FE-24)
FE-18MED · Referrals
إضافة TAT + Assigned To في referrals.
- features/lis/referrals/lis-referrals.component.ts
- عمود TAT + Assigned To
- زرار Assign + dialog
referrals page يعرض TAT المتوقع + المسؤول.
FE-19MED · TAT in investigations
إضافة tat_hours في investigations form.
- features/lis/investigations/lis-investigations.component.html
- input number ساعات
save + load يحفظ tat_hours.
FE-20MED · TAT in external pricing
إضافة tat_hours per external-lab pricing.
- features/lis/external-labs/lis-external-labs.component.html
save + load يحفظ tat_hours بـ external pricing.
FE-21LOW · Comments UI
3 comment fields في dept-worklist + validation.
- tabbed input: Printable / Internal / (defer reason يـ read-only)
save لكل field على حدا.
FE-22LOW · Barcode labels
عرض per-test status على الباركود.
- core/services/lis-barcode-label.service.ts
- لو الـ sample فيها deferred tests، badge "PARTIAL" على الـ label
label يعكس الـ state.
FE-23LOW · Cleanup utilities
حذف
filterBillableTests/
buildPanelMemberMap بعد ما الـ callers يتحولوا.
- core/services/lis-utils.ts
- تأكد من إن مفيش caller
grep لـ filterBillableTests يرجع 0 hits.
FE-24LOW · Cleanup screens
حذف
lis-samples.component.ts و
lis-kanban.component.ts لو مش routed.
- verify routes أولاً
- delete + update routes
build clean بدون unused imports.
E. Order of Execution
- BE-1 → BE-7 (Schema + Models) — Phase 1
- Truncate dev DB + run migrations
- BE-8 → BE-16 (Writers) — Phase 2 — defer/cancel/send-out أولاً، aliquot ثانياً
- BE-17 → BE-22 (Readers + bulk endpoints) — Phase 3
- FE-1 → FE-6 (Models + Services) — Phase 4.A
- FE-7 → FE-9 (Collection) — Phase 4.B
- FE-10 → FE-11 (Reception) — Phase 4.C
- FE-12 → FE-17 (Worklist + Validation) — Phase 4.D
- FE-18 → FE-24 (Referrals + Cleanup) — Phase 4.E
- End-to-end test: defer TG → recollect → collect → receive → start → enter result → validate → release → publish → unpublish → rerun → publish
- Cleanup (legacy columns + utilities) — Phase 5
F. Risk Register
| الخطر | التأثير | المعالجة |
| الـ Kanban controller شاشة legacy + شاشة جديدة | MED | تأكيد أي شاشة الـ user بيستخدمها فعلاً قبل تعديل |
| الـ GenerateResultsOnSampleReceived بيحسب section logic معقد | HIGH | اعادة كتابة كامل + unit tests على edge cases (panel partial defer) |
| الـ aliquot logic يفترض كل tests القسم في sample واحد | MED | الـ refactor بيخلي الـ aliquot ينقل rows من parent — يبقى الـ logic مبسّط |
| الـ Machine integration بيستخدم sample_id+investigation_id direct | LOW | عند match، يحدّث pivot row + ينشئ lab_result |
| الـ Referrals بتربط بـ sample كامل دلوقتي | MED | لازم نضيف investigation_id في الـ referral table أو يستخدم pivot rows اللي status=outsourced |
| الـ user testing على prod = dev backend (مش Ahmed's prod) | LOW | التحقق من config.json + إعطاء الـ user URL واضح |
| الـ build size في FE يزيد بسبب الـ shared components | LOW | code splitting إذا لزم |
| FE caching يخلي الـ user يشوف JS قديم | MED | hash في chunk names بيمنع ده، بس index.html لازم not-cached |
G. Estimated effort
| Phase | BE tasks | FE tasks | Est. days |
| 1. Schema + Models | 7 | — | 1 |
| 2. BE Writers | 9 | — | 2 |
| 3. BE Readers | 6 | — | 1 |
| 4.A FE Models + Services | — | 6 | 0.5 |
| 4.B FE Collection | — | 3 | 1 |
| 4.C FE Reception | — | 2 | 1 |
| 4.D FE Worklist + Validation | — | 6 | 2 |
| 4.E FE Referrals + Cleanup | — | 7 | 1 |
| Testing + bug fixing | — | — | 1 |
| Total | 22 | 24 | ~10 days |
H. Final Confirmation Needed
قبل ما أبدأ Phase 1:
- الـ scope ده مقبول (٢٢ BE + ٢٤ FE = ٤٦ task)؟
- الـ truncate dev DB موافق عليه؟
- تحب نـ feature branch واحدة (
refactor/per-test-status) ولا نقسم Phase 1 / Phase 2 على branches منفصلة؟
- أي شي ناقص أو غامض؟ راجع كل task ونقاطه وقولي.