# Complete LIS Workflow Analysis
## From Order Creation to Report Delivery

> Analysis based on: SENAITE LIMS source code (v2.x), OpenELIS Global source code, HL7 v2.x/FHIR R5 standards, IHE Laboratory Technical Framework, Epic Beaker/Cerner PathNet documentation, and industry best practices.

---

# PART 1: Every Role and What They Can Do

## 1.1 SENAITE Built-in Roles (Reference Implementation)

SENAITE defines 11 built-in roles that map to real-world lab positions:

| SENAITE Role | Real-World Position | Arabic |
|---|---|---|
| Client | Patient / Ordering Physician | العميل / الطبيب الطالب |
| LabClerk | Receptionist / Registration Clerk | موظف الاستقبال |
| Sampler | Phlebotomist / Sample Collector | اخصائي سحب العينات |
| Preserver | Sample Preserver | اخصائي حفظ العينات |
| Analyst | Lab Technician / Technologist | فني المختبر |
| Verifier | Lab Supervisor / Section Head | مشرف القسم |
| Publisher | Report Publisher | ناشر التقارير |
| LabManager | Lab Manager / Director | مدير المختبر |
| Manager | System Administrator | مدير النظام |
| RegulatoryInspector | QA / Auditor (read-only) | مفتش الجودة |
| Owner | Object Creator (automatic) | المنشئ |

## 1.2 OpenELIS Built-in Roles

| OpenELIS Role | Real-World Position |
|---|---|
| Reception | Receptionist |
| Results Entry | Lab Technician (data entry) |
| Validation | Lab Supervisor (technical validation) |
| Biologist | Pathologist (clinical validation) |
| Admin | System Administrator |

---

## 1.3 Detailed Role-Action Matrix

### ROLE 1: Receptionist / Registration Clerk (LabClerk / موظف الاستقبال)

**Screen: Registration / Order Entry**

| # | Action | English Label | Arabic Label | Status Change | Notes |
|---|---|---|---|---|---|
| 1 | Register new patient | Register Patient | تسجيل مريض | -- | Demographics, insurance, MRN generation |
| 2 | Create lab request/order | Create Order | إنشاء طلب | --> `registered` | Select patient, doctor, tests, billing type |
| 3 | Add tests to existing order | Add Test | إضافة تحليل | -- | Only while order is in `registered` or `sample_due` |
| 4 | Remove test from order | Remove Test | حذف تحليل | -- | Only before sample collection |
| 5 | Cancel entire order | Cancel Order | إلغاء الطلب | --> `cancelled` | Only before sample received; with reason |
| 6 | Reinstate cancelled order | Reinstate | استعادة | `cancelled` --> previous state | Undo a cancellation |
| 7 | Print barcode labels | Print Barcode | طباعة باركود | -- | Per sample/specimen type |
| 8 | Receive sample at lab | Receive Sample | استلام العينة | `sample_due` --> `sample_received` | Log date received, check sample condition |
| 9 | Reject sample at reception | Reject Sample | رفض العينة | --> `rejected` | Reason required; triggers re-collection request |
| 10 | Edit patient demographics | Edit Patient | تعديل بيانات المريض | -- | Name, phone, insurance, etc. |
| 11 | Search/retrieve orders | Search Orders | بحث الطلبات | -- | By MRN, name, barcode, date range |
| 12 | View results (no edit) | View Results | عرض النتائج | -- | Read-only access to completed results |
| 13 | Print/reprint reports | Print Report | طباعة التقرير | -- | Only for published/released results |

**SENAITE Permission Source (from workflow XML):**
- LabClerk can: View Results, Edit Sample fields (in registered/sample_due states), Modify portal content in sample_registered and sample_due
- LabClerk CANNOT: Submit results, Verify results, Retract results

---

### ROLE 2: Phlebotomist / Sample Collector (Sampler / اخصائي سحب العينات)

**Screen: Collection Worklist / Samples Page**

| # | Action | English Label | Arabic Label | Status Change | Notes |
|---|---|---|---|---|---|
| 1 | View collection worklist | Collection Worklist | قائمة السحب | -- | Filtered to today's pending collections |
| 2 | Mark sample as collected | Collect Sample | سحب العينة | `to_be_sampled` --> `sample_due` | Records: collector, date/time, conditions |
| 3 | Enter field results | Enter Field Result | إدخال نتيجة ميدانية | -- | Only for `point_of_capture=field` analyses |
| 4 | Submit field results | Submit Field Result | إرسال نتيجة ميدانية | analysis --> `to_be_verified` | For field analyses only |
| 5 | Reject sample during collection | Reject at Collection | رفض عند السحب | -- | Hemolyzed, clotted, insufficient volume |
| 6 | Create aliquot | Create Aliquot | إنشاء عينة فرعية | -- | Split sample for different sections |
| 7 | Print barcode label | Print Barcode | طباعة باركود | -- | For new samples/aliquots |
| 8 | Record sample conditions | Log Conditions | تسجيل حالة العينة | -- | Temperature, time elapsed, container integrity |
| 9 | Schedule sampling appointment | Schedule | جدولة | `to_be_sampled` --> `scheduled_sampling` | For outpatient/home collection |

**SENAITE Permission Source:**
- Sampler can: View Results (all states), Edit Field Results (registered/unassigned/assigned states)
- Sampler CANNOT: Edit lab results, Verify, Publish

---

### ROLE 3: Lab Receiving Clerk (LabClerk with receiving permissions)

**Screen: Specimen Receiving / Sample Receipt**

| # | Action | English Label | Arabic Label | Status Change | Notes |
|---|---|---|---|---|---|
| 1 | Receive sample | Receive | استلام | `sample_due` --> `sample_received` | Verify specimen integrity, label match |
| 2 | Accept sample | Accept | قبول | -- | Implicit in receive action |
| 3 | Reject sample | Reject | رفض | --> `rejected` | Wrong container, hemolyzed, expired, unlabeled |
| 4 | Partial reject | Partial Reject | رفض جزئي | Some analyses --> `rejected` | Reject specific tests, accept others |
| 5 | Log rejection reason | Record Reason | تسجيل سبب الرفض | -- | Mandatory with rejection |
| 6 | Request recollection | Request Recollect | طلب إعادة سحب | -- | Triggers new barcode and collection task |
| 7 | Accept with conditions | Conditional Accept | قبول مشروط | `sample_received` + flag | Accept but flag as suboptimal |
| 8 | Assign to section/worksheet | Assign | توزيع | analysis: `unassigned` --> `assigned` | Route to correct lab section |
| 9 | Verify sample identity | Verify Identity | التحقق من الهوية | -- | Two-patient-identifier check |
| 10 | Log storage location | Store Sample | حفظ العينة | -- | Rack, shelf, temperature |

