اتخطّى للمحتوى

المرحلة 03 · الكتالوج والتجارةدرس 16 من 3414 دقيقة قراءةآخر تحديث:

Lesson 16 / 34

Inventory & MSIالمخزون.

إزاي Magento بيعرف عنده كام قطعة، وإزاي بيمنع بيع حاجة مش موجودة. الـ Sources والـ Stocks، الـ Reservations، الفرق بين الكميات، والتعامل معاه في الكود.

● MSI Reservations Salable Qty التشخيص

المخزون في Magento 2 بنظام MSI: الـ Source مكان فيزيائي فيه كميات حقيقية، والـ Stock تجميعة منطقية لمصادر مربوطة بـ website. الكمية القابلة للبيع هي مجموع المصادر ناقص الـ reservations، وهي أسطر بالسالب بتتسجّل عند الأوردر وبتتعوّض عند الشحن أو الإلغاء. السلة مابتحجزش، والفحص في الكود بيتم بـ GetProductSalableQtyInterface على الـ stock.

// المشكلة اللي بيحلّها الحاجة الأصعب في المخزون هي السباق — عشرة عملاء بيحاولوا يشتروا آخر قطعة في نفس الثانية. لو الحسبة اتأخرت شوية، بتبيع لعشرة وعندك واحدة. Magento بيحل ده بفكرة الحجوزات، وهي أهم مفهوم في الدرس ده — القسم 04.
◆ Part 1 — الفهم
01

قبل MSI وبعده

ليه النظام اتغيّر أصلاً.

النظام القديم

رقم واحد لكل منتج: qty. مخزن واحد، وخصم مباشر عند الشراء.

MSI

كميات في أماكن متعددة، وحسبة بتراعي الطلبات اللي لسه ما اتشحنتش.

ليه احتاجوا التغيير
  • أكتر من مخزن — بضاعة موزّعة على أماكن مختلفة.
  • البيع من الفروع — الفرع نفسه مخزن.
  • الطلب من المورّد مباشرة — dropshipping.
  • أسواق مختلفة — كل website بيبيع من مخازن معيّنة.
MSI يعني إيه

اختصار Multi-Source Inventory — مخزون متعدد المصادر. مفعّل افتراضياً في النسخ الحديثة، وحتى لو عندك مخزن واحد، أنت بتستخدمه (بالمصدر والمخزون الافتراضيين).

i
ده مهم: حتى لو مشروعك بسيط بمخزن واحد، الحسابات بتمشي بمنطق MSI. فهم الـ reservations مطلوب حتى لو مش شايف أي تعقيد في الأدمن.
• • •
02

Sources و Stocks

المفهومان الأساسيان — والخلط بينهم بيعطّل الفهم كله.

concept
Source — المصدر
مكان فيزيائي فيه بضاعة. مخزن، فرع، مستودع مورّد.
الكميةهنا بتتخزّن الكميات الحقيقية.
Stock — المخزون
تجميعة منطقية لمصادر، مربوطة بـ websites.
الكميةمفيهوش كميات — بيجمّع من مصادره.
أماكن فيزيائية
مخزن القاهرة
مخزن جدة
فرع دبي
↓ بتتجمّع في
تجميعات منطقية
مخزون مصر
مخزون الخليج
↓ مربوطة بـ
مواقع البيع
Website مصر
Website الخليج
تشبيه الـ source زي مخزن حقيقي تقدر تروحه وتعدّ اللي فيه. الـ stock زي كشف بيقول "للزباين في المنطقة دي، بنسحب من المخازن دي" — مفيش بضاعة في الكشف نفسه، بس هو اللي بيحدد من فين بتخدم مين.
الافتراضيان

Magento بييجي بـ Default Source وDefault Stock. لو مضفتش غيرهم، كل حاجة بتمشي عليهم — وده الوضع في معظم المشاريع البسيطة.

