🇬🇧 English: Read this in English →

Birden fazla depo işletmek, WooCommerce’in doğal olarak ele almak üzere tasarlanmadığı bir karmaşıklığı beraberinde getirir. WooCommerce ürün başına tek bir stok miktarını takip eder. ERP’in ise 3, 5 veya 20 lokasyonda stok takip eder. Açık konuşayım: bu açığı kapatmanın kolay bir düğmesi yok — envanterin nasıl toplandığı, siparişlerin nasıl yönlendirildiği ve müşterinin kullanılabilirliği nasıl gördüğü hakkında dikkatli mimari kararlar gerektiriyor.

Çok depolu depo zorluğu

ERP’in şunu gösterir:

Product: SKU-1234 "Blue Widget"
├── Warehouse A (New York): 50 units
├── Warehouse B (Los Angeles): 30 units
├── Warehouse C (Chicago): 0 units
└── Total Available: 80 units

WooCommerce ne göstermeli? Seçenekler:

  • Toplam kullanılabilir (80) — en basit, ancak başka yerde taahhüt edilmiş stoğu vaat edebilir
  • En yakın depo — sepete eklemeden önce müşteri konumunu bilmeyi gerektirir
  • Yalnızca karşılama deposu — sadece çevrimiçi siparişler için belirlenmiş depodan stoğu göster
  • Kullanılabilir eksi tampon — toplam eksi güvenlik marjı (örn. 72 = 80 – %10)

Mimari

ERP (multi-warehouse stock)
→ Aggregation Logic (middleware)
→ WooCommerce (single stock number per product)

WooCommerce (order placed)
→ Routing Logic (middleware)
→ ERP (assign to optimal warehouse)

Middleware, ERP’in çok lokasyonlu modeli ile WooCommerce’in tek lokasyonlu modeli arasındaki uyumsuzluğu ele alır. Bütün oyun burada dönüyor: WooCommerce’i basit tutuyorsun, karmaşıklığı aradaki katmana yıkıyorsun.

Envanter toplama stratejileri

Strateji 1: Tüm depoları topla

function aggregateStock(erpItem) {
  const totalStock = erpItem.warehouses.reduce(
    (sum, wh) => sum + wh.available, 0
  );
  return {
    sku: erpItem.sku,
    stock_quantity: totalStock,
    stock_status: totalStock > 0 ? 'instock' : 'outofstock'
  };
}

Artıları: Satılabilir envanteri maksimize eder.
Eksileri: Depoya özel taahhütler takip edilmiyorsa aşırı satış yapabilir.

Strateji 2: Ana depo + taşma

Çevrimiçi siparişler için ana karşılama merkezi olarak bir depo belirle. Stokunu göster, ancak ikincil depolardan taşmaya izin ver:

function aggregateStock(erpItem, primaryWarehouseId) {
  const primary = erpItem.warehouses.find(w => w.id === primaryWarehouseId);
  const overflow = erpItem.warehouses
    .filter(w => w.id !== primaryWarehouseId)
    .reduce((sum, w) => sum + w.available, 0);

  // Show primary stock + 50% of overflow (buffer for retail/wholesale)
  const displayStock = (primary?.available || 0) + Math.floor(overflow * 0.5);

  return {
    sku: erpItem.sku,
    stock_quantity: displayStock,
    stock_status: displayStock > 0 ? 'instock' : 'outofstock'
  };
}

Strateji 3: Bölgesel gösterim (ileri seviye)

Müşterinin tespit edilen bölgesine göre farklı stok seviyelerini göster:

async function getRegionalStock(erpItem, customerRegion) {
  const regionWarehouseMap = {
    'east': ['WH-NYC', 'WH-ATL'],
    'west': ['WH-LAX', 'WH-SEA'],
    'central': ['WH-CHI', 'WH-DAL']
  };

  const relevantWarehouses = regionWarehouseMap[customerRegion] || Object.values(regionWarehouseMap).flat();

  const regionalStock = erpItem.warehouses
    .filter(w => relevantWarehouses.includes(w.id))
    .reduce((sum, w) => sum + w.available, 0);

  return { stock_quantity: regionalStock };
}

Bu, frontend’de dinamik stok gösterimi gerektirir — genellikle müşterinin konumunu tespit ettikten sonra bir AJAX çağrısı aracılığıyla.

Sipariş yönlendirme

Bir sipariş geldiğinde, middleware’in hangi deponun onu karşılayacağına karar vermelidir:

function routeOrder(order, warehouseStock) {
  const shippingState = order.shipping.state;
  const items = order.line_items;

  // 1. Find warehouses that can fulfill the entire order
  const candidates = warehouseStock.filter(wh =>
    items.every(item =>
      wh.inventory[item.sku] >= item.quantity
    )
  );

  if (candidates.length === 0) {
    // No single warehouse can fulfill — need split shipment
    return splitShipment(order, warehouseStock);
  }

  // 2. Score candidates
  const scored = candidates.map(wh => ({
    warehouse: wh,
    score: calculateScore(wh, shippingState, items)
  }));

  // 3. Select best warehouse
  return scored.sort((a, b) => b.score - a.score)[0].warehouse;
}

function calculateScore(warehouse, customerState, items) {
  let score = 0;

  // Proximity (shipping zone distance)
  const distance = getDistance(warehouse.state, customerState);
  score += (1000 - distance) * 2; // Closer = higher score

  // Stock depth (prefer warehouses with more stock)
  const minStockRatio = Math.min(
    ...items.map(item => warehouse.inventory[item.sku] / item.quantity)
  );
  score += minStockRatio * 100;

  // Workload (prefer less busy warehouses)
  score -= warehouse.pendingOrders * 5;

  return score;
}

