📦 سلة ورقة Salla Products Template Sheet

📊 8 مشاهدة

Salla Products Template Sheet

1–10: المعلومات الأساسية للمنتج

#اسم العمودالحقلنوع البياناتالاستخدام
1النوعtypeنصيحدد هل الصف منتج أم خيار
2أسم المنتجnameنصاسم المنتج
3تصنيف المنتجcategoryنصالتصنيف الهرمي للمنتج
4صورة المنتجimagesروابطصور المنتج، ويمكن أن تكون عدة روابط مفصولة بفواصل
5وصف صورة المنتجimage_descriptionنصوصف الصورة
6نوع المنتجproduct_typeنصنوع المنتج، مثل منتج جاهز
7سعر المنتجpriceرقمالسعر الأساسي للبيع
8الوصفdescriptionنص طويلالوصف التفصيلي للمنتج
9هل يتطلب شحن؟requires_shippingنعم/لاتحديد ما إذا كان المنتج يحتاج إلى شحن
10رمز المنتج SKUskuنصالمعرف الداخلي للمنتج/الخيار

مثال من الملف

المنتج الرئيسي:

النوع: منتج
أسم المنتج: ملابس سباحة
تصنيف المنتج: ملابس > رجالي
نوع المنتج: منتج جاهز
سعر المنتج: 45
هل يتطلب شحن؟ نعم
SKU: sku ABC

💰 11–20: التسعير والمخزون والشحن والعلامة التجارية

#اسم العمودالحقلنوع البياناتالاستخدام
11سعر التكلفةcost_priceرقمتكلفة شراء/إنتاج المنتج
12السعر المخفضsale_priceرقمالسعر بعد الخصم
13تاريخ بداية التخفيضsale_startتاريخ/وقتبداية فترة السعر المخفض
14تاريخ نهاية التخفيضsale_endتاريخ/وقتنهاية فترة السعر المخفض
15اقصي كمية لكل عميلmax_quantity_per_customerرقمالحد الأقصى للكمية التي يستطيع العميل شراءها
16إخفاء خيار تحديد الكميةhide_quantityنعم/لاإخفاء أداة اختيار الكمية
17اضافة صورة عند الطلبadd_image_on_requestنعم/لاالسماح بإضافة صورة مرتبطة بالطلب
18الوزنweightرقموزن المنتج
19وحدة الوزنweight_unitنصوحدة الوزن، مثل kg
20الماركةbrandنصالعلامة التجارية

القيم الموجودة في المنتج الرئيسي

سعر التكلفة: 40.9
السعر المخفض: 45
بداية التخفيض: 2026-09-13
نهاية التخفيض: 2026-09-13

أقصى كمية لكل عميل: 0
إخفاء خيار تحديد الكمية: نعم
إضافة صورة عند الطلب: نعم

الوزن: 10
وحدة الوزن: kg
الماركة: زارا

ملاحظة مهمة: حقل السعر المخفض يظهر في Excel كقيمة تاريخية داخلية مثل 1900-02-04، وهذا يحتاج إلى تنظيف/تصحيح قبل تحويل الملف إلى نظام إنتاجي.


📣 21–28: التسويق والبيانات التعريفية والضريبة

#اسم العمودالحقلنوع البياناتالاستخدام
21العنوان الترويجيpromotion_titleنصعنوان أو عبارة ترويجية للمنتج
22تثبيت المنتجpin_productنعم/لاإبقاء المنتج مثبتًا/بارزًا
23الباركودbarcodeنصBarcode الخاص بالمنتج
24السعرات الحراريةcaloriesرقمالسعرات، خصوصًا للمنتجات الغذائية
25MPNmpnنصManufacturer Part Number
26GTINgtinنصGlobal Trade Item Number
27خاضع للضريبة؟taxableنعم/لاتحديد خضوع المنتج للضريبة
28سبب عدم الخضوع للضريبةtax_exemption_reasonنصالسبب في حالة عدم خضوع المنتج للضريبة

البيانات الموجودة

العنوان الترويجي: فارغ

تثبيت المنتج: نعم

الباركود:
نص توضيحي فقط : المنتج ليس له قيمة باركود

السعرات الحرارية:
نص توضيحي فقط : يتم وضع السعرات الحرارية للمنتج إذا كان من نوع طعام

MPN: MPN
GTIN: GTIN

خاضع للضريبة؟ نعم

سبب عدم الخضوع للضريبة:
نص توضيحي فقط : يتم وضع سبب عدم الخضوع للضريبة في حال المنتج غير خاضع

وهنا واضح أن بعض القيم عبارة عن تعليمات داخل القالب وليست بيانات حقيقية.


🎨 29–32: الخيار الأول [1]

هذه المجموعة تمثل الخيار الأول للمنتج.