!
الـ Default Stock خاص وله قيود. مينفعش تشيل منه الـ Default Source، وبيتصرّف بشكل مختلف شوية عن الـ stocks اللي بتعملها إنت. لو هتعمل نظام متعدد المخازن حقيقي، اعمل stocks جديدة بدل ما تعدّل الافتراضي.
• • •
03

أنواع الكميات

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

quantity
Quantity per Source
الكمية الفعلية في مصدر واحد. ده اللي في المخزن حقيقي.
بيتغيّرعند الشحن أو الجرد أو الاستلام.
Aggregated Quantity
مجموع الكميات في كل مصادر المخزون.
بيتغيّرتبعاً للمصادر.
Salable Quantity
المتاح للبيع فعلاً — المجموع ناقص المحجوز.
الأهمده اللي بيحدد هل العميل يقدر يشتري ولا لأ.
Salable Qty = Aggregated QtyReservations
مثال يوضّح الفرق
منتج في مخزنينtext
مخزن القاهرة:  10 قطع
مخزن جدة:       5 قطع
                ──────
Aggregated:     15 قطعة   # الموجود فعلياً

طلبات لسه ما اتشحنتش: 3
                ──────
Salable:        12 قطعة   # اللي ينفع تبيعه

# الـ 3 دول لسه في المخزن فيزيائياً
# بس محجوزين لعملاء اشتروهم
!
ده أهم فرق في الدرس كله. لو كودك بيقرا الكمية العادية (qty) بدل الـ salable، هتسمح ببيع قطع محجوزة لعملاء تانيين — وهتكتشف ده لما تفشل في الشحن. أي فحص توفّر لازم يكون على الـ salable.
• • •
◆ Part 2 — الجوهر
04

الـ Reservations

أذكى فكرة في النظام — وأكترها إساءة فهم.

المشكلة

عندك قطعة واحدة، وعشرة عملاء ضغطوا "اشتري" في نفس الثانية. لو كل واحد بيقرا الكمية ويخصم منها، ممكن العشرة يقروا "1" قبل ما حد يخصم — وتبيع عشرة وعندك واحدة.

الحل التقليدي ومشكلته

تقفل الصف في قاعدة البيانات لحد ما الأول يخلص. بس ده بيخلّي الطلبات تستنى في طابور — وفي عروض الفلاش ده بيوقّع الموقع.

حل الـ reservations

بدل ما نعدّل الكمية، نضيف سطر حجز بقيمة سالبة. الإضافة أسرع بكتير من التعديل ومابتحتاجش قفل، وعمليات الإضافة مابتتعارضش مع بعض.

تشبيه زي دفتر حسابات بدل ما تمسح الرقم وتكتب رقم جديد. كل عملية بتتسجّل كسطر جديد: "−1"، "−2". الرصيد = المجموع. مفيش اتنين بيحاولوا يمسحوا نفس الرقم في نفس الوقت، فمفيش تعارض.
شكل جدول الحجوزاتtext
inventory_reservation
──────────────────────────────────────
id │ stock │ sku      │ quantity
 1 │   1   │ SKU-001  │  -2    # أوردر
 2 │   1   │ SKU-001  │  -1    # أوردر تاني
 3 │   1   │ SKU-001  │  +2    # اتشحن، الحجز اتلغى

# المحصلة: -1 → قطعة واحدة محجوزة
دورة الحجز
  • العميل يطلب → يتسجّل حجز بالسالب. الكمية الفعلية ماتغيّرتش.
  • الـ salable بتقل فوراً — فمحدش تاني يقدر ياخد نفس القطع.
  • الطلب يتشحن → الكمية الفعلية بتقل، والحجز بيتلغى بسطر موجب.
  • أو يتلغى الطلب → الحجز بيتلغى والكمية بترجع متاحة.
i
لاحظ إن الكمية الفعلية مابتتغيّرش وقت الطلب — بتتغيّر وقت الشحن. ده منطقي: البضاعة لسه في المخزن لحد ما تطلع فعلاً. وده بيخلّي المخزون في Magento مطابق للواقع الفيزيائي.
!
متعدّلش جدول الحجوزات يدوياً. ده سجل تراكمي، والتعديل المباشر بيخرّب الحسبة بشكل صعب التتبّع. فيه أوامر رسمية للإصلاح في القسم 09.
• • •
05

