تحليل فجوات · مرحلة بحث بلا كود · مبني على تدقيق ISS-2026-9253 ومُتحقَّق منه على الكود الحالي
المنتج اللي له ألوان أو مقاسات ماينفعش يتباع ولا يتشترى بلون محدّد من شاشات المبيعات والمشتريات — مافيش منتقي متغيّر أصلًا في أي منها. وحتى لو المتغيّر اتحفظ بطريقة تانية، ولا طباعة واحدة بتعرضه، فسطرين لنفس المنتج بلونين مختلفين بيطلعوا متطابقين حرفيًا في الفاتورة المطبوعة — العميل يستلم فاتورة مايعرفش منها استلم إيه.
stock_balances_product_variant_warehouse_unique، متأكَّد بـSHOW INDEX على قاعدة التطوير.GET /core/products/{id}/variants بيرجّع الاسم المحلّي والـSKU والباركود والسعر الإضافي. صفر شغل باك إند للقائمة المنسدلة.⇒ الفرضية الحاكمة للتذكرة صحيحة: طبقة البيانات كاملة، والشغل إدخال وعرض وطباعة بس.
الجدول المشترك لسطور المستندات مابيرسمش عمود متغيّر من نفسه — بيوفّر خطّافين اختياريين:
visibleForRow?: (index: number) => boolean // transaction-line.types.ts:29 optionsByIndex?: (index: number) => readonly unknown[] // transaction-line.types.ts:38
شاشات المخزون الأربعة فعّلتهم؛ شاشات المبيعات والمشتريات لأ. يعني الميزة مش ناقصة — الشاشات مش مفعّلاها. وأي شاشة مستند جديدة تتعمل بكرة هتطلع بلا عمود متغيّر برضه، لحد ما حد يفعّل الخطّاف فيها.
| الطبقة | الموجود دلوقتي | المطلوب |
|---|---|---|
| قاعدة البيانات | كامل — أعمدة ومفاتيح أجنبية وفهارس | لا شيء |
| التحويلات بين المستندات | بتنقل المتغيّر | لا شيء |
| مسار قائمة المتغيّرات | موجود ومكتمل | لا شيء |
| إدخال المتغيّر في الشاشات | صفر منتقي في ٨ شاشات قابلة للتحرير | عمود منتقي معتمد على منتج الصف |
| الباركود | بيحلّ المتغيّر ثم يرميه | يمرّر المتغيّر للسطر |
| التحقّق في الباك إند | موجود بس ضعيف — exists مجرّد بلا تقييد بالشركة ولا بمنتج السطر | يستخدم الـtrait المراجَع الموجود |
| ريسورس فاتورة البيع | بيرجّع الاسم المحلّي بالفعل | لا شيء |
| ريسورس فاتورة الشراء | رقم بلا اسم، ومفيش تحميل مسبق في أي مسار — ولا حتى show | حقل الاسم + التحميل المسبق |
| الطباعة | صفر ذكر للمتغيّر في الطبقة المشتركة | حقل واحد مشترك + سطر لكل مستند |
التدقيق قال إن كونترولري الطباعة في الباك إند مابيضفوش المتغيّر. ده صحيح — لكن النتيجة منسوبة لمكان غلط: الـSPA مابيناديش المسارات دي إطلاقًا (المستهلك الوحيد لأي مسار /print في الواجهة كلها هو موديول العيادة). وكمان خدمتا الفاتورتين بتنادوا مسار /{id}/pdf غير موجود أصلًا. ومفيش أي مسار Blade/DomPDF للمبيعات أو المشتريات.
الطباعة الحقيقية كلها في الواجهة: رد show() ← مُحوِّل لكل مستند ← باني صفوف مشترك واحد ← HTML في نافذة طباعة. ⇒ إصلاح كونترولرات الباك إند مش هيغيّر حاجة يشوفها المستخدم.
| ما قاله التدقيق | الواقع بعد التحقّق |
|---|---|
| «١٠ شاشات مبيعات ومشتريات بلا منتقي» | ٨ بس قابلة للتحرير. إذن التسليم وإذن الاستلام مالهمش محرّر سطور ولا FormArray — جداولهم عرض فقط وبيتولدوا من مستند مصدر بينقل المتغيّر. ⇒ شغلهم عرض وطباعة، مش منتقي. |
| «النمط واحد ويتكرّر» | المرتجعات مزدوجة. مرتجع البيع والشراء بيستخدموا الجدول المشترك في المسار المستقل، وجدولًا يدويًا في المسار المربوط بفاتورة — محتاج حمل وعرض لا اختيار. تعديلان مختلفان في نفس الملف. |
«اسم المتغيّر بيتحمّل في show لكل المستندات» | غلط لفاتورة الشراء: مفيش أي مسار بيحمّله — ولا show نفسه. وفاتورة البيع بالعكس سليمة تمامًا وبترجّع الاسم المحلّي. |
«product_variants = صفر صف» | بقى ٢ صف (اتعملوا 2026-07-26، بعد التدقيق) على منتج واحد «tshirt». لكن صفر سطر في كل جداول المبيعات والمشتريات العشرة ⇒ حجة «الإصلاح قبل دخول البيانات أرخص» لسه قائمة بالكامل. |
| (غير مذكور) | الباركود بيرمي المتغيّر: خدمة البحث بالباركود بترجّع variantId فعلًا، والفاتورتان بتاخدوا المنتج بس وبيرموه. سطح إدخال تاني لنفس الميزة. |
| (غير مذكور) | أداة جاهزة ومراجَعة: ValidatesLineVariantOwnership بتتحقّق إن المتغيّر تابع لمنتج السطر ولشركة المستخدم — مستخدمة في طلبين بس، وكل الـ٢٠ طلب مبيعات/مشتريات لسه على القاعدة الضعيفة. |
| الملف | التغيير |
|---|---|
| shared/print/print.interfaces.ts | حقل variantName? على عنصر الطباعة المشترك — سطر واحد يخدم كل المستندات |
| shared/print/print-helpers.ts | عرض المتغيّر جوّه خانة اسم المنتج الموجودة — مفيش عمود جديد ⇒ مفيش أي تغيير في التخطيط |
| shared/print/print-templates.ts | ⚠️ سكين الطباعة الحرارية عنده صفوفه الخاصة وبيتخطّى الباني المشترك — لازم يتلمس منفصل وإلا هيفضل يسقط المتغيّر بصمت |
| features/sales/invoices/invoices.component.ts | عمود المنتقي + تحميل كسول عند اختيار المنتج + الحمولة + الاستعادة عند التعديل + مسار الباركود |
| features/purchases/bills/bills.component.ts | نفسه (أبسط — بلا شارة مخزون) |
| */invoice-print.config.ts · bill-print.config.ts | سطر تحويل واحد لكل واحد |
| Modules/Purchases/…/PurchaseBillItemResource.php | إضافة الاسم المحلّي |
| Modules/Purchases/…/PurchaseBillController.php | تحميل مسبق للعلاقة (على الأقل في show) |
| Modules/Sales/…/StoreSalesInvoiceRequest.php + Update | استبدال exists المجرّد بالـtrait المراجَع |
| Modules/Purchases/…/StorePurchaseBillRequest.php + Update | نفسه |
| core/services/doc-config.service.ts | تسجيل العمود عشان يبقى قابل للإخفاء/الترتيب من إعدادات المستندات زي باقي الأعمدة |
| # | الصنف | الوحدة | الكمية | السعر | الإجمالي |
|---|---|---|---|---|---|
| 1 | تي شيرت قطن PRD-17156 | قطعة | 10 | 120.00 | 1,200.00 |
| 2 | تي شيرت قطن PRD-17156 | قطعة | 5 | 120.00 | 600.00 |
سطران متطابقان — محدش يعرف ده أحمر وده أخضر.
| # | الصنف | اللون/المقاس | الوحدة | الكمية | السعر | الإجمالي |
|---|---|---|---|---|---|---|
| 1 | تي شيرت قطن PRD-17156 | أحمر ▾ | قطعة | 10 | 120.00 | 1,200.00 |
| 2 | تي شيرت قطن PRD-17156 | أخضر ▾ | قطعة | 5 | 120.00 | 600.00 |
| 3 | قلم جاف PRD-2201 | — لا ينطبق — | علبة | 2 | 35.00 | 70.00 |
الصف ٣ منتجه بلا متغيّرات ⇒ الخانة فاضية (نفس سلوك شاشات المخزون الأربعة الحالي). خيارات كل صف بتتحمّل من منتج الصف نفسه.
| # | الصنف | الوحدة | الكمية | السعر | الخصم | الإجمالي |
|---|---|---|---|---|---|---|
| 1 | تي شيرت قطن PRD-17156 | قطعة | 10 | 120.00 | 0% | 1,200.00 |
| 2 | تي شيرت قطن PRD-17156 | قطعة | 5 | 120.00 | 0% | 600.00 |
| # | الصنف | الوحدة | الكمية | السعر | الخصم | الإجمالي |
|---|---|---|---|---|---|---|
| 1 | تي شيرت قطن أحمر PRD-17156 | قطعة | 10 | 120.00 | 0% | 1,200.00 |
| 2 | تي شيرت قطن أخضر PRD-17156 | قطعة | 5 | 120.00 | 0% | 600.00 |
لأن الإضافة داخل الخانة الموجودة، كل المستندات (١٤ نوع) وكل قوالب A4 بتاخد التعديل تلقائيًا — والقوالب المخصّصة اللي عملها المستخدم كمان.
| الحالة | المعالجة |
|---|---|
| منتج بلا متغيّرات | الخانة فاضية والحمولة بتبعت null — نفس سلوك شاشات المخزون الحالي بالظبط |
| تغيير منتج الصف بعد اختيار لون | المتغيّر يتصفّر إجباريًا (نمط شاشات المخزون) وإلا يفضل لون منتج تاني |
| تعديل مستند قديم فيه متغيّر | لازم تحميل الخيارات قبل رسم القائمة وإلا القيمة تتفقد — الشاشات الأربعة بتعمل كده صراحةً |
| مستند اتحوّل من مصدر (أمر ← فاتورة) | المتغيّر بينتقل بالفعل — المطلوب إنه ما يضيعش عند إعادة الحفظ |
| شركة رتّبت أعمدة الشبكة قبل كده | ⚠️ العمود الجديد هيظهر في آخر الشبكة مش جنب الصنف — لأن الترتيب المحفوظ مافيهوش المفتاح الجديد |
| الطباعة الحرارية | ⚠️ صفوفها مستقلة — لو ما اتلمستش هتفضل تسقط المتغيّر بصمت |
| الاسم العربي للمتغيّر فاضي | المتغيّرين الموجودين على الجهاز name_ar = NULL ⇒ العربي والإنجليزي هيطلعوا واحد ومش هينفع نتحقّق من التعريب إلا بمتغيّر تجريبي بالعربي |
⚠️ عيب سابق مستقل رصدناه في الطريق: زر الطباعة في قائمة فواتير الشراء بيطبع الصف كما هو من القائمة، والقائمة مابترجعش السطور أصلًا ⇒ الطباعة دي بتطلع بجدول أصناف فاضي النهارده. مالوش علاقة بالمتغيّرات لكنه هيبلع أي شغل متغيّرات على الزر ده.
| # | النطاق | الريبو |
|---|---|---|
| ١ | الطباعة في الطبقة المشتركة — حقل واحد + عرض داخل خانة الصنف + سكين الحرارية | FE |
| ٢ | فاتورة البيع: عمود المنتقي + الحمولة + الاستعادة + الباركود + التحقّق بالـtrait | FE + BE |
| ٣ | فاتورة الشراء: نفسه + إصلاح الريسورس والتحميل المسبق (بلاهم مفيش اسم يتطبع أصلًا) | FE + BE |
| ٤ | تسجيل العمود في إعدادات المستندات | FE |
| ٥ | اختبارات — صفر تغطية للمتغيّرات في المبيعات والمشتريات حاليًا | BE |
| ٦ | (بعد تجربتك) الست شاشات الباقية + المرتجعات مزدوجة النمط + عرض إذن التسليم والاستلام | FE + BE |
additional_price والشاشات الحالية بتتجاهله. يتطبّق تلقائيًا على سعر السطر في المبيعات ولا يفضل متجاهَل؟مرحلة بحث — صفر كود وصفر migration. التنفيذ يبدأ بعد اعتماد النطاق والإجابة على القرارات أعلاه.