#اسم العمودالحقلالمعنى
29[1] الاسمoption_1_nameاسم الخيار
30[1] النوعoption_1_typeنوع الخيار
31[1] القيمةoption_1_valueقيمة الخيار
32[1] الصورة / اللونoption_1_image_colorصورة أو لون مرتبط بالخيار

في المنتج:

[1] الاسم: اللون الأساسي
[1] النوع: لون
[1] القيمة: ممنوع الكتابة في هذا الحقل في صف المنتج
[1] الصورة / اللون: ممنوع الكتابة في هذا الحقل في صف المنتج

أما في صفوف الخيارات الفعلية:

[1] الاسم: فارغ
[1] النوع: فارغ
[1] القيمة: أسود
[1] الصورة / اللون: #000000

أو:

[1] القيمة: أحمر
[1] الصورة / اللون: #FF0000

أو:

[1] القيمة: أزرق
[1] الصورة / اللون: #0000FF

إذًا الخيار الأول هنا هو:

اللون الأساسي → لون → أسود/أحمر/أزرق


📏 33–36: الخيار الثاني [2]

#اسم العمودالحقلالمعنى
33[2] الاسمoption_2_nameاسم الخيار الثاني
34[2] النوعoption_2_typeنوع الخيار الثاني
35[2] القيمةoption_2_valueقيمة الخيار
36[2] الصورة / اللونoption_2_image_colorصورة أو لون الخيار

في المنتج الرئيسي:

[2] الاسم: المقاس
[2] النوع: نص
[2] القيمة: ممنوع الكتابة في هذا الحقل في صف المنتج
[2] الصورة / اللون: ممنوع الكتابة في هذا الحقل في صف المنتج

وفي المتغيرات:

[2] القيمة: XL

أو:

[2] القيمة: L

إذن الخيار الثاني هو:

المقاس → نص → XL / L


🖼️ 37–40: الخيار الثالث [3]

#اسم العمودالحقلالمعنى
37[3] الاسمoption_3_nameاسم الخيار الثالث
38[3] النوعoption_3_typeنوع الخيار الثالث
39[3] القيمةoption_3_valueقيمة الخيار
40[3] الصورة / اللونoption_3_image_colorصورة مرتبطة بالخيار

في المنتج الرئيسي:

[3] الاسم: صورة الشعار
[3] النوع: صورة
[3] القيمة: ممنوع الكتابة في هذا الحقل في صف المنتج
[3] الصورة / اللون: ممنوع الكتابة في هذا الحقل في صف المنتج

وفي المتغيرات:

[3] القيمة: الصورة الأولى
[3] الصورة / اللون: رابط الصورة

أو:

[3] القيمة: الصورة الثانية
[3] الصورة / اللون: رابط الصورة

إذن الخيار الثالث هو:

صورة الشعار → صورة → الصورة الأولى/الثانية


🧩 البنية الحقيقية للمنتج

بعد تحليل الأعمدة مع الصفوف، يمكن تمثيل المنتج الأول هكذا:

ملابس سباحة
│
├── اللون الأساسي
│   ├── أسود #000000
│   ├── أحمر #FF0000
│   └── أزرق #0000FF
│
├── المقاس
│   ├── XL
│   └── L
│
└── صورة الشعار
    ├── الصورة الأولى
    └── الصورة الثانية

وهذا ينتج:

3 ألوان × 2 مقاسات × 2 صور = 12 تركيبة/Variant

وهي الموجودة في الملف:

sku-test-1
sku-test-2
sku-test-3
sku-test-4
sku-test-5
sku-test-6
sku-test-7
sku-test-8
sku-test-9
sku-test-10
sku-test-11
sku-test-12

📑 ورقة Categories, Types & Brands

الورقة الثانية تحتوي 3 أعمدة مرجعية:

#اسم العمودوظيفته
1ما يمتلكه متجرك الحالى من تصنيفاتقائمة تصنيفات المتجر
2أنواع المنتجات المتاحة حالياَأنواع المنتجات التي يمكن استخدامها
3ما يمتلكه متجرك الحالى من ماركات تجاريةقائمة العلامات التجارية

والأنواع الموجودة في الملف تشمل:

تبرع
مجموعة منتجات
بطاقة رقمية
منتج رقمي
أكل
خدمة حسب الطلب
منتج جاهز
منتج حجز
كفالة

🧠 الخلاصة الهيكلية

الـ 40 عمودًا ليست 40 معلومة منفصلة فقط؛ بل هي مقسمة منطقيًا إلى 8 طبقات:

01. Product Identity
    ├── النوع
    ├── اسم المنتج
    ├── التصنيف
    └── نوع المنتج

02. Media
    ├── صور المنتج
    └── وصف الصور

03. Pricing
    ├── السعر
    ├── سعر التكلفة
    ├── السعر المخفض
    └── فترة التخفيض