دورة حياة المخزون

من السلة للشحن — إيه بيتغيّر امتى.

السلة
الطلب
الشحنة
اكتمال
stage
1 · في السلة
مفيش حجز. الكمية بتتشيّك بس عند الإضافة.
مهمحاجة في سلة عميل مش محجوزة — عميل تاني يقدر يشتريها.
2 · عند الطلب
بيتسجّل حجز بالسالب. الكمية الفعلية ماتغيّرتش.
الأثرالـ salable بتقل فوراً.
3 · عند الشحن
الكمية الفعلية بتقل، والحجز بيتلغى.
الأثرالمخزون بقى مطابق للواقع.
4 · عند الإلغاء
الحجز بيتلغى والكمية بترجع متاحة.
الأثرالقطع رجعت للبيع.
5 · عند المرتجع
الكمية بتزيد لو اخترت "رجّع للمخزون".
الأثرالبضاعة رجعت فيزيائياً.
!
المرحلة 1 بتفاجئ الناس. إضافة منتج للسلة مابتحجزهوش. لو آخر قطعة في سلة عميل وقعد ساعة، عميل تاني يقدر يشتريها — والأول هيلاقيها اختفت عند الدفع. ده تصميم مقصود (سلال مهجورة مش المفروض تجمّد المخزون)، بس لازم تفهمه عشان تشرحه للعمل.
• • •
06

خوارزميات التوزيع

من أنهي مخزن نشحن؟

المشكلة

الطلب فيه 5 قطع، وعندك 3 في القاهرة و4 في جدة. من فين تشحن؟ الـ Source Selection Algorithm بيجاوب.

algorithm
Priority
بيمشي على المصادر بالترتيب اللي حددته، وياخد من كل واحد لحد ما يكمّل.
امتىالافتراضي، ومناسب لمعظم الحالات. بتحط الأقرب أو الأكبر أول.
Distance Priority
بيختار الأقرب جغرافياً لعنوان الشحن.
امتىلما تكلفة ووقت الشحن مهمين. محتاج إعداد خدمة خرايط.
الترتيب في Priority

بيتحدد من Stores → Inventory → Stocks، وبتسحب المصادر بالترتيب اللي عايزه. الترتيب ده قرار تشغيلي — عادة الأكبر أول عشان تقلّل عدد الشحنات، أو الأقرب أول عشان تقلّل التكلفة.

i
الخوارزمية بتقترح بس — الموظف يقدر يغيّر وقت عمل الشحنة. ده مفيد لما فيه ظروف النظام مايعرفهاش (بضاعة تالفة، مخزن مقفول).
• • •
◆ Part 3 — العملي
07

الإعدادات المهمة

اللي بتأثر على السلوك فعلياً.

setting
Backorders
هل يسمح بالبيع لما الكمية تخلص.
حذرلو مفعّل، الـ salable ممكن تبقى بالسالب وده طبيعي.
Out-of-Stock Threshold
الكمية اللي تحتها المنتج يعتبر منتهي.
امتىحطّها فوق صفر لو عايز تحتفظ باحتياطي.
Minimum/Maximum Qty in Cart
حد أدنى وأقصى للشراء.
امتىمنع الشراء بكميات كبيرة من منتج محدود.
Display Out of Stock Products
هل المنتجات المنتهية تظهر في الكتالوج.
الأثرمفيد للـ SEO، بس بيزوّد حجم الفهرس.
Only X left Threshold
يعرض "باقي X قطع" لما الكمية تقل.
امتىتحفيز الشراء. بيقرا من الـ salable.
Decrease Stock When Order is Placed
إعداد قديم من قبل MSI.
ملاحظةمع MSI الحجز بيحصل تلقائياً، فالإعداد ده مالوش نفس المعنى.
Manage Stock
هل نتابع المخزون لهذا المنتج أصلاً.
امتىfalse للخدمات والمنتجات غير المحدودة.
!
الإعدادات دي ليها مستويان: عام (لكل المنتجات) وعلى مستوى المنتج الواحد. لو منتج بيتصرّف بشكل مختلف عن الباقي، شوف إعداداته الخاصة الأول — غالباً حد غيّرها من صفحة المنتج ونسي.
• • •
08