---

### ROLE 4: Lab Technician / Analyst (Analyst / فني المختبر) -- DETAILED

**Screen: Worksheet / Kanban / Results Entry**

| # | Action | English Label | Arabic Label | Status Change | Notes |
|---|---|---|---|---|---|
| 1 | View assigned worklist | My Worklist | قائمة أعمالي | -- | Tests assigned to this analyst |
| 2 | Start testing | Start Test | بدء التحليل | -- | Optional; marks "in progress" |
| 3 | Enter result value | Enter Result | إدخال النتيجة | -- | Numeric, text, selection, or memo |
| 4 | Enter interim values | Enter Interim | إدخال قيم وسيطة | -- | For calculated tests (e.g., dilution factor) |
| 5 | Upload attachment | Attach File | إرفاق ملف | -- | Images, graphs, instrument output |
| 6 | Submit result | Submit | إرسال | analysis: `assigned`/`unassigned` --> `to_be_verified` | Triggers auto-calculation for dependent tests |
| 7 | Submit all on worksheet | Submit All | إرسال الكل | worksheet --> `to_be_verified` | Batch submit when all analyses on worksheet done |
| 8 | Flag abnormal result | Flag Abnormal | تمييز كنتيجة غير طبيعية | -- | Low/High/Critical flags, can be auto-calculated |
| 9 | Add comment to result | Add Comment | إضافة تعليق | -- | Clinical notes, instrument issues |
| 10 | Run QC check | Record QC | تسجيل رقابة الجودة | -- | Control/blank result on same worksheet |
| 11 | Request re-test | Request Re-test | طلب إعادة تحليل | -- | Flags test for supervisor review |
| 12 | View previous results | View History | عرض السوابق | -- | Delta check comparison |
| 13 | Mark instrument reading | Record Machine Result | تسجيل نتيجة الجهاز | -- | Auto-import from analyzer interface |
| 14 | Create duplicate analysis | Create Duplicate | إنشاء مكرر | -- | QC duplicate for same sample on worksheet |

**What the Analyst CANNOT do (critical restrictions from SENAITE guards):**
- CANNOT verify own submitted results (unless self-verification is explicitly enabled in settings)
- CANNOT retract results (this is supervisor action)
- CANNOT reject a sample
- CANNOT publish/release results
- CANNOT edit results after submission (to_be_verified state locks editing)
- CANNOT assign/unassign analyses unless in worksheet context

**SENAITE Guard Logic (from guards.py):**
```
guard_submit():
  - MUST have a result value (non-empty)
  - All interim fields must have values (unless allow_empty=true)
  - Attachment must be set if required
  - Sample must be received (for lab point_of_capture)
  - If "AllowToSubmitNotAssigned" is OFF: only the assigned analyst can submit
  - All dependency analyses must be submitted or submittable
```

---

### ROLE 5: Lab Supervisor / Section Head (Verifier / مشرف القسم)

**Screen: Verification Worklist / Validation**

| # | Action | English Label | Arabic Label | Status Change | Notes |
|---|---|---|---|---|---|
| 1 | View pending verifications | Verification Queue | قائمة المراجعة | -- | All tests in `to_be_verified` state |
| 2 | Verify result (approve) | Verify | تصديق | `to_be_verified` --> `verified` | Final technical approval |
| 3 | Multi-verify (if enabled) | Verify (Round N) | تصديق (جولة N) | `to_be_verified` --> still `to_be_verified` | Requires N verifications before final |
| 4 | Retract submitted result | Retract | سحب/تراجع | `to_be_verified` --> `retracted` + NEW copy created | Creates new analysis, old one frozen as retracted |
| 5 | Reject analysis | Reject | رفض التحليل | --> `rejected` | Remove test entirely, with reason |
| 6 | Request re-test (from verified) | Re-test | إعادة تحليل | `to_be_verified` --> `verified` (old) + new copy in `unassigned` | Old result gets verified, new copy created |
| 7 | Return result to technician | Return | إرجاع | Effectively: retract --> new copy to analyst | "Retract" is the mechanism; creates fresh copy |
| 8 | Add comment/note | Add Comment | إضافة ملاحظة | -- | Explains verification decision |
| 9 | View audit trail | View History | عرض سجل المراجعة | -- | Who did what, when |
| 10 | Manage worksheet | Manage Worksheet | إدارة ورقة العمل | -- | Create, assign analyses, review |
| 11 | Assign analyst to test | Assign Analyst | تعيين فني | `unassigned` --> `assigned` | On worksheet only |
| 12 | Unassign analyst | Unassign | إلغاء التعيين | `assigned` --> `unassigned` | Remove from worksheet |

**Multi-Verification Rules (from SENAITE guards.py):**
```
guard_multi_verify():
  - Remaining verifications must be > 1
  - If submitter == current user: self-verification must be enabled
  - If current user already verified: multi-verification must be allowed
  - If current user was LAST verifier: consecutive-same-user must be allowed
  - Types: "self_multi_disabled", "self_multi_not_cons", (default = allowed)

guard_verify():
  - Remaining verifications must be <= 1 (final verification)
  - Same self-verification and multi-verification rules apply
  - All dependencies must be verified or verifiable
```

---

### ROLE 6: Pathologist / Lab Director (LabManager / مدير المختبر)

**Screen: All screens with elevated privileges**