Bölünmüş kargolar

Hiçbir depo tek başına tüm siparişi karşılayamadığında:

function splitShipment(order, warehouses) {
  const shipments = [];
  const remaining = [...order.line_items];

  // Greedy algorithm: assign items to nearest warehouse with stock
  while (remaining.length > 0) {
    const item = remaining[0];
    const warehouse = warehouses
      .filter(wh => wh.inventory[item.sku] >= item.quantity)
      .sort((a, b) =>
        getDistance(a.state, order.shipping.state) -
        getDistance(b.state, order.shipping.state)
      )[0];

    if (!warehouse) {
      throw new Error(`Cannot fulfill ${item.sku}: insufficient stock across all warehouses`);
    }

    // Find or create shipment for this warehouse
    let shipment = shipments.find(s => s.warehouseId === warehouse.id);
    if (!shipment) {
      shipment = { warehouseId: warehouse.id, items: [] };
      shipments.push(shipment);
    }

    shipment.items.push(item);
    warehouse.inventory[item.sku] -= item.quantity;
    remaining.shift();
  }

  return shipments;
}

Bölünmüş kargolar için müşteri iletişimi:

  • Müşteriye siparişinin birden fazla pakette geleceğini bildir
  • Kargo başına ayrı takip numaraları sağla
  • Ekstra kargo ücreti alma (maliyeti karşıla)

WooCommerce uygulaması

Plugin yaklaşımı

WooCommerce’e depo başına stok takibi ekleyen bir çok depolu plugin (ATUM veya WooCommerce Multi-Warehouse gibi) kullan. ERP senkronizasyonun her deponun stok seviyesini günceller.

Özel meta yaklaşımı

Depo seviyesindeki verileri ürün meta’sında sakla:

// Store per-warehouse stock in product meta
update_post_meta($product_id, '_warehouse_stock', json_encode([
  'WH-NYC' => 50,
  'WH-LAX' => 30,
  'WH-CHI' => 0
]));

// Display stock is the aggregated number
update_post_meta($product_id, '_stock', 80);
update_post_meta($product_id, '_stock_status', 'instock');

Fazla satışın gerçek maliyeti ve güvenlik tamponu

Şimdi bir dakikalığına strateji tablosundan çıkıp işletme tarafına bakalım, çünkü çok depolu kurulumlarda insanların kendini asıl yaktığı yer burası. Toplam stoğu (yukarıdaki Strateji 1) göstermek kâğıt üzerinde en çok satışı vaat eder; pratikte ise en sık fazla satışa yol açan seçenek de odur. Sebep basit: 80 birimin 30’u Los Angeles deposunda başka bir kanala, bir toptancıya ya da bir mağaza içi rezervasyona söz verilmiş olabilir. Sistem bunu bilmez, sen “stokta” gösterirsin, müşteri sipariş verir, ve depoda o birim yoktur. O andan itibaren ya siparişi iptal edip özür dilersin ya da bir yerden acil tedarik ararsın — ikisi de para ve güven kaybı.

Ben olsam her toplama stratejisinin üstüne küçük bir güvenlik tamponu koyardım — toplamın yüzde beş ila onunu görünür stoktan düşerdim. Evet, kâğıt üzerinde birkaç satışı masada bırakırsın; ama iptal, geç kalan kargo ve “sipariş ettim, gelmedi” e-postalarının maliyeti neredeyse her zaman o birkaç kaçan satıştan yüksektir. Tamponu sabit bir sayı olarak değil, deponun geçmiş hata payına göre ayarla: envanteri sık kayan bir depo daha büyük tampon hak eder. Bu sıkıcı bir ayar gibi görünür, ama fazla satışın müşteri hizmetlerinde açtığı yarayı bir kez yaşayan herkes neden buna değdiğini bilir.

Çok depolu operasyonları izleme

Metrik Neyi takip etmeli
Stok doğruluğu ERP stoku vs WooCommerce gösterilen stok
Yönlendirme verimliliği En yakın depodan karşılanan siparişlerin % oranı
Bölünmüş kargo oranı Bölünmüş kargo gerektiren siparişlerin % oranı (hedef: < %5)
Depoya göre karşılama süresi Yavaş depoları tespit et
Stok tükenmesi olayları Toplam stok sıfıra düştüğünde

Sonuç

Çok depolu WooCommerce temelde middleware aracılığıyla çözülen bir ERP problemidir. WooCommerce basitleştirilmiş bir görünüm sergiler; ERP’in karmaşıklığı yönetir. Temel kararlar — toplama stratejisi, yönlendirme mantığı ve bölünmüş kargo işleme — senin spesifik lojistik kurulumuna bağlıdır. En basit toplama ile başla (toplam veya ana depo), temel yönlendirme uygula ve karmaşıklığı yalnızca veriler buna ihtiyacın olduğunu gösterdiğinde ekle. Bunu haklı çıkaracak sipariş hacmine sahip olmadan önce depo mantığını aşırı mühendislik yapmak, geliştirme zamanını boşa harcar. Otuz yıldır aynı dersi görüyorum: sistemi karmaşıklaştıran değil, karmaşıklığı gerçekten gerektiği ana kadar erteleyen ekip kazanıyor.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Close Search Window