04. Shipping & Quantity
    ├── الشحن
    ├── أقصى كمية
    ├── إخفاء الكمية
    ├── صورة عند الطلب
    └── الوزن

05. Brand & Marketing
    ├── الماركة
    ├── العنوان الترويجي
    └── تثبيت المنتج

06. Identifiers
    ├── SKU
    ├── Barcode
    ├── MPN
    └── GTIN

07. Tax & Food
    ├── الضريبة
    ├── سبب الإعفاء
    └── السعرات الحرارية

08. Product Options
    ├── Option 1: اللون
    ├── Option 2: المقاس
    └── Option 3: الصورة

والأهم: الملف ليس مجرد جدول منتجات؛ إنه في الحقيقة Schema لاستيراد Product + Variants + Options + Reference Data.

في الخطوة التالية أستطيع إعادة كتابة هذه الـ40 خانة في جدول احترافي كامل جدًا يحتوي لكل حقل: الاسم العربي + الاسم التقني المقترح + نوع البيانات SQL + Required/Optional + مثال + قواعد التحقق Validation + هل يخص Product أم Variant + علاقته بقاعدة البيانات. وهذا سيكون أساسًا ممتازًا لتحويل القالب إلى نظام تجارة إلكترونية مثل TwistTaste Mart.

استخراج الأعمدة الأربعين الفعلية من ورقة Salla Products Template Sheet، وسأميز بين اسم الحقل الأصلي وبين الاسم التقني المقترح حتى لا نخلط بين قالب Salla وتصميم قاعدة بيانات جديدة.

📦 قاموس الحقول الكامل — 40 حقلًا

#اسم العمود الأصليالاسم التقني المقترحنوع البياناتالمستوىمطلوب؟مثال من الملفالوصف / قاعدة الاستخدام
1النوعtypeENUM / VARCHARProduct / Variantنعممنتج / خياريحدد هل الصف منتج رئيسي أم Variant/خيار
2أسم المنتجproduct_nameVARCHAR(255)Productنعمملابس سباحةالاسم الظاهر للمنتج
3تصنيف المنتجcategoryVARCHAR / PathProductنعمملابس > رجاليمسار تصنيف المنتج
4صورة المنتجproduct_imagesTEXT / URLsProductاختياري3 روابطروابط صور المنتج، ويمكن أن يحتوي الحقل على عدة صور
5وصف صورة المنتجimage_descriptionTEXTProductاختياريوصف صورة المنتجوصف/نص بديل للصورة
6نوع المنتجproduct_typeENUM / VARCHARProductنعممنتج جاهزنوع المنتج وفق أنواع المنصة
7سعر المنتجpriceDECIMAL(12,2)Product / Variantنعم45سعر البيع الأساسي
8الوصفdescriptionLONGTEXTProductاختياريفارغالوصف التفصيلي للمنتج
9هل يتطلب شحن؟requires_shippingBOOLEANProductنعمنعميحدد هل المنتج مادي ويحتاج إلى شحن
10رمز المنتج skuskuVARCHAR(100)Product / Variantنعمsku ABCمعرف SKU الفريد
11سعر التكلفةcost_priceDECIMAL(12,2)Product / Variantاختياري40.9تكلفة المنتج لحساب الهامش والربحية
12السعر المخفضsale_priceDECIMAL(12,2)Product / Variantاختياري45*سعر البيع أثناء التخفيض
13تاريخ بداية التخفيضsale_start_dateDATETIMEProduct / Variantاختياري2026-09-13بداية صلاحية السعر المخفض
14تاريخ نهاية التخفيضsale_end_dateDATETIMEProduct / Variantاختياري2026-09-13نهاية صلاحية السعر المخفض
15اقصي كمية لكل عميلmax_quantity_per_customerINTProduct / Variantاختياري0الحد الأعلى لكمية الشراء للعميل
16إخفاء خيار تحديد الكميةhide_quantity_selectorBOOLEANProductاختيارينعمإخفاء واجهة اختيار الكمية
17اضافة صورة عند الطلبallow_order_imageBOOLEANProductاختيارينعمالسماح للعميل بإرفاق صورة مع الطلب
18الوزنweightDECIMAL(10,3)Product / Variantاختياري10وزن المنتج
19وحدة الوزنweight_unitENUM / VARCHARProduct / Variantاختياريkgوحدة الوزن مثل kg / g
20الماركةbrandVARCHAR(255)Productاختياريزاراالعلامة التجارية
21العنوان الترويجيpromotion_titleVARCHAR(255)Productاختياريفارغعنوان تسويقي قصير
22تثبيت المنتجis_pinnedBOOLEANProductاختيارينعمتثبيت المنتج وإبرازه
23الباركودbarcodeVARCHAR(100)Product / Variantاختياريtest barcode optionalرمز Barcode للمنتج
24السعرات الحراريةcaloriesDECIMAL(10,2)Product / Variantاختيارينص توضيحيالسعرات، خصوصًا للمنتجات الغذائية
25MPNmpnVARCHAR(100)Product / VariantاختياريMPNManufacturer Part Number
26GTINgtinVARCHAR(100)Product / VariantاختياريGTINGlobal Trade Item Number
27خاضع للضريبة ؟is_taxableBOOLEANProductنعمنعمتحديد خضوع المنتج للضريبة
28سبب عدم الخضوع للضريبةtax_exemption_reasonTEXTProductمشروطنص توضيحييستخدم عندما يكون المنتج غير خاضع للضريبة
29[1] الاسمoption_1_nameVARCHAR(255)Optionمشروطاللون الأساسياسم الخيار الأول
30[1] النوعoption_1_typeENUM / VARCHAROptionمشروطلوننوع الخيار الأول
31[1] القيمةoption_1_valueVARCHAR(255)Variantمشروطأسودقيمة الخيار الأول
32[1] الصورة / اللونoption_1_visualVARCHAR / URL / HEXVariantمشروط#000000لون HEX أو رابط صورة حسب نوع الخيار
33[2] الاسمoption_2_nameVARCHAR(255)Optionمشروطالمقاساسم الخيار الثاني
34[2] النوعoption_2_typeENUM / VARCHAROptionمشروطنصنوع الخيار الثاني
35[2] القيمةoption_2_valueVARCHAR(255)VariantمشروطXLقيمة الخيار الثاني
36[2] الصورة / اللونoption_2_visualVARCHAR / URL / HEXVariantمشروطفارغقيمة مرئية إضافية إذا كان نوع الخيار يسمح بذلك
37[3] الاسمoption_3_nameVARCHAR(255)Optionمشروطصورة الشعاراسم الخيار الثالث
38[3] النوعoption_3_typeENUM / VARCHAROptionمشروطصورةنوع الخيار الثالث
39[3] القيمةoption_3_valueVARCHAR(255)Variantمشروطالصورة الأولىقيمة الخيار الثالث
40[3] الصورة / اللونoption_3_visualVARCHAR / URL / HEXVariantمشروطرابط صورةالصورة المرتبطة بقيمة الخيار