| # | Action | English Label | Arabic Label | Status Change | Notes |
|---|---|---|---|---|---|
| 1 | All Supervisor actions | (all above) | (all above) | (all above) | Full supervisor capabilities |
| 2 | Publish/release results | Publish | نشر/إصدار | `verified` --> `published` | Makes results available to patient/doctor |
| 3 | Republish results | Republish | إعادة النشر | `published` --> `published` | Generate new report PDF |
| 4 | Invalidate published results | Invalidate | إبطال | `published` --> `invalid` + NEW SAMPLE created | Creates entirely new sample (retest) from invalid |
| 5 | Retract from any state | Retract | سحب | any --> `retracted` | Broader retract authority |
| 6 | Add analysis to any sample | Add Analysis | إضافة تحليل | -- | Even in `to_be_verified` or `verified` state |
| 7 | Create sample partitions | Create Partition | إنشاء تجزئة | -- | Split sample for different sections |
| 8 | Reject sample at any stage | Reject Sample | رفض العينة | --> `rejected` | Reject from received, to_be_verified, etc. |
| 9 | Cancel order at any stage | Cancel | إلغاء | --> `cancelled` | Only in pre-published states |
| 10 | Reinstate cancelled order | Reinstate | استعادة | `cancelled` --> previous state | Restores to state before cancellation |
| 11 | Override auto-verification | Manual Override | تجاوز يدوي | -- | Override auto-verify rules |
| 12 | Sign interpretation/comments | Sign Report | توقيع التقرير | -- | Clinical interpretation text |
| 13 | Dispatch sample | Dispatch | تسليم/إرسال | --> `dispatched` | Physical sample sent (to archive, to external) |
| 14 | Restore dispatched sample | Restore | استرجاع | `dispatched` --> previous state | Bring back dispatched sample |
| 15 | Manage external referrals | Manage Referrals | إدارة التحويلات | -- | Send out, receive results, create invoices |
| 16 | Amend published result | Amend | تعديل | Published --> amended report | Correction with audit trail |

---

# PART 2: Every Status Transition in Detail

## 2.1 Three Separate Workflows That Interact

A LIS has THREE distinct but interconnected workflows:

### A) SAMPLE/ORDER Workflow (the container)
### B) ANALYSIS/TEST Workflow (individual test results)
### C) WORKSHEET Workflow (lab work organization)

These cascade: when ALL analyses in a sample reach a state, the sample auto-transitions too.

---

## 2.2 SAMPLE/ORDER Status States

### SENAITE Sample States (13 total, from XML definition)

```
                          +---> [scheduled_sampling] --+
                          |                            |
[sample_registered] --+---+---> [to_be_sampled] ------+---> [sample_due]
                      |                                        |
                      +---- (no_sampling_workflow) ------------+
                                                               |
                                                        [sample_received]
                                                               |
                                                        [to_be_verified]
                                                               |
                                                          [verified]
                                                               |
                                                          [published]
                                                               |
                                                         [dispatched]

Side states:
  [cancelled] -- can reinstate back
  [rejected]  -- terminal
  [invalid]   -- from published, creates retest sample
```

| State | English Name | Arabic Name | Description |
|---|---|---|---|
| `sample_registered` | Registered | مسجل | Order created, no sample yet |
| `to_be_sampled` | Awaiting Collection | بانتظار السحب | Needs phlebotomist action |
| `scheduled_sampling` | Scheduled | مجدول | Collection appointment set |
| `sample_due` | Sample Due | بانتظار الاستلام | Sample collected, not yet received at lab |
| `sample_received` | Received | مستلم | Lab has the sample, testing can begin |
| `to_be_verified` | Awaiting Verification | بانتظار المراجعة | All results submitted, pending approval |
| `verified` | Verified | تم التصديق | All results approved |
| `published` | Published / Released | منشور / صادر | Report released to patient/doctor |
| `dispatched` | Dispatched | تم التسليم | Physical sample sent out/archived |
| `cancelled` | Cancelled | ملغي | Order cancelled (reversible) |
| `rejected` | Rejected | مرفوض | Sample rejected (terminal) |
| `invalid` | Invalidated | مبطل | Published results recalled; new sample auto-created |

### OpenELIS Order States (4)

| Status | Description |
|---|---|
| `Entered` | Order registered, no work started |
| `Started` | At least one analysis has begun |
| `Finished` | All analyses complete |
| `NonConforming` (deprecated) | Legacy status |

### OpenELIS Sample States (4)

| Status | Description |
|---|---|
| `Entered` | Sample registered |
| `SampleRejected` | Sample rejected |
| `Canceled` | Sample cancelled |
| `Disposed` | Sample disposed after retention |

### HL7 v2 Order Status (OBR-25, Table 0123)

| Code | Name | Description |
|---|---|---|
| `O` | Order received | Specimen not yet received |
| `I` | In Progress | Specimen received, testing in progress |
| `S` | Partial | Some results available |
| `A` | Amended | Previously final, now amended |
| `P` | Preliminary | Preliminary results |
| `C` | Corrected | Correction to final |
| `R` | Results entered | Not verified |
| `F` | Final | Final verified results |
| `X` | Cancelled | Order cancelled |
| `Y` | No order on record | |

### FHIR R5 DiagnosticReport Status

| Status | Description | Arabic |
|---|---|---|
| `registered` | Report registered, no results | مسجل |
| `partial` | Some results available | جزئي |
| `preliminary` | Results entered, not verified | أولي |
| `modified` | Subsequent to preliminary | معدل |
| `final` | All results verified and released | نهائي |
| `amended` | Final changed, clinically significant | معدل (بعد النهائي) |
| `corrected` | Final corrected (error fix) | مصحح |
| `appended` | Additional information added | ملحق |
| `cancelled` | Report cancelled | ملغي |
| `entered-in-error` | Should not exist, retracted | خطأ إدخال |

---

## 2.3 ANALYSIS/TEST Result Status States

### SENAITE Analysis States (9 total, from XML definition)

```
[registered] ---(initialize)--> [unassigned]
                                     |
                              (assign)|
                                     v
                                [assigned]
                                     |
                              (submit)|
                                     v
                            [to_be_verified]
                              /     |     \
                     (retract)/  (verify)   \(retest)
                           v       |         v
                    [retracted]    v      [verified] (old gets verified,
                         |    [verified]      new copy in [unassigned])
                         |         |
                  (unassign)  (publish)
                         v         v
                  [unassigned]  [published]  <-- TERMINAL
                  (new copy)

Side transitions:
  [rejected] -- from unassigned, assigned, to_be_verified
  [cancelled] -- from registered, unassigned (when parent order cancelled)
```