المخزون في الكود

الواجهات الصح للقراءة والكتابة.

الكمية القابلة للبيع — الأهمphp
use Magento\InventorySalesApi\Api\
     GetProductSalableQtyInterface;
use Magento\InventorySalesApi\Api\
     StockResolverInterface;
use Magento\InventorySalesApi\Api\Data\
     SalesChannelInterface;

class StockChecker
{
    public function __construct(
        private readonly GetProductSalableQtyInterface $getSalableQty,
        private readonly StockResolverInterface $stockResolver
    ) {}

    public function getQty(
        string $sku,
        string $websiteCode
    ): float {
        // نحوّل الـ website لـ stock
        $stock = $this->stockResolver->execute(
            SalesChannelInterface::TYPE_WEBSITE,
            $websiteCode
        );

        // الكمية القابلة للبيع فعلاً
        return $this->getSalableQty->execute(
            $sku,
            (int) $stock->getStockId()
        );
    }
}
شرح الخطوتين

الـ stock resolver بيحوّل "أنا بابيع في website مصر" لـ "يبقى المخزون رقم 2". وبعدين الـ salable qty بيحسب المتاح في المخزون ده. لازم الخطوتين — لأن نفس المنتج ليه كميات مختلفة حسب الـ website.

فحص التوفّر — أبسط وأسرعphp
use Magento\InventorySalesApi\Api\
     IsProductSalableInterface;

// لو عايز تعرف بس "متاح ولا لأ"
$canSell = $this->isProductSalable->execute(
    $sku,
    $stockId
);

// أو بكمية محددة
use Magento\InventorySalesApi\Api\
     IsProductSalableForRequestedQtyInterface;

$result = $this->isSalableForQty->execute(
    $sku, $stockId, $requestedQty
);

if (!$result->isSalable()) {
    // بيرجّع أسباب الرفض
    foreach ($result->getErrors() as $error) {
        // $error->getMessage()
    }
}
i
لو محتاج تعرف "متاح ولا لأ" بس، استخدم IsProductSalableInterface مش حساب الكمية — أسرع بكتير لأنه بيوقف أول ما يتأكد بدل ما يجمّع كل حاجة.
تحديث كمية في مصدرphp
use Magento\InventoryApi\Api\SourceItemsSaveInterface;
use Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory;
use Magento\InventoryApi\Api\Data\SourceItemInterface;

$sourceItem = $this->sourceItemFactory->create();

$sourceItem->setSku('SKU-001');
$sourceItem->setSourceCode('cairo_warehouse');
$sourceItem->setQuantity(50);
$sourceItem->setStatus(
    SourceItemInterface::STATUS_IN_STOCK
);

// بياخد مصفوفة — أسرع للتحديث الجماعي
$this->sourceItemsSave->execute([$sourceItem]);
!
الـ execute() بياخد مصفوفة. لو بتحدّث مخزون كتير (مزامنة من ERP مثلاً)، ابعتهم كلهم مرة واحدة مش واحد واحد — الفرق في الأداء كبير جداً لأن كل نداء بيطلق إعادة فهرسة.
متعملش حجز بنفسك

فيه واجهة لإضافة حجوزات يدوياً، بس ماتستخدمهاش إلا لو فاهم النتائج كويس. الحجوزات بتتدار تلقائياً مع دورة حياة الأوردر، وإضافة حجز يدوي من غير ما تلغيه بيخلّي كمية محجوزة للأبد.

• • •
09

التشخيص وإصلاح الأخطاء

لما الأرقام تطلع غلط.

