١. المطلوب (بكلامك)
- فحص دقيق للشق المحاسبي: طرق الدفع بتشتغل إزاي وإيه اللي بيحصل فعلاً.
- نخلي كارت الفيزا هو الافتراضي.
- العميل ممكن يدفع دفعة جزئية ويكمّل بعدين.
- العميل ممكن يدفع بـ طريقتين دفع في الفاتورة الواحدة (split payment).
- لو العميل عليه فلوس، ما ينفعش يعمل Release للتحاليل ويتبعت — على الأقل يحتاج كونفيرم من الأدمن.
٢. الوضع الحالي (الفحص الدقيق)
✓ دورة الفاتورة + الدفع على مستوى الـ Backend سليمة
- إنشاء الطلب → فاتورة (draft) تتولّد تلقائيًا → تتـ post (لو الإعداد مفعّل) → تتسجّل دفعة.
- الفاتورة فيها:
subtotal,discount_amount,tax_amount(الـ VAT),total,amount_paid,balance_due. - الدفعة (
LabPayment): كل دفعة بتعمل قيد محاسبي عبرPostLabPaymentوبتقلّلbalance_dueوتعيد حساب حالة السداد. - الدفع الجزئي + إكمال لاحقًا مدعوم أصلاً: ممكن تضيف أكتر من دفعة على نفس الفاتورة من شاشة
/lab/payments؛ كل دفعة بتقلّل المتبقّي. والـ BE بيرفض الدفع الزائد (amount > balance_due → 422). - الدفع بطريقتين مدعوم على مستوى البيانات: ممكن دفعتين بطريقتين مختلفتين على نفس الفاتورة (صفّين
LabPayment).
BE: LabPaymentController::store() · PostLabPayment · LabInvoice (balance_due)
✓ شاشة المدفوعات (/lab/payments) بتسجّل دفعات لاحقة صح
بتبعت lab_invoice_id + payment_method بقيمها الصح (cash / visa / bank_transfer)، فالدفع المتأخّر على فاتورة قائمة شغّال.
FE: features/lis/payments/lis-payments.component.ts
✗✗ خطأ حرج: الدفع من شاشة الـ Request (الـ wizard) مكسور CRITICAL
الـ wizard وقت إنشاء الطلب بيحاول يسجّل دفعة لكن بيبعت أسماء/قيم حقول غلط، فالطلب الـ BE بيرفض الدفعة (422) والكود بيبلع الخطأ ويكمّل (error: () => this.onOrderSuccess()) — يعني الطلب بيتعمل والدفعة مش بتتسجّل والمتبقّي بيفضل كامل من غير ما حد يلاحظ.
| الحقل اللي الـ wizard بيبعته | اللي الـ BE متوقّعه | النتيجة |
|---|---|---|
invoice_id | lab_invoice_id (required) | الدفعة مرفوضة |
| — | date (required) | ناقص → مرفوضة |
payment_method: 'card' | enum: 'visa' | قيمة غير صالحة |
bank_account_id = ba.id | exists:accounts,id | id غلط |
receiving_account_id | required ✓ | تمام |
FE: request-wizard-v2.component.ts → recordPayment() (≈ سطر 1051-1082)
BE: StoreLabPaymentRequest.php (الحقول الصح)
✗ مفيش أي منع للـ Release لو عليه فلوس BACKEND
LabResultController::release() و bulkRelease() بيفحصوا حالة النتيجة بس (canRelease()) — مفيش أي فحص لـ balance_due بتاع فاتورة الطلب. يعني أي حد يقدر يعمل Release ويبعت النتيجة حتى لو الفاتورة متبقّي عليها مبلغ.
BE: LabResultController.php:448 release() · :953 bulkRelease()
✗ الافتراضي دلوقتي Cash مش Visa FRONTEND
paymentMethod = signal<'cash' | 'card' | 'bank_transfer'>('cash');
القيمة 'card' أصلاً غلط (المفروض 'visa')، والافتراضي 'cash'.
FE: request-wizard-v2.component.ts:198
٣. الحلول المقترحة (أهداف — لسه مفيش كود)
حل ١ — إصلاح دفع الـ wizard + Visa افتراضي FRONTEND
- تغيير الـ type والافتراضي:
'cash' | 'visa' | 'bank_transfer'والافتراضي'visa'. - تصحيح payload الدفعة:
lab_invoice_idبدلinvoice_id، إضافةdate، استخدام'visa'، وتصحيحbank_account_id/receiving_account_idحسب ما الـ BE متوقّع. - إظهار خطأ حقيقي لو الدفعة فشلت (بدل ما نبلعه) عشان ما يحصلش طلب "مدفوع" وهو مش مدفوع.
حل ٢ — دفع جزئي + إكمال لاحقًا FRONTEND
- الـ BE بيدعمه أصلاً. في الـ wizard: لما
amountPaid < totalالطلب يتعمل والباقي يفضلbalance_due. - الإكمال لاحقًا من
/lab/payments(شغّال). ممكن نضيف "تحصيل" سريع من شاشة الطلبات/الفاتورة للفواتير اللي عليها متبقّي.
حل ٣ — دفع بطريقتين في فاتورة واحدة (Split) FRONTEND
- الـ BE بيدعم صفوف دفع متعددة. في الـ wizard: واجهة "تقسيم الدفع" — مثلاً مبلغ على Visa + مبلغ على Cash؛ عند الحفظ نعمل صفّين LabPayment على نفس الفاتورة.
- التحقق: مجموع الدفعتين ≤
total؛ كل صف يحدّد طريقته وحسابه المستلم. - (اختياري) endpoint مجمّع
payments/bulkفي الـ BE لو حبينا عملية واحدة بدل نداءين.
حل ٤ — منع الـ Release لو عليه فلوس (بموافقة أدمن) BACKEND FRONTEND
- BE: في
release()+bulkRelease()نفحصbalance_dueلفاتورة الطلب. لو > 0 نرجّع 422 برسالة واضحة — إلا لو فيه override. - الـ override: صلاحية (مثلاً
lis.results.release_unpaid) أو تأكيد أدمن (باسوورد/كونفيرم). الأدمن بس يقدر يعمل Release رغم المتبقّي. - الاستثناء: فواتير المعمل الخارجي B2B (الدفع آجل/مطالبات شهرية) — منطقي إنها مستثناة من المنع (أكّد ده في الأسئلة).
- FE: في شاشة الـ validation/results لو الـ Release اترفض بسبب الرصيد، نظهر dialog "الفاتورة عليها متبقّي X — يتطلب موافقة أدمن" مع زرّ تأكيد للأدمن.
٤. أسئلة محتاجة قرارك
س١ آلية موافقة الأدمن على الـ Release
(أ) صلاحية على الدور (الأدمن عنده lis.results.release_unpaid فيعمل Release عادي) · (ب) كونفيرم بباسوورد الأدمن وقت كل Release متبقّي · (ج) الاتنين. — اقتراحي: (أ) صلاحية أبسط وأوضح للأودِت.
س٢ فواتير المعمل الخارجي B2B
تتستثنى من منع الـ Release (لأن الدفع آجل بمطالبة شهرية)؟ — اقتراحي: نعم تتستثنى.
س٣ الدفع المقسّم — كام طريقة كحد أقصى؟
طريقتين بس كفاية ولا عدد مفتوح؟ — اقتراحي: مفتوح (واجهة تضيف صفوف دفع)، نبدأ بطريقتين عمليًا.
س٤ الدفع الجزئي وقت إنشاء الطلب
نسمح بـ "بدون دفع" (آجل) من الـ wizard للعميل العادي كمان، ولا الدفع إجباري؟ — اقتراحي: نسمح بالجزئي/الآجل والباقي balance_due.
٥. ترتيب التنفيذ المقترح
- FE حل ١ — إصلاح دفع الـ wizard (حرج، بيخلي الفلوس تتسجّل صح) + Visa افتراضي.
- BE حل ٤ — منع الـ Release على المتبقّي + صلاحية override.
- FE حل ٤ — dialog موافقة الأدمن في الـ validation/results.
- FE حل ٣ — واجهة الدفع المقسّم في الـ wizard.
- حل ٢ موجود أساسًا؛ نضيف زرّ "تحصيل" سريع للفواتير المتبقّية لو حبيت.