ملاحظة مهمة حول *: Excel يخزن بعض القيم الرقمية في الملف بتنسيق تاريخ. مثلًا القيمة الموجودة في حقل السعر المخفض تظهر برمجيًا كتاريخ Excel مثل 1900-02-04، لذلك عند بناء Importer يجب قراءة القيمة الرقمية الأصلية والتنسيق وليس اعتبارها تاريخًا حقيقيًا تلقائيًا.


🧬 تقسيم الـ40 حقلًا معماريًا

بدل التعامل معها كـ40 عمودًا مسطحًا، الأفضل فهمها كـ 8 Domains:

PRODUCT
│
├── 01. Identity
│   ├── type
│   ├── product_name
│   ├── category
│   └── product_type
│
├── 02. Media
│   ├── product_images
│   └── image_description
│
├── 03. Content
│   └── description
│
├── 04. Pricing
│   ├── price
│   ├── cost_price
│   ├── sale_price
│   ├── sale_start_date
│   └── sale_end_date
│
├── 05. Inventory / Shipping
│   ├── requires_shipping
│   ├── sku
│   ├── max_quantity_per_customer
│   ├── hide_quantity_selector
│   ├── weight
│   └── weight_unit
│
├── 06. Brand / Marketing
│   ├── brand
│   ├── promotion_title
│   └── is_pinned
│
├── 07. Identification / Tax
│   ├── barcode
│   ├── calories
│   ├── mpn
│   ├── gtin
│   ├── is_taxable
│   └── tax_exemption_reason
│
└── 08. Options / Variants
    ├── Option 1
    │   ├── name
    │   ├── type
    │   ├── value
    │   └── visual
    │
    ├── Option 2
    │   ├── name
    │   ├── type
    │   ├── value
    │   └── visual
    │
    └── Option 3
        ├── name
        ├── type
        ├── value
        └── visual

🔗 العلاقة بين Product و Variant

وهذه أهم نقطة في الملف.

الصف:

منتج | ملابس سباحة

هو Parent Product.

أما:

خيار | ملابس سباحة | sku-test-1

فهو Variant تابع للمنتج.

مثال:

Product
└── ملابس سباحة
    │
    ├── Option: اللون الأساسي
    │   ├── أسود
    │   ├── أحمر
    │   └── أزرق
    │
    ├── Option: المقاس
    │   ├── XL
    │   └── L
    │
    └── Option: صورة الشعار
        ├── الصورة الأولى
        └── الصورة الثانية

وبالتالي لدينا:

3 × 2 × 2 = 12 Variants