أوامر التشخيص الرسمية
فحص وإصلاح الحجوزاتbash
# يكشف الحجوزات المعلّقة الغلط
bin/magento inventory:reservation:list-inconsistencies

# يولّد أوامر التصحيح (من غير تنفيذ)
bin/magento inventory:reservation:create-compensations \
  --raw

# التنفيذ الفعلي — بعد المراجعة
bin/magento inventory:reservation:create-compensations
!
شغّل الأمر الأول في وضع القراءة الأول دايماً. راجع النتيجة وافهم كل بند قبل ما تنفّذ التصحيح. التصحيح الأعمى ممكن يخفي مشكلة حقيقية في الكود بدل ما يحلها — والمشكلة هترجع تاني.
استعلامات تشخيصية
SQLsql
-- الكميات الفعلية في المصادر
SELECT source_code, quantity, status
FROM inventory_source_item
WHERE sku = 'SKU-001';

-- الحجوزات القائمة
SELECT stock_id, SUM(quantity) AS reserved
FROM inventory_reservation
WHERE sku = 'SKU-001'
GROUP BY stock_id;

-- أوردرات قديمة لسه محجوزة (مؤشر مشكلة)
SELECT o.increment_id, o.status, o.created_at
FROM sales_order o
WHERE o.status IN ('pending', 'processing')
  AND o.created_at < NOW() - INTERVAL 30 DAY;
شجرة التشخيص
  • الكمية الفعلية صح؟ — شوف inventory_source_item.
  • الحجوزات منطقية؟ — قارنها بالأوردرات المفتوحة.
  • فيه أوردرات عالقة؟ — أوردر قديم مش متشحن ولا ملغي بيفضل حاجز.
  • الفهارس متحدّثة؟indexer:status.
  • الكاش اتمسح؟ — الكميات بتتكاش في الصفحات.
i
السبب الأشهر للحجوزات العالقة: أوردرات قديمة لا اتشحنت ولا اتلغت — قاعدة في pending لشهور. الحجز بتاعها بيفضل شغّال والكمية محجوزة. راجع الأوردرات القديمة دورياً، والاستعلام التالت فوق بيلاقيها.
• • •
10

الأنواع المركّبة

المخزون في الـ configurable والـ bundle.

type
configurable
المخزون على الأبناء. الأب متاح طالما ابن واحد متاح.
الفحصعلى الـ SKU بتاع الابن مش الأب.
bundle
بيتحسب من المكوّنات الإلزامية.
الفحصالحزمة متاحة لو كل الإلزامي متاح.
grouped
كل منتج مستقل تماماً.
الفحصعلى كل منتج لوحده.
virtual / downloadable
ممكن يتابع مخزون أو لأ حسب Manage Stock.
الفحصعادة بتتعطّل المتابعة.
غلط — الفحص على الأبphp
// الأب مالوش مخزون أصلاً
$qty = $this->getSalableQty->execute(
    $configurableProduct->getSku(),
    $stockId
);
// النتيجة مالهاش معنى
صح — على الأبناءphp
$children = $product->getTypeInstance()
    ->getUsedProducts($product);

$total = 0;

foreach ($children as $child) {
    $total += $this->getSalableQty->execute(
        $child->getSku(),
        $stockId
    );
}

// أو للتوفّر بس — أسرع
$isAvailable = $product->isSalable();
i
الـ isSalable() على المنتج بيتعامل مع كل الأنواع صح تلقائياً. استخدمه لما تحتاج التوفّر بس — وسيب حساب الكميات التفصيلي لما تحتاجه فعلاً.
• • •
◆ Part 4 — الخلاصة
11

الفخاخ الشائعة

