توحيد نظام صور المنتجات في Moon ERP

تحليل جذري قبل التنفيذ · moonui4 · فرع hazemdev4 · 2026-07-20 · كل رقم هنا مقيس على البيئة الحيّة، مش مستنتج

خلاصة في ثلاث جمل: النظام فيه مساران للصور مش تلاتة — مسار عام صحيح تستخدمه كل المتحكّمات في الباك-إند، ومسار مرفقات خاص لا تستخدمه إلا واجهة الأدمن. التوحيد اللي طلبته متحقق بالفعل في الباك-إند؛ الخلل كله في طبقة الواجهة. وتطبيق الموبايل — أكّد المالك إنه يستهلك سرفيس الاستور — يقع على السطح الصحيح، فمفيش شغل إضافي ليه.

١ · المشكلة

شاشتا /app/core/products و/app/core/product-catalog مابتعرضش ولا صورة واحدة، رغم إن 1018 من 1024 منتج عندهم صورة مخزّنة فعلًا. وبالتوازي، رفع صورة من شاشة المنتجات بيرجّع HTTP 422.

المطلوب من المالك حرفيًا: «الصور تبقى من مكان واحد — سواء رفع من المنتجات أو رفع من الاستور، يترفع في نفس المكان بنفس الآلية»، مع ملاحظة إضافية: «ممكن نعتمد أكتر على الاستور علشان في موبايل أبليكيشن أصلًا خلصان».

Two admin product screens render zero images although 1018 of 1024 products have one stored, and uploading an image returns 422. The owner wants a single upload location and mechanism across admin and store, and hints at leaning on the store API because a mobile app already exists.

٢ · الوضع الحالي — بالأدلة

٢.١ المسارات الموجودة فعلًا

المسارالآليةمكان التخزينقابل للعرض؟مين بيستخدمه
أ — مسار المنتج HandlesImageUpload uploads/products
قرص public
أيوه — رابط مباشر كل الباك-إند
ب — المرفقات AttachmentController attachments/{company}/{YYYY-MM}
قرص private
لأ — تنزيل مصادَق فقط واجهة الأدمن وحدها

١٦ متحكّم في الباك-إند بيستخدموا المسار (أ)، من ضمنهم المتحكّمان اللي يهمّانا:

Core/app/Http/Controllers/ProductController.php              ← شاشة المنتجات
WebStore/app/Http/Controllers/Admin/AdminProductController.php ← إدارة المتجر
اكتشاف يلغي نصف الشغل المتوقع: فيه HandlesImageUpload باسمين، وده كان بيبان ازدواج. لكن بتاع WebStore ٨ أسطر بيعيد تصدير بتاع الجذر حرفيًا:
trait HandlesImageUpload {
    use \App\Http\Controllers\Concerns\HandlesImageUpload;
}
يعني المتحكّمان يكتبان نفس الأعمدة على نفس القرص في نفس المجلد. التوحيد في الباك-إند قائم بالفعل — مش محتاج بناء، محتاج إثبات.

٢.٢ الأرقام على moonui4

القياسالقيمةالدلالة
products بصورة1018 / 1024المسار (أ) مليان
product_images11 صفالمعرض شبه فاضي
attachments0المسار اللي الواجهة بتقرأ منه فاضي تمامًا
GET /api/core/productsبترجّع image + image_urlالـAPI سليمة
صورة تجريبية / مستوردة200 image/png · 200 image/jpegالملفات موجودة وتُخدَم

يعني البيانات صح، والـAPI صح، والملفات صح — الواجهة ببساطة مابتبصّش على image_url إطلاقًا، بتنزّل blob من نظام المرفقات الفاضي.

٢.٣ سبب انكسار الرفع — وهو عيبي أنا