وكل Variant يمكن أن يمتلك بياناته الخاصة:

Variant
├── SKU
├── Price
├── Cost Price
├── Sale Price
├── Barcode
├── MPN
├── GTIN
├── Option Values
└── Image

وهذا واضح جدًا في الملف؛ فمثلًا sku-test-1 يمثل تركيبة:

اللون = أسود
المقاس = XL
الصورة = الصورة الأولى
السعر = 55
التكلفة = 22.94

بينما sku-test-12 يمثل:

اللون = أزرق
المقاس = L
الصورة = الصورة الثانية
السعر = 100
التكلفة = 90.94

⚠️ حقول تحتاج معالجة قبل تحويلها إلى نظام Production

هناك 5 نقاط أعتبرها مهمة جدًا:

1. type

القيم الحالية:

منتج
خيار

الأفضل داخليًا:

product
variant

مع الاحتفاظ بالترجمة في طبقة العرض.

2. category

القيمة:

ملابس > رجالي

ليست أفضل صيغة لقاعدة البيانات.

الأفضل:

categories
├── ملابس
└── رجالي

ثم علاقة:

product_categories

3. الصور

الحقل الحالي يجمع عدة URLs في خلية واحدة:

URL1,URL2,URL3

الأفضل في النظام:

product_images
----------------
id
product_id
url
sort_order
alt_text
is_primary

4. Options

وجود:

[1]
[2]
[3]

مناسب لـ Excel Import Template، لكنه ليس التصميم المثالي لقاعدة البيانات.

الأفضل:

product_options
----------------
id
product_id
name
type
sort_order

product_option_values
----------------
id
option_id
value
visual

5. حقول التعليمات

مثل:

نص توضيحي فقط: ممنوع الكتابة...

هذه ليست بيانات منتج.

يجب أن تكون:

Template Instructions

خارج البيانات الفعلية، أو يتم تجاهلها أثناء الاستيراد.


🏗️ الشكل الاحترافي المقترح للـSchema

لو كان الهدف تحويل هذا القالب إلى منصة تجارة إلكترونية حديثة، فأنا لا أنصح بإنشاء جدول واحد فيه 40 عمودًا.

الأفضل:

products
│
├── product_images
│
├── product_categories
│
├── product_options
│   └── product_option_values
│
├── product_variants
│   └── variant_option_values
│
├── product_prices
│
├── product_identifiers
│
├── product_shipping
│
├── product_tax
│
└── brands

أي أن ملف Excel الحالي هو Import/Export Schema، وليس بالضرورة أن يكون هو Database Schema.

وهذا التفريق مهم جدًا إذا كنا سنبني فوقه لاحقًا TwistTaste Mart / Multivendor Commerce / Salla-compatible Importer.

إذا أردت الاستمرار بنفس المستوى، فالخطوة المنطقية التالية هي أن أحول هذه الـ40 خانة إلى Database Schema احترافي كامل: MySQL tables + primary/foreign keys + indexes + ENUMs + validation rules + Product/Variant/Option relationships + JSON API schema، بحيث يصبح جاهزًا للبناء الفعلي.

هل-يمكنك-اعادة-كتابتها-في-جداول-منظمة-ومفرغة-للادخال-كاصيغة-Production واعادة-كتابة-الجداول-كاملة

تم التحليل

import openpyxl, os, json, pandas as pd
from openpyxl import Workbook
from openpyxl.worksheet.table import Table, TableStyleInfo

src="/mnt/data/files/product-sample (1).xlsx"
wb_src=openpyxl.load_workbook(src, data_only=False)
ws=wb_src["Salla Products Template Sheet"]

headers=[c.value for c in ws[1]]
headers

النتائج

['بيانات المنتج',
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None,
 None]

تم التحليل

import openpyxl, os, re, json
from openpyxl import Workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter

out="/mnt/data/production_product_template.xlsx"

# Production-oriented normalized workbook derived from the uploaded Salla product template.
wb=Workbook()
default=wb.active
wb.remove(default)

# ---------- Styles ----------
header_fill = PatternFill("solid", fgColor="1F6D66")
sub_fill = PatternFill("solid", fgColor="DCEFEA")
header_font = Font(color="FFFFFF", bold=True)
bold = Font(bold=True)
thin = Side(style="thin", color="D9E2E1")
border = Border(left=thin,right=thin,top=thin,bottom=thin)