اقرا دي حتى لو مش هتقرا حاجة تانية.

  • قراءة qty بدل الـ salable — بتسمح ببيع قطع محجوزة. الفخ الأول.
  • افتراض إن السلة بتحجز — مابتحجزش. الحجز عند الطلب.
  • الفحص على الأب في الـ configurable — الأب مالوش مخزون.
  • تعديل جدول الحجوزات يدوياً — بيخرّب الحسبة بشكل صعب التتبّع.
  • أوردرات عالقة في pending — بتفضل حاجزة كمية للأبد.
  • تحديث المخزون واحد واحد — بطيء جداً في المزامنة. ابعت مصفوفة.
  • نسيان الـ website في حساب الكمية — نفس المنتج له كميات مختلفة لكل مخزون.
  • الاستغراب من salable بالسالب — طبيعي لو الـ backorders مفعّلة.
  • تعديل الـ Default Stock — له قيود خاصة. اعمل stock جديد.
  • تشغيل التصحيح من غير مراجعة — بيخفي مشكلة حقيقية في الكود.
i
لو كمية طالعة غلط، اسأل بالترتيب: الكمية الفعلية صح؟فيه حجوزات عالقة؟فيه أوردرات قديمة مفتوحة؟الفهرس والكاش؟
• • •
12

أسئلة الإنترفيو

من أكتر المواضيع اللي بتميّز السنيور.

Q1إيه الفرق بين Source و Stock؟
الإجابة: الـ source مكان فيزيائي فيه بضاعة حقيقية — مخزن أو فرع. الـ stock تجميعة منطقية لمصادر مربوطة بـ websites، ومفيهاش كميات — بتجمّع من مصادرها. المصدر بيجاوب "الحاجة فين"، والمخزون بيجاوب "بنخدم مين من فين".
Q2إيه الـ reservations وليه موجودة؟
الإجابة: سجل تراكمي بيسجّل الكميات المطلوبة اللي لسه ما اتشحنتش، كأسطر بالسالب. موجودة عشان تحل مشكلة السباق — الإضافة أسرع من التعديل ومابتحتاجش قفل، فعشرة عملاء بيشتروا في نفس اللحظة مابيتعارضوش. والكمية الفعلية مابتتغيّرش إلا عند الشحن، فتفضل مطابقة للواقع.
Q3إزاي تتحسب الـ Salable Quantity؟
الإجابة: مجموع كميات كل مصادر المخزون ناقص مجموع الحجوزات. دي الكمية اللي بتحدد هل العميل يقدر يشتري — مش الكمية الفعلية. الفرق بينهم هو الطلبات اللي لسه في المخزن بس محجوزة.
Q4إضافة منتج للسلة بتحجزه؟
الإجابة: لأ. الحجز بيحصل عند إنشاء الأوردر. السلة بتشيّك على التوفّر عند الإضافة بس مش بتحجز. ده تصميم مقصود — سلال مهجورة مش المفروض تجمّد المخزون — بس معناه إن آخر قطعة في سلة عميل ممكن عميل تاني ياخدها.
Q5الكمية طالعة غلط — تشخّص إزاي؟
الإجابة: بالترتيب: أشوف الكمية الفعلية في inventory_source_item، بعدين الحجوزات وأقارنها بالأوردرات المفتوحة، بعدين أدوّر على أوردرات عالقة في pending من شهور. وفيه أمر رسمي inventory:reservation:list-inconsistencies بيكشف التعارضات.
Q6فين المخزون في الـ configurable؟
الإجابة: على الأبناء. الأب مالوش كمية، وبيبقى متاح طالما ابن واحد على الأقل متاح. أي فحص كمية لازم يكون على SKU الابن — الفحص على الأب بيدي نتيجة مالهاش معنى.

Inventory & MSI ✓

دلوقتي فاهم بنية الـ sources والـ stocks، الفرق بين الكميات، فكرة الحجوزات وليه موجودة، ودورة حياة المخزون والتشخيص.

الخلاصة: الـ salable هي اللي بتحدد البيع مش الكمية الفعلية، والحجوزات بتحل السباق بالإضافة بدل التعديل، والسلة مابتحجزش.

// magento 2 · inventory · msi · reservations

خلّصت الدرس؟علّمه عشان تتابع تقدّمك في الكورس.

كاتب الدرس

Abdulrahman Masoud

