ISS-2026-9143 · تحليل فجوة (Phase 1 — بلا كود)

من عرض سعر إلى فاتورة بيع Quotation → Sales Invoice → Stock Issue · flow gap analysis · moonui2 / hazemdev2

النوع: تحسين الباك: الـendpoint موجود وكامل الواجهة: زر التحويل مفقود فاتورة→إذن صرف: موجود (9121) قرارات مالك: 4

1 المشكلة

العميل بيوصف الفلو اللي عايزه ويسأل هل موجود وصحيح ومقبول وإيه التعديلات:

«الوقتي فين نظام الشركة الحالي — لو عملت فاتورة بيع مباشرة بتعمل إذن صرف من المخزن. فالمندوب لما يبعت عرض السعر يتحوّل على طول لفاتورة بيع، يعني المحاسب أو المسؤول بيحوّله مباشر لفاتورة بيع. هل ده صحيح ومقبول؟ وإيه هي التعديلات اللي محتاجينها علشان نعمل كده؟»

الفلو المطلوب باختصار: مندوب يعمل عرض سعر → مسؤول/محاسب يحوّله لفاتورة بيع → الفاتورة عند ترحيلها تعمل إذن صرف من المخزن.

الإجابة المختصرة: الفلو ده صحيح ومقبول محاسبيًا ومخزنيًا، ومعظمه موجود ومبني بالفعل — بس فيه حلقة واحدة ناقصة في الواجهة بتخلّي الفلو مش قابل للوصول من الشاشة، + شويّة قرارات صلاحيات.

2 الوضع الحالي — إيه اللي موجود فعلاً

عرض سعرمقبول (Accepted)
تحويل لفاتورةالباك ✅ · الواجهة ❌ (مفيش زر)
فاتورة مسودةDraft
ترحيلPost → قيود + إذن صرف
إذن صرفيعتمده أمين المخزن

✅ الباك (BE) — تحويل عرض السعر لفاتورة موجود وكامل

BE الـendpoint POST /api/sales/quotations/{id}/convert-to-invoice شغّال ومكتمل:

✅ الباك (BE) — الفاتورة عند الترحيل بتعمل إذن صرف (ISS-9121)

BE PostSalesInvoice::execute PostSalesInvoice.php:38-117:

❌ الواجهة (FE) — زر «تحويل لفاتورة» غير موجود إطلاقًا

FE ده جوهر المشكلة. في شاشة عروض الأسعار الموجود بس زر «تحويل لأمر بيع» (Convert to Order) — quotations.component.html:106-115 (يظهر للعرض «المقبول»، صلاحية sales.orders.create).

أما «تحويل لفاتورة» فالكود التحتي موجود (الخدمة sales-quotation.service.ts:98 + الـeffect quotations.effects.ts:179 + الـreducer) لكن مفيش أي زر أو شاشة بتنده عليه — كود ميت. فالمستخدم مش قادر يوصل للفلو ده من الشاشة.

توضيح للسجل: فيتشر 9122 (WP1) ضاف الـendpoint في الباك فقط — الزر في الواجهة ما اتعملش. رسالة تحقّق 9122 السابقة قالت «الزر بقى شغّال» وده كان غير دقيق؛ التذكرة دي بتكمّل الحلقة الناقصة.

⚠️ الصلاحيات الافتراضية — مين يقدر يعمل إيه

BE من RolePermissionSeeder، خارج الصندوق:

الدوريحوّل (create)يرحّل (post)يعتمد الصرف (issues.approve)
المالك / super-admin
المدير (manager)
المحاسب (accountant)
الكاشير / مندوب المبيعات

يعني «المحاسب/المسؤول بيحوّله» زي ما العميل بيقول — المحاسب حاليًا مالوش الصلاحية لا يحوّل ولا يرحّل. ده قرار توزيع صلاحيات محتاج تأكيد (قسم 8).

3 المطلوب

  1. إمكانية تحويل عرض السعر لفاتورة بيع من الشاشة (اللي هي الحلقة الناقصة).
  2. الفاتورة تعمل إذن صرف من المخزن (موجود — 9121).
  3. تأكيد إن الفلو ككل صحيح ومقبول، وتحديد أي تعديلات لازمة (صلاحيات/خطوة واحدة/سلوك المخزن).