| State | English Name | Arabic Name | Who Puts It Here | Can Edit Result? |
|---|---|---|---|---|
| `registered` | Registered | مسجل | System (at creation) | No (no sample received) |
| `unassigned` | Unassigned | غير معين | System (after sample received) | YES - Analyst, LabManager |
| `assigned` | Assigned | معين | Worksheet assignment | YES - Assigned Analyst, LabManager |
| `to_be_verified` | Submitted / Pending Verification | بانتظار المراجعة | Analyst (submit) | NO - locked |
| `retracted` | Retracted | مسحوب | Verifier/LabManager (retract) | NO - frozen |
| `rejected` | Rejected | مرفوض | Verifier/LabManager (reject) | NO - frozen |
| `verified` | Verified | مصدق | Verifier/LabManager (verify) | NO - locked |
| `published` | Published | منشور | Publisher/LabManager (publish) | NO - frozen |
| `cancelled` | Cancelled | ملغي | System (when order cancelled) | NO |

### OpenELIS Analysis States (7)

| Status | Description | Arabic |
|---|---|---|
| `NotStarted` | Test ordered, no work done | لم يبدأ |
| `TechnicalAcceptance` | Result entered, pending technical review | بانتظار المراجعة الفنية |
| `TechnicalRejected` | Technician rejected by supervisor | مرفوض فنيا |
| `BiologistRejected` | Rejected by pathologist/biologist | مرفوض من الأخصائي |
| `Finalized` | Fully validated and released | نهائي |
| `Canceled` | Test cancelled | ملغي |
| `SampleRejected` | Parent sample was rejected | العينة مرفوضة |

### HL7 v2 Observation Result Status (OBX-11, Table 0085)

| Code | Name | Description | Arabic |
|---|---|---|---|
| `O` | Order detail | No result yet | تفاصيل الطلب |
| `I` | In Progress | Specimen in lab, pending | قيد التنفيذ |
| `S` | Partial | Partial result available | نتيجة جزئية |
| `P` | Preliminary | Preliminary, may change | أولي |
| `A` | Amended | Changed after final | معدل |
| `C` | Corrected | Error correction after final | مصحح |
| `R` | Entered, not verified | Result entered, not verified | مدخل غير مراجع |
| `F` | Final | Final, can only be corrected | نهائي |
| `X` | Cannot obtain | Results cannot be obtained | تعذر الحصول |
| `U` | Preliminary (from instrument) | From analyzer, not verified | أولي من الجهاز |
| `N` | Not asked for | Test not ordered | غير مطلوب |
| `W` | Original posted as wrong | Retracted/wrong | خطأ - تم السحب |
| `D` | Delete (obsolete) | OBX should be deleted | محذوف |

---

## 2.4 Complete Transition Table

### Analysis Transitions (from SENAITE XML + source code)

| # | Transition | From State(s) | To State | Triggered By | Arabic Name | Permission Required |
|---|---|---|---|---|---|---|
| 1 | `initialize` | registered | unassigned | System (on sample receive) | تهيئة | -- (automatic) |
| 2 | `assign` | unassigned | assigned | LabManager/Analyst (worksheet) | تعيين | Analyst, LabManager |
| 3 | `unassign` | assigned | unassigned | LabManager (worksheet) | إلغاء التعيين | LabManager |
| 4 | `submit` | unassigned, assigned | to_be_verified | Analyst | إرسال | Analyst, LabManager |
| 5 | `multi_verify` | to_be_verified | to_be_verified | Verifier | تصديق (جولة) | Verifier, LabManager |
| 6 | `verify` | to_be_verified | verified | Verifier/LabManager | تصديق | Verifier, LabManager |
| 7 | `retest` | to_be_verified | verified (old) + unassigned (new) | LabManager | إعادة تحليل | LabManager |
| 8 | `retract` | to_be_verified | retracted | Verifier/LabManager | سحب النتيجة | LabManager, Verifier |
| 9 | `reject` | unassigned, assigned, to_be_verified | rejected | LabManager | رفض التحليل | LabManager |
| 10 | `publish` | verified | published | Publisher/LabManager | نشر | Publisher, LabManager |
| 11 | `cancel` | registered, unassigned | cancelled | System (from order cancel) | إلغاء | LabManager |
| 12 | `reinstate` | cancelled | unassigned | LabManager | استعادة | LabManager |

### Sample Transitions (from SENAITE XML + source code)

| # | Transition | From State(s) | To State | Triggered By | Arabic Name |
|---|---|---|---|---|---|
| 1 | `no_sampling_workflow` | sample_registered | sample_due | System (auto) | -- |
| 2 | `to_be_sampled` | sample_registered | to_be_sampled | System (when sampling required) | -- |
| 3 | `schedule_sampling` | to_be_sampled | scheduled_sampling | LabClerk/Sampler | جدولة السحب |
| 4 | `sample` | to_be_sampled, scheduled_sampling | sample_due | Sampler | سحب العينة |
| 5 | `receive` | sample_due | sample_received | LabClerk | استلام العينة |
| 6 | `submit` | sample_received | to_be_verified | System (all analyses submitted) | إرسال |
| 7 | `retract` | to_be_verified | sample_received | Verifier/LabManager | سحب |
| 8 | `rollback_to_receive` | to_be_verified, verified | sample_received | System (on analysis retract/retest) | تراجع |
| 9 | `verify` | to_be_verified | verified | Verifier/LabManager (all analyses verified) | تصديق |
| 10 | `prepublish` | sample_received, to_be_verified | -- | LabManager (pre-publish step) | -- |
| 11 | `publish` | verified | published | Publisher/LabManager | نشر |
| 12 | `republish` | published | published | LabManager | إعادة النشر |
| 13 | `invalidate` | verified, published | invalid | LabManager | إبطال |
| 14 | `reject` | to_be_sampled, scheduled_sampling, sample_due, sample_received, to_be_verified | rejected | LabManager | رفض |
| 15 | `cancel` | sample_registered, scheduled_sampling, to_be_sampled, sample_due | cancelled | LabClerk/LabManager | إلغاء |
| 16 | `reinstate` | cancelled | sample_registered | LabManager | استعادة |
| 17 | `create_partitions` | sample_received, to_be_verified, verified, published | sample_received (partition) | LabManager | تجزئة |
| 18 | `detach` | sample_due, sample_received, to_be_verified, verified | (no change) | LabManager | فصل |
| 19 | `dispatch` | sample_due through published, rejected, invalid | dispatched | LabManager | تسليم |
| 20 | `restore` | dispatched | previous state | LabManager | استرجاع |