عندك سؤال على الدرس أو محتاج مساعدة في مشروع Magento؟ كلّمني.

أسئلة شائعة

إيه الفرق بين Source و Stock في MSI؟

الـ Source مكان فيزيائي فيه بضاعة حقيقية زي مخزن أو فرع، والكميات الفعلية بتتخزّن فيه في جدول inventory_source_item. الـ Stock تجميعة منطقية لمصادر مربوطة بـ websites، ومفيهاش كميات بل بتجمّع من مصادرها. Magento بييجي بـ Default Source و Default Stock، ولو هتعمل نظام متعدد المخازن اعمل stocks جديدة بدل ما تعدّل الافتراضي.

إيه الفرق بين Quantity و Salable Quantity في Magento 2؟

الـ Quantity هي الكمية الفعلية في المصدر، والـ Aggregated مجموعها في كل مصادر الـ stock. الـ Salable Quantity هي المتاح للبيع فعلًا: المجموع ناقص الـ reservations بتاعة الأوردرات اللي لسه مااتشحنتش. أي فحص توفّر لازم يكون على الـ salable، لأن قراءة qty العادية بتسمح ببيع قطع محجوزة لعملاء تانيين.

يعني إيه Reservations في MSI وليه موجودة؟

سجل تراكمي في جدول inventory_reservation بيسجّل الكميات المطلوبة اللي لسه مااتشحنتش كأسطر بالسالب، ولما الأوردر يتشحن أو يتلغي بيتسجّل سطر موجب يعوّضها. بتحل مشكلة السباق: الإضافة أسرع من التعديل ومابتحتاجش قفل، فعشرة عملاء بيشتروا آخر قطعة في نفس اللحظة مابيتعارضوش. الكمية الفعلية مابتتغيّرش إلا عند الشحن.

هل إضافة المنتج للسلة بتحجزه من المخزون؟

لأ. السلة بتشيّك على التوفّر عند الإضافة بس. الحجز بيتسجّل عند إنشاء الأوردر، والكمية الفعلية بتتخصم عند الشحن، ولو الأوردر اتلغى الحجز بيتعوّض والقطع بترجع متاحة. ده تصميم مقصود عشان السلال المهجورة ماتجمّدش المخزون، بس معناه إن آخر قطعة في سلة عميل ممكن عميل تاني يشتريها قبل ما يدفع.

إزاي أقرا الكمية القابلة للبيع في الكود؟

حوّل الـ website لـ stock بـ StockResolverInterface::execute(SalesChannelInterface::TYPE_WEBSITE, $websiteCode)، وبعدين GetProductSalableQtyInterface::execute($sku, $stockId). لو محتاج تعرف متاح ولا لأ بس، IsProductSalableInterface أسرع، وIsProductSalableForRequestedQtyInterface بيرجّع أسباب الرفض لكمية معيّنة. في الـ configurable افحص على SKU الابن لأن الأب مالوش كمية.

إزاي أحدّث كميات المخزون برمجيًا في Magento 2؟

اعمل SourceItemInterface بالـ sku و source_code و quantity و status، وابعته لـ SourceItemsSaveInterface::execute([$sourceItem]). الميثود بتاخد مصفوفة، فلو بتزامن من ERP ابعت كل الأصناف مرة واحدة مش واحد واحد لأن كل نداء بيطلق إعادة فهرسة. ومتضيفش reservations يدويًا، لأنها بتتدار تلقائيًا مع دورة حياة الأوردر.

كمية المنتج طالعة غلط في Magento 2، أشخّص إزاي؟

بالترتيب: الكمية الفعلية في inventory_source_item، وبعدين مجموع الحجوزات في inventory_reservation وقارنه بالأوردرات المفتوحة، وبعدين دوّر على أوردرات قاعدة في pending من شهور لأنها بتفضل حاجزة كمية. الأمر inventory:reservation:list-inconsistencies بيكشف التعارضات، وcreate-compensations بيصلّحها بعد ما تراجع النتيجة. وفي الآخر الفهرس والكاش.