4 الفجوة (GAP)

البندالمطلوبالموجود اليوماللازم يتعمل
endpoint تحويل عرض→فاتورةموجود✅ كامل (BE)لا شيء
زر «تحويل لفاتورة» في الواجهةموجود❌ مفقود (كود ميت)بناء الزر + التنقّل للمسودة (FE)
فاتورة → إذن صرفموجود✅ 9121إعداد فقط (تفعيل التوجّلات)
تحويل بخطوة واحدة لفاتورة نهائية مرحّلة؟ (غامض)❌ (خطوتين: تحويل→مسودة ثم ترحيل)قرار مالك (اختياري WP)
صلاحية المحاسب للتحويل/الترحيل«المحاسب يحوّل»❌ المحاسب مالوشقرار مالك (توزيع صلاحيات)
ترحيل خصومات الرأس المركّبة d1/d2/d3 (9123)❌ عرض السعر مفهوش الأعمدة ديغير مطبّق (تُدخل على المسودة لو لزم)

الخلاصة: الفجوة الحقيقية صغيرة وواضحة = زر واحد في الواجهة يربط الـendpoint الموجود بالمستخدم، + قرارَي صلاحيات/خطوة-واحدة. مفيش أي إعادة بناء للباك.

5 الملفات المتأثرة والاعتماديات

الطبقةالملفالتغيير
FEfeatures/sales/quotations/quotations.component.htmlزر «تحويل لفاتورة» في عمود الإجراءات (للعرض المقبول، صلاحية sales.invoices.create)
FEfeatures/sales/quotations/quotations.component.tsهاندلر يدِسباتش convertQuotationToInvoice (موجود) + تأكيد + توست + تنقّل للمسودة الجديدة
FEstore/sales/quotations/quotations.effects.ts:179غالبًا لا تغيير (الـeffect موجود)؛ ممكن نضيف تنقّل بعد النجاح
FEquotation-view/quotation-view.component.html(اختياري) نفس الزر في شاشة العرض التفصيلية
FEassets/i18n/ar.json · en.jsonمفتاح SALES.CONVERT_TO_INVOICE
BERolePermissionSeeder.php(لو المالك وافق) منح المحاسب/المدير sales.invoices.create/post — منح غير كاسر

اعتماديات موجودة تُعاد استخدامها كما هي: الـendpoint، الـPostSalesInvoice، شاشة الفاتورة (زر الترحيل + بادج «غير مصروف»)، إعدادات «التسليم» (9121).

6 الحالات الحدّية

الحالةالسلوك الحالي
عرض سعر مش «مقبول»الـendpoint يرفض بـ422؛ الزر لازم يظهر للمقبول فقط (زي زر «تحويل لأمر»).
عرض سعر اتحوّل قبل كدهيبقى Converted → يفشل شرط «المقبول» → مايتحوّلش مرتين. (نخفي الزر بعد التحويل.)
مندوب محصور (own-scoped)يقدر يحوّل عروضه هو بس (الباك بيفرض ده :761).
عرض السعر مخزنه فاضيالفاتورة تاخد مخزن الرأس؛ لو فاضي → يقع على الإعداد sales.default_warehouse_id عند الترحيل/الصرف. (سؤال 3.)
عرض فيه أصناف خدمية (بلا مخزون)إذن الصرف بيتعامل معاها زي أي فاتورة عادية (سلوك 9121 القائم).
خصومات مركّبة على الرأسعرض السعر مفهوش d1/d2/d3؛ تُدخل يدويًا على المسودة قبل الترحيل لو محتاجها.
الترحيل غير قابل للتراجعلذلك الخطوتين (تحويل→مسودة، مراجعة، ترحيل) هي التصميم الأأمن — الترحيل يثبّت قيود + مخزون.

7 خطة التنفيذ (WPs)

WP1 — زر «تحويل لفاتورة» في الواجهة FEجوهر التذكرة. زر في عمود إجراءات عرض السعر المقبول، gated sales.invoices.create، يدِسباتش الأكشن الموجود، وبعد النجاح يفتح مسودة الفاتورة الجديدة (زي ما «تحويل لأمر» بيفتح الأمر). اختبار: build أخضر + جربة حيّة عرض→مسودة.