---

## 2.5 Backward/Undo Transitions (The Critical Part)

### Going BACKWARD Through the Workflow

```
FORWARD:  registered -> unassigned -> assigned -> to_be_verified -> verified -> published
BACKWARD: published  <- verified   <- to_be_verified <- assigned <- unassigned

HOW BACKWARD WORKS:
  published  ---(invalidate)---> [invalid] + NEW SAMPLE CREATED
  verified   ---(retest at sample level = invalidate)---> [invalid] + NEW SAMPLE
  to_be_verified ---(retract)---> [retracted] + NEW ANALYSIS COPY in [unassigned]
  to_be_verified ---(retest)----> [verified] (old) + NEW ANALYSIS COPY in [unassigned]
  to_be_verified ---(reject)----> [rejected] (terminal, no new copy)
  assigned   ---(unassign)---> [unassigned]
  cancelled  ---(reinstate)---> previous state
```

**KEY INSIGHT: There is NO direct "return to previous state" in professional LIS systems. Going backward ALWAYS creates a new copy. The original is frozen for audit trail.**

---

# PART 3: Feedback Operations (Every Undo/Reversal)

## 3.1 Cancel a Test

| Aspect | Detail |
|---|---|
| **Who can cancel** | LabManager, or system (when parent order is cancelled) |
| **At what stage** | Only `registered` or `unassigned` states |
| **What happens to result** | No result exists yet (too early in workflow) |
| **Side effects** | Removed from worksheet (if any); analysis marked `cancelled` |
| **Reversible?** | YES -- `reinstate` transition brings it back to `unassigned` |
| **English action** | Cancel Test / Cancel Analysis |
| **Arabic action** | إلغاء التحليل |

**From SENAITE code (`after_cancel`):**
```python
def after_cancel(analysis):
    remove_analysis_from_worksheet(analysis)
```

---

## 3.2 Reject a Specimen

| Aspect | Detail |
|---|---|
| **Who can reject** | LabManager (any stage), LabClerk (at reception) |
| **When** | From `to_be_sampled`, `scheduled_sampling`, `sample_due`, `sample_received`, `to_be_verified` |
| **Does it create a new specimen?** | NOT automatically. A new order/request must be created manually for recollection |
| **Partial rejection** | YES -- individual analyses can be rejected while others continue |
| **What about existing results** | All analyses cascade to `rejected`. Attachments hidden from report |
| **Reason required** | YES -- hemolysis, clotting, wrong container, insufficient volume, expired, unlabeled |
| **English action** | Reject Sample / Reject Specimen |
| **Arabic action** | رفض العينة |

**From SENAITE code (`after_reject` for analysis):**
```python
def after_reject(analysis):
    alsoProvides(analysis, IRejected)
    remove_analysis_from_worksheet(analysis)
    # Hide attachments from report
    for attachment in analysis.getAttachment():
        attachment.setRenderInReport(False)
    # Cascade to dependent analyses
    cascade_to_dependents(analysis, "reject")
```

**Common Rejection Reasons (Arabic/English):**

| English | Arabic | Code |
|---|---|---|
| Hemolyzed specimen | عينة متحللة | HEM |
| Clotted specimen | عينة متجلطة | CLT |
| Insufficient volume | كمية غير كافية | QNS |
| Wrong container | حاوية خاطئة | WC |
| Mislabeled | بيانات خاطئة | ML |
| Expired specimen | عينة منتهية الصلاحية | EXP |
| Contaminated | عينة ملوثة | CON |
| Broken container | حاوية مكسورة | BRK |
| No specimen received | لم تستلم العينة | NSR |
| Wrong temperature | درجة حرارة خاطئة | TMP |

---

## 3.3 Re-test / Repeat

There are TWO different re-test mechanisms:

### A) Re-test from `to_be_verified` State (Analysis-Level)

| Aspect | Detail |
|---|---|
| **Who requests** | LabManager (guard requires verify permission) |
| **Trigger** | `retest` transition on individual analysis |
| **What happens to old result** | OLD analysis gets VERIFIED (auto-verify) and marked as "retested" |
| **New barcode?** | SAME sample, NO new barcode. New analysis created inside same sample |
| **New analysis state** | `unassigned` (ready for re-assignment) |
| **Worksheet behavior** | New copy is auto-added to the same worksheet as the original |
| **Cascade** | All dependent analyses are verified first, then retested too |
| **Sample state** | Rolls back to `sample_received` |
| **English action** | Re-test / Repeat Test |
| **Arabic action** | إعادة التحليل |

**From SENAITE code (`after_retest`):**
```python
def after_retest(analysis):
    alsoProvides(analysis, IVerified)
    # Verify all submitted relatives first
    for relative in relatives:
        if ISubmitted.providedBy(relative):
            doActionFor(relative, "verify")
    # Create retests for submitted relatives
    for relative in relatives:
        if ISubmitted.providedBy(relative):
            create_retest(relative)
    # Create the retest for this analysis
    create_retest(analysis)
    # Rollback the sample to received
    doActionFor(analysis.getRequest(), "rollback_to_receive")
```

**From `create_retest` (analysis level):**
```python
def create_retest(analysis):
    parent = api.get_parent(analysis)
    retest = create_analysis(parent, analysis, RetestOf=analysis)
    # Add to same worksheet
    worksheet = analysis.getWorksheet()
    if worksheet:
        worksheet.addAnalysis(retest)
    return retest
```

### B) Invalidate from `published` State (Sample-Level)

| Aspect | Detail |
|---|---|
| **Who requests** | LabManager only |
| **Trigger** | `invalidate` transition on sample/order |
| **What happens to old** | Entire sample marked `invalid`. Old remains for audit |
| **New barcode?** | YES -- entire new sample created with new ID/barcode |
| **New sample state** | `sample_received` (skips registration and collection) |
| **New analyses state** | All copied to `unassigned` |
| **Excluded from copy** | Retracted analyses, published dates, remarks |
| **English action** | Invalidate / Recall Results |
| **Arabic action** | إبطال النتائج |