def make_sheet(name, headers, widths=None, freeze="A2", table_name=None):
    ws=wb.create_sheet(name)
    ws.append(headers)
    for cell in ws[1]:
        cell.fill=header_fill
        cell.font=header_font
        cell.alignment=Alignment(horizontal="center", vertical="center", wrap_text=True)
        cell.border=border
    ws.freeze_panes=freeze
    ws.auto_filter.ref=f"A1:{get_column_letter(len(headers))}1"
    ws.row_dimensions[1].height=34
    if widths:
        for i,w in enumerate(widths,1):
            ws.column_dimensions[get_column_letter(i)].width=w
    if table_name:
        ref=f"A1:{get_column_letter(len(headers))}2"
        tab=Table(displayName=table_name, ref=ref)
        tab.tableStyleInfo=TableStyleInfo(name="TableStyleMedium2", showFirstColumn=False,
                                          showLastColumn=False, showRowStripes=True, showColumnStripes=False)
        ws.add_table(tab)
    return ws

# 1 Products
products_headers=[
"product_id","product_code","name","slug","category_id","product_type_id","brand_id",
"description","promotion_title","status","is_pinned","requires_shipping","hide_quantity_selector",
"allow_order_image","max_quantity_per_customer","weight","weight_unit","is_taxable",
"tax_exemption_reason","calories","primary_image_id","created_at","updated_at"
]
ws=make_sheet("Products",products_headers,[18,18,30,28,16,18,16,45,30,14,12,18,22,18,22,12,12,14,35,14,18,20,20],"A2","ProductsTable")
# add blank production rows
for _ in range(20): ws.append([""]*len(products_headers))

# 2 Variants
variants_headers=[
"variant_id","product_id","sku","barcode","mpn","gtin","price","cost_price","sale_price",
"sale_start_date","sale_end_date","weight","weight_unit","status","stock_quantity","image_id","notes"
]
ws=make_sheet("Variants",variants_headers,[18,18,20,20,18,20,14,14,14,20,20,12,12,14,16,18,35],"A2","VariantsTable")
for _ in range(30): ws.append([""]*len(variants_headers))

# 3 Options
options_headers=["option_id","product_id","name","type","sort_order","is_required"]
ws=make_sheet("Options",options_headers,[18,18,28,18,12,14],"A2","OptionsTable")
for _ in range(15): ws.append([""]*len(options_headers))

# 4 Option Values
values_headers=["option_value_id","option_id","value","visual_type","visual_value","sort_order","is_active"]
ws=make_sheet("OptionValues",values_headers,[20,18,28,16,45,12,14],"A2","OptionValuesTable")
for _ in range(30): ws.append([""]*len(values_headers))

# 5 Variant Option Values
vov_headers=["variant_id","option_value_id"]
ws=make_sheet("VariantOptionValues",vov_headers,[18,22],"A2","VariantOptionValuesTable")
for _ in range(40): ws.append([""]*len(vov_headers))

# 6 Images
images_headers=["image_id","product_id","variant_id","url","alt_text","sort_order","is_primary"]
ws=make_sheet("Images",images_headers,[18,18,18,70,40,12,14],"A2","ImagesTable")
for _ in range(30): ws.append([""]*len(images_headers))

# 7 Categories
cat_headers=["category_id","parent_category_id","name","slug","status","sort_order"]
ws=make_sheet("Categories",cat_headers,[20,24,35,30,14,12],"A2","CategoriesTable")
for _ in range(30): ws.append([""]*len(cat_headers))

# 8 Brands
brand_headers=["brand_id","name","slug","status"]
ws=make_sheet("Brands",brand_headers,[18,35,35,14],"A2","BrandsTable")
for _ in range(20): ws.append([""]*len(brand_headers))

# 9 Product Types
ptype_headers=["product_type_id","name","code","status"]
ws=make_sheet("ProductTypes",ptype_headers,[22,35,30,14],"A2","ProductTypesTable")
for _ in range(15): ws.append([""]*len(ptype_headers))