WP2 — توزيع الصلاحيات BE (قرار مالك) — لو المالك حدّد إن المحاسب/المدير يحوّل/يرحّل، نمنحهم الصلاحيات في السيدر (منح غير كاسر). اختبار: seeder + تأكيد الأدوار.

WP3 (اختياري) — زر «تحويل وترحيل» بخطوة واحدة FE+BE — لو المالك عايز «مباشر» فعلاً: زر بيحوّل ثم يرحّل في خطوة (يستدعي endpointين موجودين بالتتابع، أو endpoint مجمّع). [FIN] لأنه بيثبّت قيود+مخزون فورًا — يحتاج مراجعة. توصيتنا: نبدأ بالخطوتين (WP1) والـone-click اختياري لو طُلب.

8 قرارات تحتاج المالك

1) خطوة واحدة ولا خطوتين؟
التحويل يعمل مسودة فاتورة (تتراجع/تتعدّل قبل الترحيل) والمستخدم يرحّلها بعد المراجعة — ولا زر واحد «تحويل وترحيل مباشر» يثبّت القيود والصرف فورًا؟
✅ التوصية: خطوتين (تحويل→مسودة ثم ترحيل) — أأمن لأن الترحيل غير قابل للتراجع (قيود + مخزون). نضيف الـone-click لاحقًا لو حبيت.
2) مين الدور اللي يحوّل ويرحّل؟
حاليًا المحاسب والمدير مالهومش صلاحية التحويل ولا الترحيل ولا اعتماد الصرف (المالك بس). تحب نمنح المحاسب صلاحية التحويل والترحيل؟ ومين يعتمد إذن الصرف — أمين المخزن (الوضع الصحي)؟
✅ التوصية: المحاسب/المدير = تحويل + ترحيل؛ اعتماد إذن الصرف يفضل لأمين المخزن (فصل المهام).
3) مخزن الفاتورة المحوّلة
الفاتورة بتاخد مخزن رأس عرض السعر. لو عرض السعر مخزنه فاضي — يقع على إعداد sales.default_warehouse_id ولا نطلب اختيار المخزن قبل التحويل؟
✅ التوصية: مخزن الرأس، ويقع على الإعداد الافتراضي لو فاضي (سلوك الفواتير القائم).
4) اعتماد إذن الصرف تلقائي ولا يدوي؟
إذن الصرف الناتج عن الفاتورة المحوّلة — يستنى اعتماد أمين المخزن (بادج «غير مصروف» لحد ما يعتمد — سلوك 9121) ولا auto-approve فوري؟
✅ التوصية: يستنى اعتماد أمين المخزن (رقابة مخزنية حقيقية) — وهو الإعداد الافتراضي في 9121.

9 معاينة الواجهة المتوقّعة

التغيير الوحيد في الواجهة = زر «تحويل لفاتورة» في عمود إجراءات عرض السعر المقبول (واختياريًا في شاشة العرض). تحت: قبل → بعد.

قبل (الحالي)

عروض الأسعارQUO-000042
QUO-000042
العميل: بلاك سيركل
مقبول
١٢٬٥٠٠ ج
عرض تحويل لأمر
↑ مفيش زر «تحويل لفاتورة» — الفلو مش قابل للوصول

بعد (المقترح — WP1)

عروض الأسعارQUO-000042
QUO-000042
العميل: بلاك سيركل
مقبول
١٢٬٥٠٠ ج
عرض تحويل لأمر تحويل لفاتورة
↑ الزر الجديد → يفتح مسودة الفاتورة على طول

وبعد الترحيل (موجود بالفعل — 9121)

فاتورة بيعINV-000108 · مسودة → مرحّلة
INV-000108
من عرض QUO-000042
مرحّلة
غير مصروف
عرض
↑ بادج «غير مصروف» لحد ما أمين المخزن يعتمد إذن الصرف → يبقى «مصروف»
الخلاصة النهائية: الفلو اللي العميل عايزه صحيح ومقبول ومبني 90% منه. الناقص = زر واحد في الواجهة (WP1) يربط endpoint موجود بالمستخدم + قرارَي صلاحيات وسلوك (قسم 8). مفيش إعادة بناء ولا مخاطرة على الباك.