**From SENAITE code (`create_retest` for sample):**
```python
def create_retest(ar):
    # AR must be in 'invalid' state
    retest = _createObjectByType("AnalysisRequest", ar.aq_parent, tmpID())
    copy_field_values(ar, retest, ignore=['Analyses','DatePublished','Invalidated','Sample','Remarks'])
    alsoProvides(retest, IAnalysisRequestRetest)
    retest.setInvalidated(ar)  # Link to original
    # Copy analyses (skip retracted ones)
    for an in ar.getAnalyses():
        if an.isRetest(): continue
        if status in ['retracted']: continue
        nan = _createObjectByType("Analysis", retest, keyword)
        copy_field_values(an, nan)
    # Jump directly to sample_received
    changeWorkflowState(retest, SAMPLE_WORKFLOW, 'sample_received')
    # Initialize all analyses to unassigned
    for analysis in retest.getAnalyses():
        changeWorkflowState(analysis, ANALYSIS_WORKFLOW, "unassigned")
```

---

## 3.4 Return a Result (from Verification back to Entry)

| Aspect | Detail |
|---|---|
| **Mechanism** | `retract` transition (there is no separate "return" action) |
| **Who** | Verifier or LabManager |
| **From state** | `to_be_verified` |
| **What happens** | Original analysis --> `retracted` (frozen). NEW COPY created in `unassigned` |
| **Old result preserved?** | YES -- old analysis is frozen at `retracted` with all its data |
| **New analysis** | Copy of original, empty result, in `unassigned` state |
| **Cascade** | Retract cascades DOWN to dependents AND UP to dependencies |
| **Sample state** | Rolls back to `sample_received` |
| **English action** | Retract |
| **Arabic action** | سحب النتيجة / إرجاع للفني |

**From SENAITE code (`after_retract`):**
```python
def after_retract(analysis):
    alsoProvides(analysis, IRetracted)
    # Hide attachments from report
    for attachment in analysis.getAttachment():
        attachment.setRenderInReport(False)
    # Retract dependents (analyses that depend on this)
    cascade_to_dependents(analysis, "retract")
    # Retract dependencies (analyses this depends on)
    promote_to_dependencies(analysis, "retract")
    # Create new copy for re-testing
    create_retest(analysis)
    # Roll back the sample
    doActionFor(analysis.getRequest(), "rollback_to_receive")
```

**IMPORTANT: Retract creates a chain reaction for calculated tests:**
- If you retract Hemoglobin, and MCV depends on Hemoglobin, MCV also gets retracted
- Both get new copies created
- The sample rolls back to received

---

## 3.5 Retract/Recall a Released Result

| Aspect | Detail |
|---|---|
| **Mechanism** | `invalidate` transition at sample level (NOT individual analysis) |
| **Who** | LabManager only |
| **From state** | `verified` or `published` |
| **What happens** | Entire sample --> `invalid`. Brand new sample created (full copy) |
| **Old results** | Preserved in original sample marked as invalid |
| **New sample** | Gets new barcode/ID. Starts at `sample_received` |
| **Patient notification** | Configurable -- can send invalidation email |
| **English action** | Invalidate Results |
| **Arabic action** | إبطال النتائج / سحب التقرير |

**KEY DISTINCTION from SENAITE:**
- There is NO "step back" from verified to to_be_verified for individual analyses
- Once verified, you can ONLY invalidate the ENTIRE sample
- This is a deliberate design: verified results have legal weight

---

## 3.6 Amend a Result (Correct Without Retracting)

**This is NOT a native SENAITE transition.** It exists in HL7/FHIR and commercial systems:

| Aspect | Detail |
|---|---|
| **HL7 mechanism** | Send new OBX with status `C` (corrected) or `A` (amended) |
| **FHIR mechanism** | Update DiagnosticReport status to `corrected` or `amended` |
| **Who** | Pathologist / Lab Director |
| **What happens** | New version of result with correction reason; original preserved in history |
| **Audit trail** | MUST record: original value, new value, who changed, when, why |
| **Report** | New report generated with "AMENDED" or "CORRECTED" watermark |
| **English action** | Amend Result / Correct Result |
| **Arabic action** | تعديل النتيجة / تصحيح النتيجة |

**Difference between Amend and Correct:**

| | Amended | Corrected |
|---|---|---|
| **When** | Clinical significance change | Error fix |
| **Example** | Additional findings added | Transcription error fixed |
| **FHIR status** | `amended` | `corrected` |
| **HL7 code** | `A` | `C` |
| **Arabic** | معدل | مصحح |

**How commercial systems handle it:**
- Epic Beaker: "Amended Result" workflow -- creates new version, original preserved
- Cerner PathNet: Result correction with mandatory reason; original flagged but visible
- Both require: reason for amendment, who authorized, timestamp, original value preserved

---

## 3.7 Send Out to External Lab

| Aspect | Detail |
|---|---|
| **From which stage** | During collection (outsourced from start) OR from kanban (send-out decision) |
| **Who decides** | LabManager or Analyst (from kanban) |
| **What happens to kanban** | Test LEAVES kanban entirely. Goes to Referrals page |
| **New barcode?** | YES -- new barcode for the external lab sample |
| **Status flow** | Kanban item --> back to collection (new barcode) --> after collection goes to Referrals (NOT kanban) |
| **Result entry** | Via: external lab portal, referrals page, or results page (all sync) |
| **English action** | Send Out / Refer to External Lab |
| **Arabic action** | تحويل لمختبر خارجي |

**Two pathways for external tests:**

1. **Pre-configured outsource**: Investigation has `is_outsourced=true` + `default_external_lab_id`
   - At collection: gets separate barcode automatically
   - After collection: goes DIRECTLY to referrals (never enters kanban)

2. **Ad-hoc send-out from kanban**: Internal test that lab decides to outsource
   - From kanban: click "Send Out"
   - Creates new external barcode
   - Goes back to collection for the external barcode
   - After collection: goes to referrals (exits kanban)

---

## 3.8 Add a Test to an Existing Order

| Aspect | Detail |
|---|---|
| **Who** | LabClerk (early states), LabManager (any state) |
| **At what stage** | LabClerk: `sample_registered`, `sample_due`. LabManager: up through `verified` |
| **What happens** | New analysis created in `unassigned` or `registered` state |
| **Sample state change** | If sample was `verified`/`to_be_verified`, may roll back to `sample_received` |
| **New barcode needed?** | Only if the added test requires a different specimen type |
| **English action** | Add Test / Add Analysis |
| **Arabic action** | إضافة تحليل |
| **Reflex testing** | System can auto-add tests based on rules (e.g., abnormal glucose --> add HbA1c) |

