🧩 باكدجات الـB2B بسعر مباشر — تحليل شامل والتصميم المقترح
الميزة المطلوبة: باقة = مجموعة تحاليل بسعر مباشر واحد، أقدر أعيّنها لأكتر من شريك B2B (المعامل الخارجية — علاقة inbound: بيبعتوا لنا مرضى/طلبات). الباقة تتفوتر سطر واحد بسعرها المباشر — من غير أي تقسيم/توزيع على المكوّنات. التحاليل بتتعمل في المعمل عادي، لكن الفوترة والإيراد على مستوى الباقة.
🔄 نسخة v2 (3 يوليو) — بعد توضيحك: غيّرنا من "سعر باقة موزّع على المكوّنات" (v1) إلى سعر مباشر بلا تقسيم + سطر فاتورة واحد + تعيين لأكتر من شريك. ده بيبسّط المحاسبة ويلغي خطر "ثبات المبلغ" بالكامل.
👈 الفرق الجوهري في v2: الباقة الحالية (Retail) بتوزّع السعر على المكوّنات. باقة الـB2B الجديدة اللي إحنا عايزينها مالهاش توزيع — سعر مباشر واحد + سطر فاتورة واحد. فده وضع فوترة جديد على الباقة، مش نفس سلوك الـRetail.
ملاحظة توافق v2: كل الآلة الحالية (فاتورة + قيد) شغّالة لكل تحليل (per-item). باقة B2B بسطر واحد محتاجة مسار سطر-باقة جديد (سطر فاتورة واحد + قيد واحد وقت الاكتمال) — ده أهم نقطة تكامل في v2 (§4).
2 الفجوة
الباقة ليها سعر عام واحد بيتوزّع — مفيش سعر مباشر بلا تقسيم، ومفيش تعيين للباقة على شريك B2B.
الفوترة/القيد B2B per-item بس — مفيش سطر باقة واحد ولا قيد باقة واحد.
بورتال/فلو الـB2B مابياخدش باقات خالص.
3 التصميم المقترح — سعر مباشر، سطر واحد، تعيين متعدد
3.1 نموذج البيانات
العنصر
التفاصيل
الباقة (نعيد استخدام lab_packages)
نضيف وضع فوترة: billing_mode = allocated (الحالي/Retail) أو direct (الجديد/B2B). في وضع direct السعر = سعر مباشر واحد للباقة (نستخدم package_price كسعر مباشر) — مفيش توزيع على المكوّنات.
ليه تعيين مباشر مش قايمة أسعار؟ "أحطها لكذا B2B" = علاقة باقة ↔ شركاء مباشرة (many-to-many)، أبسط من إني أحط الباقة في قايمة وأعيّن القايمة. والسعر مباشر على الباقة (مع override اختياري لكل شريك). لو حبيت لاحقًا تدخّلها في قوايم الأسعار، الجدول ده يقدر يمتد.
الفوترة: سطر واحد للباقة (نضيف package_id + سعر على بند الفاتورة، أو نوع بند "package"). المكوّنات أسطر تنفيذ بصفر — مفيش تقسيم.
التنفيذ في المعمل: التحاليل بتظهر وتتجمّع وتترفع نتايجها عادي (الباقة مفهوم تجاري، مالهاش لازمة في شاشات المعمل — التحاليل هي اللي بتظهر).
opt-in: الباقة قابلة للطلب من الشريك بس لو مُعيّنة له (صف فعّال في lab_external_lab_packages).
3.3 الواجهة (FE)
شاشة الباقات: نضيف وضع الفوترة (موزّع/مباشر) + تبويب "الشركاء (B2B)" لتعيين الباقة لأكتر من معمل خارجي (مع سعر اختياري لكل شريك).
أو من شاشة المعمل الخارجي: تبويب "الباقات" يعيّن باقات للمعمل ده بسعرها/بسعر خاص.
بورتال الـB2B: الكتالوج يعرض الباقات المُعيّنة للشريك بسعرها؛ الطلب يمرّ بنفس خدمة الـBE.
4 المعالجة المحاسبية — قيد واحد للباقة (بلا تقسيم)
بما إن الباقة سطر واحد بسعر مباشر، الإيراد يتسجّل قيد واحد للباقة كلها — مش قيد لكل تحليل.
توقيت الاعتراف — عند اكتمال الباقة (رفع كل نتايجها)
الباقة = التزام أداء واحد (سعر واحد، مفيش تقسيم) → الإيراد يتحقق لما الباقة تتسلّم بالكامل = رفع كل نتايج مكوّناتها. قيد واحد ساعتها:
قيد الباقة عند اكتمالها — مثال: سعر مباشر 200، VAT 15% = 30
الحساب
مدين
دائن
ذمم المعمل الخارجي (Partner AR)
230.00
إيراد المختبر (Lab Revenue)
200.00
ض.ق.م المستحقة (VAT Payable)
30.00
قيد واحد · بلا توزيع · balanced · VAT بعد/على السعر المباشر
✅ إيراد صافي (Net) — مش contra-revenue (Fable 5 / IFRS 15): السعر المباشر هو سعر الصفقة؛ الفرق عن مجموع أسعار التحاليل مش خصم محاسبي، ده تسعير. متّسق مع خصومات B2B الحالية (بترحّل net). لو الإدارة عايزة تشوف "قيمة التوفير" — تقرير من (مجموع أسعار التحاليل − السعر المباشر) بلا مساس بالـGL.
⚠️ توقيت الاعتراف — قرار لازم: "عند اكتمال الباقة" هو الأنظف (إيراد وقت التسليم الكامل). بديل أبسط: الاعتراف عند الفوترة/الطلب (لو العمل بيحاسب مقدّم). التوصية: عند الاكتمال. حالة جزئية: لو مكوّن اتلغى/QNS ومكمّلش — سياسة صريحة: (أ) الباقة تتفوتر كاملة (المتفق عليه الباقة) لو التسليم مقبول، أو (ب) تتظبط. لازم تتحدّد.
نقطة التكامل الأساسية: الآلة الحالية per-item؛ محتاجين مسار سطر-باقة: (1) بند فاتورة واحد للباقة، (2) trigger اكتمال (آخر نتيجة تترفع) يرحّل قيد الباقة الواحد، (3) المطالبة الشهرية تجمّع سطر الباقة زي أي بند، (4) التحصيل/التخصيص زي ما هو (على مستوى الفاتورة).
5 قرارات مطلوبة منك
القرار
الخيارات
التوصية
السعر لكل شريك
سعر مباشر واحد للباقة لكل الشركاء · أو سعر مختلف لكل شريك
سعر مباشر + override اختياري لكل شريك (يغطّي الاتنين)
توقيت الاعتراف بالإيراد
عند اكتمال الباقة (كل النتايج) · أو عند الفوترة/الطلب
عند الاكتمال (إيراد وقت التسليم)
الحالة الجزئية (مكوّن ملغى/QNS)
تُفوتر كاملة · أو تتظبط
قرار صريح لازم — الافتراضي: كاملة (المتفق = الباقة)
دلالة الضريبة
السعر شامل VAT · أو غير شامل
غير شامل (تُضاف فوقه) — نكتبها في الشاشة
عرض المطالبة/الفاتورة
سطر باقة واحد · أو سطر باقة + مكوّنات معلوماتية
سطر باقة واحد (المكوّنات معلوماتية تحته اختياري)
وضع الباقة الحالية (Retail)
تفضل موزّعة · أو الكل يبقى مباشر
Retail تفضل موزّعة؛ billing_mode يفصل الاتنين
6 مراحل التنفيذ
المرحلة 1 — نواة الـBE:billing_mode على الباقة + جدول lab_external_lab_packages (تعيين + سعر) + خدمة حلّ السعر المباشر (opt-in) + مسار سطر-باقة في الفاتورة (بند واحد، مكوّنات بصفر للتنفيذ). مسار الموظّف بس. أساس
المرحلة 2 — المحاسبة:قيد الباقة الواحد عند اكتمالها (trigger آخر نتيجة) — مدين ذمم الشريك / دائن إيراد / دائن VAT. + سياسة الحالة الجزئية. + اختبار: قيد واحد = السعر المباشر + VAT.
المرحلة 3 — الواجهة: وضع الفوترة + تبويب تعيين الشركاء (سعر لكل شريك) في شاشة الباقات/المعمل الخارجي.
المرحلة 4 — البورتال + المطالبة: الكتالوج يعرض باقات الشريك بسعرها؛ الطلب بنفس خدمة الـBE؛ المطالبة تعرض سطر الباقة؛ تقرير "قيمة توفير الباقات".
🔴 أكبر خطر (اتغيّر عن v1): مش ثبات-المبلغ (اتلغى مع إلغاء التوزيع)، لكن تكييف آلة الفوترة/القيد per-item لتتعامل مع سطر باقة واحد + قيد واحد عند الاكتمال — لأن كل حاجة دلوقتي per-test. لازم trigger الاكتمال يكون موثوق (مايترحّلش مرتين، ومايتنسيش لو مكوّن اتلغى).
7 الحالات الحدّية والمخاطر
الحالة
المعالجة
ازدواجية الترحيل
قيد الباقة يترحّل مرة واحدة عند الاكتمال — idempotent (علم package_posted_at/journal_entry_id على سطر الباقة).
مكوّن ملغى/QNS
سياسة الاكتمال: هل "اكتمال" = كل المكوّنات غير الملغاة اترفعت؟ (التوصية: أيوه) → القيد يترحّل بالسعر الكامل. لو التسعير هيتظبط، ده يكسر "السعر المباشر" — يُفضّل يفضل كامل.
تغيّر تركيب الباقة
إضافة/حذف تحليل من باقة مُعيّنة بيغيّر اللي الشريك بياخده بنفس السعر → log/تنبيه (versioning خارج v1).
نفس التحليل داخل الباقة ومنفرد
لو التحليل مطلوب داخل الباقة (بصفر) ومنفرد (بسعر) في نفس الطلب — المنفرد يتحاسب عادي، والباقة سطرها المباشر. مفيش تجميع تلقائي.
الضريبة
السعر المباشر غير شامل VAT (نضيف 15%) — نكتبها صريحة.