في WP-IMG-1 ضفت تحقّقًا يرفض رفع صورة كمرفق على منتج، لمنع تكرار الغلط الأصلي. لكن معرض صور المنتج في شاشة الأدمن بيرفع بالطريقة دي بالظبط (attachmentAccept شامل image/*). أعدت الاختبار على الحيّ:

POST /api/core/attachments  (png على منتج)  →  HTTP 422
"Product images cannot be uploaded as attachments …"
كتبت وقتها في اللِدجر تحذيرًا نصّه إن أي مسار يرفق صورًا على منتج «هينكسر»، وماروحتش أدوّر على المسار ده. كتابة التحذير مش فحص. المالك هو اللي مسك العيب، مش أنا.

٣ · المطلوب

  1. مكان واحد وآلية واحدة لصور المنتجات، أيًا كان مصدر الرفع.
  2. إصلاح الرفع المكسور من شاشة الأدمن.
  3. إرجاع العرض في الشاشتين.
  4. مُجاب: تطبيق الموبايل يستهلك api/store — السطح الصحيح — فالصور هتظهر عنده فور ظهورها في المتجر، بدون شغل إضافي.

٤ · الفجوة

الطبقةالحالةالشغل المطلوب
التخزين (قرص + مجلد)موحّدلا شيء
المخطط (products.image + product_images.position)موحّدلا شيء — ولا هجرة
الباك-إند (١٦ متحكّم)موحّد على trait واحدلا شيء
واجهة المتجرتقرأ المسار الصحيحلا شيء — منتهية ومتحقَّقة
واجهة الأدمن — العرضجزئيًاالكتالوج اتصلّح · شاشة المنتجات باقية
واجهة الأدمن — الرفعمكسور 422التحويل لنقاط نهاية المنتج

The unification the owner asked for already holds at the storage, schema, backend and storefront layers. The entire remaining gap is the admin frontend: one screen's display, and the upload path.

٥ · الملفات المتأثرة

src/app/features/products/products.component.ts       ← العرض + الرفع (الأساسي)
src/app/features/products/products.component.html     ← معاينة الشبكة والمعرض
src/app/core/services/product.service.ts              ← أُضيف فيه توصيل نقاط المنتج ✅
src/app/core/models/product.model.ts                  ← أُضيف image_url ✅
src/app/features/product-catalog/product-catalog.*    ← ✅ منتهي (44f1d9bb)

لا تُلمس:
Modules/Core/app/Http/Requests/StoreAttachmentRequest.php   ← الحارس يبقى
Modules/Core/app/Http/Controllers/AttachmentController.php  ← المستندات تفضل
projects/storefront/**                                      ← منتهٍ

٦ · الحالات الحدّية

٧ · خطة التنفيذ

WPالنطاقالحالة
IMG-3أعرض الكتالوج من image_url + نموذج + خدمة44f1d9bb
IMG-3بشاشة المنتجات: العرض ثم الرفع عبر نقاط المنتج · تضييق attachmentAcceptجزئي — محفوظ في stash@{0}
IMG-3جإثبات دائري: رفع من الأدمن → يظهر في الأدمن و في المتجرلم يبدأ
IMG-4مشروط بقرار الموبايل — توحيد سطح الـAPIمحجوب

٨ · قرارات تحتاج المالك

✅ مُجاب (2026-07-20) — تطبيق الموبايل يستهلك api/store

أكّد المالك إن التطبيق بيستخدم سرفيس الاستور. يعني الموبايل على السطح اللي بيقرأ products.image / product_images الصحيح — مفيش شغل إضافي، والصور هتظهر عنده فور ظهورها في المتجر. ده يلغي WP IMG-4 المحجوب ويحصر الباقي في شاشة أدمن واحدة.

نص السؤال الأصلي قبل الإجابة

مابعرفش عنه أي حاجة، ومفيش أي أثر ليه في الباك-إند. بحثت في المسارات والإعدادات وسجل التغييرات — صفر إشارة. والإجابة بتغيّر حجم الشغل جذريًا:

لو التطبيق يستهلك…الأثر
api/store 207 مسارمفيش شغل إضافي — المتجر بيقرأ المسار الصحيح أصلًا، والموبايل هيشوف الصور فورًا.
api/core 154 مسارلازم نتأكد إنه يقرأ image_url مش المرفقات — وإلا هيقع في نفس الحفرة.
سطح خاص بهمسار تالت غير معروف — لازم جرد قبل أي توحيد.

محتاج منك: التطبيق بيضرب على أنهي عنوان؟

قرارات أصغر

  1. حذف صورة من المعرض — لو مافيش نقطة نهاية، نضيف واحدة في الباك-إند (يخالف قيد «لا تغييرات باك-إند») ولا نأجّل الميزة؟ ترشيحي: نضيفها — معرض بلا حذف نصف ميزة.
  2. المرفقات القديمةattachments فاضي هنا، لكن التركيبات الأخرى مليانة. نبني ترحيلًا لمرة واحدة، ولا نكتفي بالتوحيد للأمام؟ ترشيحي: ترحيل مؤجَّل لتذكرة مستقلة — مش شرط لإصلاح moonui4.
  3. «الاعتماد أكتر على الاستور» — لو المقصود إن الأدمن يستهلك api/store، ده إعادة معمارية مش إصلاح صور، وتستاهل تحليلها لوحدها.

٩ · المعاينة والتوزيع

ما تم التحقق منه مقابل ما تم استنتاجه. متحقَّق بالقياس: أعداد الجداول · رد الـAPI · حالة 200 للصور · الـ422 للرفع · محتوى الـtrait الثمانية أسطر · قائمة الـ١٦ متحكّمًا · غياب أي أثر للموبايل. كان مستنتَجًا وبقى متحقَّقًا: تطبيق الموبايل يستهلك api/storeأكّده المالك 2026-07-20.