**SENAITE permissions for Add Analysis (from XML):**
- `sample_registered`: LabClerk, LabManager, Manager
- `sample_due`: LabClerk, LabManager, Manager
- `sample_received`: LabClerk, LabManager, Manager
- `to_be_verified`: LabManager, Manager only (NOT LabClerk)
- `verified`: LabManager, Manager only

---

## 3.9 Cancel an Entire Order

| Aspect | Detail |
|---|---|
| **Who** | LabClerk (early states), LabManager (pre-published) |
| **When** | `sample_registered`, `scheduled_sampling`, `to_be_sampled`, `sample_due` |
| **What about samples already collected?** | Collection cancelled; sample marked for disposal |
| **What about results already entered?** | All analyses cascade to `cancelled` state |
| **Side effects** | All analyses removed from worksheets |
| **Reversible?** | YES -- `reinstate` transition restores to previous state |
| **English action** | Cancel Order / Cancel Request |
| **Arabic action** | إلغاء الطلب |

**From SENAITE code (`after_cancel` for AR):**
```python
def after_cancel(analysis_request):
    do_action_to_descendants(analysis_request, "cancel")  # Cancel partitions
    do_action_to_analyses(analysis_request, "cancel")     # Cancel all analyses
```

**From SENAITE code (`after_reinstate` for AR):**
```python
def after_reinstate(analysis_request):
    do_action_to_descendants(analysis_request, "reinstate")
    do_action_to_analyses(analysis_request, "reinstate")
    # Restore to previous state before cancellation
    prev = api.get_previous_workflow_status_of(analysis_request, skip=["cancelled"])
    changeWorkflowState(analysis_request, SAMPLE_WORKFLOW, prev)
```

---

# PART 4: The Exact Names/Labels for Each Action

## 4.1 Complete Action Terminology (English / Arabic / SENAITE / OpenELIS)

| # | Action | English (Standard) | Arabic (Standard) | SENAITE Label | OpenELIS Label | HL7/FHIR Term |
|---|---|---|---|---|---|---|
| 1 | Create order | Create Order | إنشاء طلب | Register | Enter Order | New Order (ORM) |
| 2 | Collect sample | Collect | سحب العينة | Sample | -- | Specimen Collected |
| 3 | Schedule collection | Schedule | جدولة | Schedule Sampling | -- | -- |
| 4 | Receive sample | Receive | استلام العينة | Receive | -- | Specimen Received |
| 5 | Accept sample | Accept | قبول العينة | (implicit in Receive) | -- | -- |
| 6 | Reject sample | Reject | رفض العينة | Reject | Reject | -- |
| 7 | Assign to worksheet | Assign | تعيين | Assign | -- | -- |
| 8 | Unassign from worksheet | Unassign | إلغاء التعيين | Unassign | -- | -- |
| 9 | Enter result | Enter Result | إدخال النتيجة | (data entry) | Enter Result | -- |
| 10 | Submit result | Submit | إرسال النتيجة | Submit | Save | Results Entered (R) |
| 11 | Verify (technical) | Verify | تصديق فني | Verify | Technical Acceptance | -- |
| 12 | Validate (clinical) | Validate | مصادقة سريرية | (same as verify) | Biologist Validation | -- |
| 13 | Approve result | Approve | اعتماد النتيجة | Verify | Validate | -- |
| 14 | Release result | Release | إصدار النتيجة | Publish | Finalize | Final (F) |
| 15 | Publish report | Publish | نشر التقرير | Publish | -- | Final (F) |
| 16 | Retract result | Retract | سحب النتيجة | Retract | -- | -- |
| 17 | Reject result | Reject Test | رفض التحليل | Reject | Technical Reject | -- |
| 18 | Re-test | Re-test | إعادة التحليل | Retest | -- | -- |
| 19 | Invalidate | Invalidate | إبطال | Invalidate | -- | Entered in Error (W) |
| 20 | Amend | Amend | تعديل | -- (not native) | -- | Amended (A) |
| 21 | Correct | Correct | تصحيح | -- (not native) | -- | Corrected (C) |
| 22 | Cancel test | Cancel | إلغاء التحليل | Cancel | Cancel | Cancelled (X) |
| 23 | Cancel order | Cancel Order | إلغاء الطلب | Cancel | Cancel | Cancel Order |
| 24 | Reinstate | Reinstate | استعادة | Reinstate | -- | -- |
| 25 | Send out | Send Out | تحويل خارجي | -- (custom) | Refer | -- |
| 26 | Add test | Add Test | إضافة تحليل | Add Analysis | Add Test | Add Order |
| 27 | Dispatch | Dispatch | تسليم العينة | Dispatch | -- | -- |
| 28 | Restore | Restore | استرجاع | Restore | -- | -- |
| 29 | Create partition | Partition | تجزئة | Create Partitions | -- | -- |
| 30 | Print report | Print | طباعة التقرير | Print | Print | -- |
| 31 | Republish | Republish | إعادة النشر | Republish | -- | -- |
| 32 | Flag critical | Critical Alert | تنبيه حرج | (automatic) | -- | Critical (FHIR flag) |
| 33 | Start test | Start | بدء التحليل | (not explicit) | -- | In Progress (I) |

---

## 4.2 Status Label Terminology

| Status | English | Arabic | SENAITE State ID | HL7 Code | FHIR Status |
|---|---|---|---|---|---|
| Registered | Registered | مسجل | sample_registered / registered | O | registered |
| Awaiting Collection | Awaiting Collection | بانتظار السحب | to_be_sampled | -- | -- |
| Collected | Collected | تم السحب | sample_due | -- | -- |
| Received | Received | مستلم | sample_received | I | -- |
| In Progress | In Progress | قيد التنفيذ | (assigned) | I | -- |
| Pending Verification | Pending Verification | بانتظار المراجعة | to_be_verified | R | preliminary |
| Verified | Verified | مصدق | verified | -- | -- |
| Released / Final | Final | نهائي | published | F | final |
| Retracted | Retracted | مسحوب | retracted | W | entered-in-error |
| Rejected | Rejected | مرفوض | rejected | X | cancelled |
| Cancelled | Cancelled | ملغي | cancelled | X | cancelled |
| Invalidated | Invalidated | مبطل | invalid | W | entered-in-error |
| Amended | Amended | معدل | -- | A | amended |
| Corrected | Corrected | مصحح | -- | C | corrected |
| Partial | Partial | جزئي | -- | S | partial |