# 10 Import Map
map_headers=["original_column","production_field","entity","data_type","required","validation_rule","notes"]
ws=make_sheet("ImportMap",map_headers,[34,34,20,20,12,55,55],"A2","ImportMapTable")
mapping=[
("النوع","Products / Variants","Product/Variant","ENUM", "YES","product|variant","يفصل المنتج الرئيسي عن المتغير"),
("أسم المنتج","Products.name","Product","VARCHAR(255)","YES","1-255 chars","اسم المنتج"),
("تصنيف المنتج","Products.category_id","Product","FK","YES","existing category_id","العلاقة مع Categories"),
("صورة المنتج","Images.url","Image","URL","NO","valid URL","لا تجمع عدة روابط في خلية واحدة"),
("وصف صورة المنتج","Images.alt_text","Image","TEXT","NO","max 500 chars","وصف بديل للصورة"),
("نوع المنتج","Products.product_type_id","Product","FK","YES","existing product_type_id","العلاقة مع ProductTypes"),
("سعر المنتج","Variants.price","Variant","DECIMAL(12,2)","YES",">=0","السعر الفعلي للمتغير"),
("الوصف","Products.description","Product","LONGTEXT","NO","UTF-8 text","الوصف"),
("هل يتطلب شحن؟","Products.requires_shipping","Product","BOOLEAN","YES","0|1",""),
("رمز المنتج SKU","Variants.sku","Variant","VARCHAR(100)","YES","unique","SKU يجب أن يكون فريدًا"),
("سعر التكلفة","Variants.cost_price","Variant","DECIMAL(12,2)","NO",">=0",""),
("السعر المخفض","Variants.sale_price","Variant","DECIMAL(12,2)","NO",">=0 and <= price",""),
("تاريخ بداية التخفيض","Variants.sale_start_date","Variant","DATETIME","NO","valid datetime",""),
("تاريخ نهاية التخفيض","Variants.sale_end_date","Variant","DATETIME","NO",">= start date",""),
("اقصي كمية لكل عميل","Products.max_quantity_per_customer","Product","INT","NO",">=0","0 يمكن اعتباره بلا حد حسب سياسة النظام"),
("إخفاء خيار تحديد الكمية","Products.hide_quantity_selector","Product","BOOLEAN","NO","0|1",""),
("اضافة صورة عند الطلب","Products.allow_order_image","Product","BOOLEAN","NO","0|1",""),
("الوزن","Products.weight / Variants.weight","Product/Variant","DECIMAL(10,3)","NO",">=0",""),
("وحدة الوزن","Products.weight_unit / Variants.weight_unit","Product/Variant","ENUM","NO","g|kg|lb|oz",""),
("الماركة","Products.brand_id","Product","FK","NO","existing brand_id","العلاقة مع Brands"),
("العنوان الترويجي","Products.promotion_title","Product","VARCHAR(255)","NO","max 255 chars",""),
("تثبيت المنتج","Products.is_pinned","Product","BOOLEAN","NO","0|1",""),
("الباركود","Variants.barcode","Variant","VARCHAR(100)","NO","unique when present",""),
("السعرات الحرارية","Products.calories","Product","DECIMAL(10,2)","NO",">=0",""),
("MPN","Variants.mpn","Variant","VARCHAR(100)","NO","max 100 chars",""),
("GTIN","Variants.gtin","Variant","VARCHAR(100)","NO","valid GTIN when supplied",""),
("خاضع للضريبة؟","Products.is_taxable","Product","BOOLEAN","YES","0|1",""),
("سبب عدم الخضوع للضريبة","Products.tax_exemption_reason","Product","TEXT","CONDITIONAL","required when is_taxable=0",""),
("[1] الاسم","Options.name","Option","VARCHAR(255)","CONDITIONAL","option exists","الخيار الأول"),
("[1] النوع","Options.type","Option","ENUM","CONDITIONAL","text|color|image|...",""),
("[1] القيمة","OptionValues.value","OptionValue","VARCHAR(255)","CONDITIONAL","non-empty",""),
("[1] الصورة / اللون","OptionValues.visual_value","OptionValue","VARCHAR/TEXT","NO","HEX or URL depending on visual_type",""),
("[2] الاسم","Options.name","Option","VARCHAR(255)","CONDITIONAL","option exists","الخيار الثاني"),
("[2] النوع","Options.type","Option","ENUM","CONDITIONAL","text|color|image|...",""),
("[2] القيمة","OptionValues.value","OptionValue","VARCHAR(255)","CONDITIONAL","non-empty",""),
("[2] الصورة / اللون","OptionValues.visual_value","OptionValue","VARCHAR/TEXT","NO","HEX or URL depending on visual_type",""),
("[3] الاسم","Options.name","Option","VARCHAR(255)","CONDITIONAL","option exists","الخيار الثالث"),
("[3] النوع","Options.type","Option","ENUM","CONDITIONAL","text|color|image|...",""),
("[3] القيمة","OptionValues.value","OptionValue","VARCHAR(255)","CONDITIONAL","non-empty",""),
("[3] الصورة / اللون","OptionValues.visual_value","OptionValue","VARCHAR/TEXT","NO","HEX or URL depending on visual_type",""),
]
for row in mapping: ws.append(row)

