# حالات الرسالة والحجز

```mermaid
stateDiagram-v2
    [*] --> new
    new --> in_progress: claim
    released --> in_progress: claim
    in_progress --> resolved: resolve_with_reason
    in_progress --> failed: fail_with_reason
    in_progress --> released: release_with_reason
    in_progress --> in_progress: reassign_with_reason
    resolved --> in_progress: admin_reassign_with_reason
    failed --> in_progress: admin_reassign_with_reason
```

| الحدث | الشرط |
|---|---|
| وصول رسالة | بعد قبول جهاز سري ومرسل متاح للعميل، تبدأ `new`. المرسل غير المسموح يذهب إلى صندوق Super Admin. |
| `claim` | موظف مخول أو Admin؛ معاملة وقفل صف. لا يوجد حجز نشط، والحالة `new` أو `released`. يسجل الحجز والحدث `in_progress` معًا. |
| تغيير حالة | يتم عبر `MessageWorkflow`; الموظف يجب أن يكون صاحب الحجز للحالات النهائية. الحالة `failed` أو `released` تتطلب سببًا نصيًا أو صوتيًا. أي انتقال آخر بعد البداية يحتاج سببًا، باستثناء استلام `new/released`. |
| إعادة التعيين | Admin أو Super Admin فقط، وسبب إلزامي. الهدف موظف نشط في العميل لديه مشاهدة وتفاعل لذلك المرسل. يُغلق الحجز السابق وينشأ الحجز الجديد في المعاملة نفسها. |
| تدخل المنصة | يُحفظ في سجل المنصة الخاص، ويُخفى الحدث الداخلي عن Timeline العميل. |

## التزامن والتاريخ

- تقفل الخدمة سجل الرسالة في InnoDB بواسطة `lockForUpdate()` قبل فحص الحالة أو إنشاء الحجز.
- يظل للحجز النشط صف واحد على مستوى الخدمة؛ الطلب المتعارض يرفض بـ409 بدل استبدال الموظف بصمت.
- `message_status_events` سجل أحداث غير قابل للتعديل عبر واجهة التطبيق. الملاحظات الصوتية ترتبط بحدث الحالة في جدول `attachments`.
- كل تغيير للحالة والتعيين يسجل actor والسبب والوقت والحجز السابق والجديد ضمن بيانات الحدث.
- أحداث العملاء تُكتب في `tenant_activity_logs`. إجراءات Super Admin تسجل في `super_admin_security_logs` ولا تصل إلى سجل العميل.

## الإحالات

- إنشاء إحالة لا يحرر الحجز الأصلي ولا يغير الحالة. يجب كتابة سبب الإحالة.
- يوجد إحالة مفتوحة واحدة لكل رسالة. يقفل النظام الرسالة قبل التحقق من إحالة مفتوحة جديدة.
- عضو القسم أو Admin يستلم الإحالة؛ ينتقل الحجز إلى الموظف المستلم في معاملة واحدة. يُسجل انتقال حالة صريح إلى `in_progress` إن لم تكن الرسالة بهذه الحالة.
- يرفض أرشفة قسم لديه إحالة مفتوحة. الاحتفاظ بالإحالات المغلقة مطلوب لسجل الرسالة، لذلك الأرشفة تعطل القسم بدل حذف تاريخه.