---

# PART 5: Comparison with Moon ERP's Current Implementation

## What Moon ERP Currently Has vs What It Should Have

### Current Moon ERP Status Model (from lis-request.model.ts):
```
Request: pending | in_progress | completed | cancelled
Result: (entered/validated/approved/released timestamps)
Sample: status + collection/rejection fields
```

### What's Missing (Critical Gaps):

| Gap | What Professional Systems Have | Impact |
|---|---|---|
| **No analysis-level workflow** | Each test has its own state machine independent of order | Cannot retract/reject individual tests |
| **No "retract" creates copy** | Retract freezes old, creates new copy | Cannot maintain audit trail of original result |
| **No multi-verification** | Configurable N-level verification with self-verify prevention | Compliance risk |
| **No invalidate/retest at sample level** | Invalidate published results --> new sample auto-created | Cannot recall released results properly |
| **No worksheet concept** | Group analyses for batch processing on same instrument | Lab efficiency |
| **Timestamps instead of states** | Using entered/validated/approved/released timestamps vs discrete states | Cannot enforce transition rules |
| **No cascade logic** | Retract/reject cascades to dependent and dependency analyses | Calculated tests break |
| **No partition support** | Split sample for different sections | Cannot track aliquots properly |
| **No amendment workflow** | HL7 amended/corrected status after publication | Cannot correct released results per standard |

---

# PART 6: Recommended Status Model for Moon ERP

## Proposed Analysis/Result States (11 states)

```typescript
enum ResultStatus {
  REGISTERED = 'registered',       // Test ordered, sample not received
  PENDING = 'pending',             // Sample received, awaiting work
  IN_PROGRESS = 'in_progress',     // Analyst working on it
  SUBMITTED = 'submitted',         // Result entered, awaiting verification
  VERIFIED = 'verified',           // Technically verified
  RELEASED = 'released',           // Published to patient/doctor (= FHIR "final")
  RETRACTED = 'retracted',         // Pulled back (frozen, new copy created)
  REJECTED = 'rejected',           // Test rejected (terminal)
  CANCELLED = 'cancelled',         // Test cancelled (reversible)
  AMENDED = 'amended',             // Corrected after release
  INVALIDATED = 'invalidated'      // Entire sample invalidated after release
}
```

## Proposed Request/Order States (8 states)

```typescript
enum RequestStatus {
  REGISTERED = 'registered',       // Order created
  COLLECTING = 'collecting',       // Awaiting/in-progress collection
  RECEIVED = 'received',           // All samples received at lab
  IN_PROGRESS = 'in_progress',     // Testing underway
  PENDING_VERIFICATION = 'pending_verification',  // All results submitted
  VERIFIED = 'verified',           // All results verified
  RELEASED = 'released',           // Report published
  CANCELLED = 'cancelled'          // Order cancelled
}
```

## Proposed Sample States (7 states)

```typescript
enum SampleStatus {
  PENDING = 'pending',             // Awaiting collection
  COLLECTED = 'collected',         // Collected, in transit
  RECEIVED = 'received',           // Received at lab
  REJECTED = 'rejected',           // Rejected at any point
  DISPATCHED = 'dispatched',       // Sent out (external or archive)
  DISPOSED = 'disposed',           // Past retention, disposed
  CANCELLED = 'cancelled'          // Cancelled
}
```

---

# APPENDIX: Auto-Verification Rules

Professional LIS systems support auto-verification (auto-release) when ALL of these pass:

| Rule | Description | Arabic |
|---|---|---|
| **Normal Range** | Result within reference range | ضمن المدى الطبيعي |
| **Critical Range** | Result NOT in critical/panic range | خارج المدى الحرج |
| **Delta Check** | Change from previous result within threshold | فحص التغير |
| **QC Check** | Current QC lot in control | فحص الرقابة |
| **Instrument Flags** | No error flags from analyzer | لا توجد أعلام خطأ |
| **Linearity** | Result within instrument's linear range | ضمن مدى الخطية |
| **Specimen Age** | Specimen not too old | عمر العينة مقبول |
| **Patient Rules** | No special patient flags (first-time, age-specific) | لا قيود خاصة |

When all rules pass: result auto-transitions from `submitted` --> `verified` --> `released`.
When any rule fails: result stays at `submitted` for manual review.

---

Sources:
- [SENAITE LIMS Source Code (GitHub)](https://github.com/senaite/senaite.core)
- [SENAITE Features](https://www.senaite.com/features/)
- [SENAITE Sample Basics](https://www.senaite.com/docs/sample-basics.html)
- [OpenELIS Global](https://openelis-global.org/features-and-functionality/)
- [OpenELIS Global Source Code (GitHub)](https://github.com/DIGI-UW/OpenELIS-Global-2)
- [HL7 Result Status Table 0123](https://terminology.hl7.org/CodeSystem-v2-0123.html)
- [HL7 Observation Result Status Table 0085](https://terminology.hl7.org/CodeSystem-v2-0085.html)
- [FHIR DiagnosticReport](https://build.fhir.org/diagnosticreport.html)
- [FHIR Lifecycle](https://hl7.org/fhir/R4/lifecycle.html)
- [IHE Laboratory Testing Workflow](https://wiki.ihe.net/index.php/Laboratory_Testing_Workflow)
- [Bika LIMS Verification Workflow](https://www.bikalims.org/manual/workflow/images-ar-verification/verify-or-retract-analysis-results-in-bika-and-senaite/view)
- [OpenMRS Lab Order Status Mapping](https://talk.openmrs.org/t/the-handling-and-mapping-of-lab-order-status-for-the-lab-workflow/26348)
- [Epic Beaker Implementation](https://pmc.ncbi.nlm.nih.gov/articles/PMC4763507/)
- [LIS Auto-Verification Design](https://pmc.ncbi.nlm.nih.gov/articles/PMC6609390/)