# 11 Instructions
ws=make_sheet("README",["section","item","details"],[25,35,90],"A2","ReadmeTable")
readme=[
("Purpose","Production template","قالب فارغ ومنظم للإدخال قبل الاستيراد إلى نظام تجارة إلكترونية."),
("Architecture","Products","البيانات العامة للمنتج."),
("Architecture","Variants","كل تركيبة قابلة للبيع لها SKU وسعر ومخزون مستقل."),
("Architecture","Options","تعريف خيارات المنتج مثل اللون والمقاس."),
("Architecture","OptionValues","القيم الفعلية لكل خيار."),
("Architecture","VariantOptionValues","يربط كل Variant بقيم خياراته."),
("Architecture","Images","صور المنتج والمتغيرات، رابط واحد لكل صف."),
("Reference","Categories","التصنيفات الهرمية."),
("Reference","Brands","العلامات التجارية."),
("Reference","ProductTypes","أنواع المنتجات."),
("Validation","Money","استخدم أرقامًا عشرية، وليس تواريخ Excel."),
("Validation","Dates","صيغة مقترحة: YYYY-MM-DD HH:MM:SS."),
("Validation","IDs","استخدم معرفات فريدة وثابتة."),
("Validation","SKU","يجب أن يكون فريدًا على مستوى المتغيرات."),
("Validation","Tax","إذا is_taxable=0 يجب إدخال tax_exemption_reason."),
("Validation","Images","لا تضع عدة URLs في خلية واحدة؛ أنشئ صفًا لكل صورة."),
("Validation","Options","لا تستخدم أعمدة [1][2][3] داخل قاعدة البيانات؛ استخدم Options/OptionValues."),
]
for r in readme: ws.append(r)

# Add light formatting and data validation
from openpyxl.worksheet.datavalidation import DataValidation
for ws in wb.worksheets:
    for row in ws.iter_rows(min_row=2):
        for cell in row:
            cell.border=border
            cell.alignment=Alignment(vertical="top", wrap_text=True)
    # ensure blank production rows are visually ready
    if ws.title not in ("ImportMap","README"):
        for row in ws.iter_rows(min_row=2):
            for cell in row:
                if cell.value=="":
                    cell.fill=PatternFill("solid", fgColor="F8FBFA")

# Basic validations
ws=wb["Products"]
dv_bool=DataValidation(type="list", formula1='"0,1"', allow_blank=True)
ws.add_data_validation(dv_bool); dv_bool.add(f"K2:N21"); dv_bool.add(f"R2:R21")
ws=wb["Variants"]
dv_bool2=DataValidation(type="list", formula1='"active,inactive"', allow_blank=True)
ws.add_data_validation(dv_bool2); dv_bool2.add("N2:N31")

# Remove table second blank-row issue by keeping exactly header + blank rows is valid.
# Set workbook properties
wb.properties.title="Production Product Data Template"
wb.properties.subject="Normalized production product/variant/options import template"
wb.properties.creator="Zezo Technology AI"

wb.save(out)
print(f"تم إنشاء قالب Production كامل وفارغ: {out}")
print("الأوراق:", ", ".join(wb.sheetnames))
print("الهيكل: Products + Variants + Options + OptionValues + VariantOptionValues + Images + Categories + Brands + ProductTypes + ImportMap + README")

STDOUT/STDERR

تم إنشاء قالب Production كامل وفارغ: /mnt/data/production_product_template.xlsx
الأوراق: Products, Variants, Options, OptionValues, VariantOptionValues, Images, Categories, Brands, ProductTypes, ImportMap, README
الهيكل: Products + Variants + Options + OptionValues + VariantOptionValues + Images + Categories + Brands + ProductTypes + ImportMap + README

نعم. جهزت لك نسخة Production فارغة ومنظمة بالكامل بدل الجدول المسطح ذي الـ40 عمودًا.

📦 ملف Production Template

تحميل قالب Production — Excel

يحتوي الملف على الجداول الكاملة:

الجدولالغرض
Productsالبيانات الأساسية للمنتجات
Variantsالمتغيرات والتركيبات القابلة للبيع
Optionsتعريف خيارات المنتج
OptionValuesقيم الخيارات مثل أسود، XL
VariantOptionValuesربط المتغيرات بخياراتها
Imagesصور المنتجات والمتغيرات
Categoriesالتصنيفات الهرمية
Brandsالعلامات التجارية
ProductTypesأنواع المنتجات
ImportMapتحويل حقول Salla إلى Production Schema
READMEقواعد الإدخال والتحقق

مثال الهيكل

Products
   │
   ├── Categories
   ├── Brands
   ├── ProductTypes
   ├── Images
   │
   ├── Options
   │     └── OptionValues
   │
   └── Variants
          │
          └── VariantOptionValues

وهذا أفضل بكثير للإنتاج من وضع كل شيء في جدول واحد:

Product + 40 Columns

لأنه يسمح لاحقًا بتحويل البيانات مباشرة إلى:

MySQL → Laravel → REST API → Vue/React → WooCommerce/Salla-compatible importer → Multivendor Marketplace.

كما أضفت داخل الملف ImportMap بحيث نستطيع معرفة أين ينتقل كل حقل من قالب Salla إلى البنية الجديدة، وقواعد التحقق مثل SKU unique، وGTIN، والتواريخ، والضريبة، والصور.

الملف الحالي فارغ للإدخال Production؛ أي لم أخلط بيانات العينة داخل جداول الإنتاج. production_product_template.xlsxجداول البياناتفتح الملف

Scroll to Top

🤖 موصى به لك بناءً على اهتماماتك