WooCommerce CLI ile Otomatik Sipariş Yönetimi Scripti

E-ticaret sitelerinde sipariş yönetimi, zamanla kaotik bir hal alabiliyor. Onlarca, yüzlerce sipariş arasında manuel işlem yapmak hem zaman kaybı hem de hata riski demek. WP-CLI’nin WooCommerce entegrasyonu sayesinde bu işlemlerin büyük çoğunluğunu otomatize edebilir, bash scriptleriyle güçlü yönetim araçları oluşturabilirsiniz. Bu yazıda gerçek dünya senaryolarına dayanan, production ortamında kullanabileceğiniz scriptler yazacağız.

WP-CLI WooCommerce Eklentisini Tanıyalım

WP-CLI, WordPress’in komut satırı arayüzü. WooCommerce ise kendi WP-CLI komutlarını wc namespace’i altında sunuyor. Ancak hemen belirtmek gerekiyor: WooCommerce’in native WP-CLI komutları sınırlı. Asıl gücü, wp eval ve wp eval-file komutlarıyla PHP kodunu doğrudan çalıştırma yeteneğinden geliyor.

Önce ortamımızı kontrol edelim:

# WP-CLI sürümünü kontrol et
wp --version

# WooCommerce eklentisinin aktif olduğunu doğrula
wp plugin is-active woocommerce && echo "WooCommerce aktif" || echo "WooCommerce pasif"

# Mevcut WC komutlarını listele
wp wc --help

# REST API kullanımı için kullanıcı oluştur
wp wc customer create --email="[email protected]" --first_name="API" --last_name="User" --role="administrator" --user_login="wc_api_user" --user_pass="GucluSifre123!" --porcelain

WooCommerce CLI komutlarının büyük çoğunluğu REST API üzerinden çalışır. Bu yüzden --user parametresiyle yetkilendirme yapmanız gerekir.

Temel Sipariş Sorgulama Komutları

Sipariş yönetim scriptleri yazmadan önce temel sorgu komutlarını kavramak şart.

# Belirli durumdaki siparişleri listele
wp wc shop_order list --status=processing --user=1 --format=table

# Belirli bir siparişin detayını gör
wp wc shop_order get 12345 --user=1 --format=json

# Son 30 günün siparişlerini say
wp eval '
$args = array(
    "post_type"   => "shop_order",
    "post_status" => array("wc-processing", "wc-completed"),
    "date_query"  => array(
        array(
            "after" => "30 days ago",
        ),
    ),
    "posts_per_page" => -1,
    "fields"         => "ids",
);
$orders = get_posts($args);
echo "Son 30 gun siparis sayisi: " . count($orders) . "n";
'

# Pending durumundaki siparişleri ID listesi olarak al
wp wc shop_order list --status=pending --user=1 --format=ids

Bu temel komutları anladıktan sonra asıl işe girebiliriz.

Senaryo 1: Bekleyen Siparişleri Otomatik İşleme Alan Script

En yaygın ihtiyaçlardan biri: ödeme onaylanan siparişleri otomatik olarak “processing” durumuna geçirmek. Bazı ödeme gateway’leri webhook’ları bazen gecikebilir veya başarısız olabilir.

#!/bin/bash
# /usr/local/bin/wc-pending-to-processing.sh

WP_PATH="/var/www/html/wordpress"
WP_USER="1"
LOG_FILE="/var/log/woocommerce/order-automation.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')

# Log dizini yoksa oluştur
mkdir -p /var/log/woocommerce

echo "[$DATE] Bekleyen siparis kontrolu basliyor..." >> $LOG_FILE

# Pending siparişleri al
PENDING_ORDERS=$(cd $WP_PATH && wp wc shop_order list 
    --status=pending 
    --user=$WP_USER 
    --format=ids 
    --allow-root 2>/dev/null)

if [ -z "$PENDING_ORDERS" ]; then
    echo "[$DATE] Bekleyen siparis bulunamadi." >> $LOG_FILE
    exit 0
fi

ORDER_COUNT=$(echo $PENDING_ORDERS | wc -w)
echo "[$DATE] $ORDER_COUNT adet bekleyen siparis bulundu." >> $LOG_FILE

for ORDER_ID in $PENDING_ORDERS; do
    # Siparişin oluşturulma zamanını kontrol et (1 saatten eski olanları işle)
    ORDER_AGE=$(cd $WP_PATH && wp eval "
        $order = wc_get_order($ORDER_ID);
        if ($order) {
            $created = $order->get_date_created()->getTimestamp();
            echo time() - $created;
        }
    " --allow-root 2>/dev/null)

    # 3600 saniye = 1 saat
    if [ ! -z "$ORDER_AGE" ] && [ "$ORDER_AGE" -gt 3600 ]; then
        # Siparişi processing'e al ve not ekle
        cd $WP_PATH && wp eval "
            $order = wc_get_order($ORDER_ID);
            if ($order && $order->get_status() === 'pending') {
                $order->update_status('processing', 'Otomatik sistem tarafindan isleme alindi.');
                $order->save();
                echo 'UPDATED';
            }
        " --allow-root 2>/dev/null

        echo "[$DATE] Siparis #$ORDER_ID processing durumuna gecildi." >> $LOG_FILE
    fi
done

echo "[$DATE] Islem tamamlandi." >> $LOG_FILE

Bu scripti crontab’a ekleyerek her saat çalıştırabilirsiniz:

# Crontab kaydı
0 * * * * /usr/local/bin/wc-pending-to-processing.sh

Senaryo 2: Eski İptal Edilmiş Siparişleri Temizleme

Veritabanı şişmesinin önüne geçmek için belirli süreden eski iptal edilmiş siparişleri arşivlemek veya silmek gerekebilir. Bu işlemi dikkatli yapmak lazım, önce log alıp sonra silmeyi öneririm.

#!/bin/bash
# /usr/local/bin/wc-cleanup-cancelled-orders.sh

WP_PATH="/var/www/html/wordpress"
ARCHIVE_DIR="/var/backups/woocommerce/cancelled-orders"
DATE=$(date '+%Y-%m-%d')
LOG_FILE="/var/log/woocommerce/cleanup.log"

mkdir -p $ARCHIVE_DIR
mkdir -p /var/log/woocommerce

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Temizlik islemi basliyor..." >> $LOG_FILE

# 90 günden eski iptal siparişlerini JSON olarak dışa aktar
cd $WP_PATH && wp eval '
$args = array(
    "post_type"      => "shop_order",
    "post_status"    => "wc-cancelled",
    "posts_per_page" => -1,
    "date_query"     => array(
        array(
            "before"    => "90 days ago",
            "inclusive" => true,
        ),
    ),
    "fields" => "ids",
);

$old_orders = get_posts($args);
$export_data = array();

foreach ($old_orders as $order_id) {
    $order = wc_get_order($order_id);
    if ($order) {
        $export_data[] = array(
            "id"         => $order_id,
            "status"     => $order->get_status(),
            "total"      => $order->get_total(),
            "customer"   => $order->get_billing_email(),
            "date"       => $order->get_date_created()->date("Y-m-d"),
            "items"      => count($order->get_items()),
        );
    }
}

echo json_encode($export_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
' --allow-root > $ARCHIVE_DIR/cancelled-orders-$DATE.json

EXPORTED=$(cat $ARCHIVE_DIR/cancelled-orders-$DATE.json | grep -c '"id"')
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $EXPORTED siparis arsivlendi: $ARCHIVE_DIR/cancelled-orders-$DATE.json" >> $LOG_FILE

# Sadece --dry-run parametresi geçilmemişse sil
if [ "$1" != "--dry-run" ]; then
    cd $WP_PATH && wp eval '
    $args = array(
        "post_type"      => "shop_order",
        "post_status"    => "wc-cancelled",
        "posts_per_page" => -1,
        "date_query"     => array(
            array(
                "before"    => "90 days ago",
                "inclusive" => true,
            ),
        ),
        "fields" => "ids",
    );

    $old_orders = get_posts($args);
    $deleted = 0;

    foreach ($old_orders as $order_id) {
        wp_delete_post($order_id, true);
        $deleted++;
    }

    echo "Silinen siparis sayisi: $deletedn";
    ' --allow-root >> $LOG_FILE
fi

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Temizlik tamamlandi." >> $LOG_FILE

Scripti test modunda çalıştırmak için:

# Önce dry-run ile test et
bash /usr/local/bin/wc-cleanup-cancelled-orders.sh --dry-run

# Sonuçtan memnunsanız gerçek çalıştırma
bash /usr/local/bin/wc-cleanup-cancelled-orders.sh

Senaryo 3: Günlük Sipariş Raporu Maili

Her sabah yöneticiye dünün özet raporunu gönderen script. Bunu kurmak müşteri memnuniyeti açısından gerçekten fark yaratıyor.

#!/bin/bash
# /usr/local/bin/wc-daily-report.sh

WP_PATH="/var/www/html/wordpress"
REPORT_EMAIL="[email protected]"
YESTERDAY=$(date -d "yesterday" '+%Y-%m-%d')

# WooCommerce'den dün istatistikleri çek
REPORT_DATA=$(cd $WP_PATH && wp eval "
$yesterday_start = '$YESTERDAY 00:00:00';
$yesterday_end   = '$YESTERDAY 23:59:59';

$args = array(
    'post_type'      => 'shop_order',
    'post_status'    => array('wc-completed', 'wc-processing', 'wc-refunded', 'wc-cancelled'),
    'posts_per_page' => -1,
    'date_query'     => array(
        array(
            'after'     => $yesterday_start,
            'before'    => $yesterday_end,
            'inclusive' => true,
        ),
    ),
    'fields' => 'ids',
);

$orders = get_posts($args);

$stats = array(
    'completed'  => 0,
    'processing' => 0,
    'cancelled'  => 0,
    'refunded'   => 0,
    'total_rev'  => 0,
    'total_ord'  => count($orders),
);

foreach ($orders as $order_id) {
    $order  = wc_get_order($order_id);
    $status = $order->get_status();
    
    if (isset($stats[$status])) {
        $stats[$status]++;
    }
    
    if (in_array($status, array('completed', 'processing'))) {
        $stats['total_rev'] += $order->get_total();
    }
}

echo 'TOPLAM_SIPARIS=' . $stats['total_ord'] . 'n';
echo 'TAMAMLANAN=' . $stats['completed'] . 'n';
echo 'ISLEMDEKI=' . $stats['processing'] . 'n';
echo 'IPTAL=' . $stats['cancelled'] . 'n';
echo 'IADE=' . $stats['refunded'] . 'n';
echo 'TOPLAM_GELIR=' . number_format($stats['total_rev'], 2) . 'n';
" --allow-root 2>/dev/null)

# Değerleri parse et
TOPLAM_SIPARIS=$(echo "$REPORT_DATA" | grep TOPLAM_SIPARIS | cut -d= -f2 | tr -d 'r')
TAMAMLANAN=$(echo "$REPORT_DATA" | grep TAMAMLANAN | cut -d= -f2 | tr -d 'r')
ISLEMDEKI=$(echo "$REPORT_DATA" | grep ISLEMDEKI | cut -d= -f2 | tr -d 'r')
IPTAL=$(echo "$REPORT_DATA" | grep IPTAL | cut -d= -f2 | tr -d 'r')
IADE=$(echo "$REPORT_DATA" | grep IADE | cut -d= -f2 | tr -d 'r')
TOPLAM_GELIR=$(echo "$REPORT_DATA" | grep TOPLAM_GELIR | cut -d= -f2 | tr -d 'r')

# Mail gönder
MAIL_BODY="WooCommerce Gunluk Raporu - $YESTERDAY

Toplam Siparis  : $TOPLAM_SIPARIS
Tamamlanan      : $TAMAMLANAN
Islemdeki       : $ISLEMDEKI
Iptal Edilen    : $IPTAL
Iade Edilen     : $IADE
----------------------------
Toplam Gelir    : ${TOPLAM_GELIR} TL

Bu rapor otomatik olarak olusturulmustur."

echo "$MAIL_BODY" | mail -s "[$YESTERDAY] WooCommerce Gunluk Raporu" $REPORT_EMAIL

echo "Rapor gonderildi: $REPORT_EMAIL"

Senaryo 4: Stok Durumuna Göre Otomatik Sipariş Uyarısı

Stok biten ürün içeren siparişleri tespit edip yöneticiye uyarı gönderen script. Özellikle yüksek hacimli mağazalarda bu durum sık yaşanır.

#!/bin/bash
# /usr/local/bin/wc-stock-order-alert.sh

WP_PATH="/var/www/html/wordpress"
ALERT_EMAIL="[email protected]"
LOG_FILE="/var/log/woocommerce/stock-alerts.log"

mkdir -p /var/log/woocommerce

PROBLEMATIC_ORDERS=$(cd $WP_PATH && wp eval '
$args = array(
    "post_type"      => "shop_order",
    "post_status"    => array("wc-processing", "wc-on-hold"),
    "posts_per_page" => -1,
    "fields"         => "ids",
);

$orders = get_posts($args);
$problems = array();

foreach ($orders as $order_id) {
    $order = wc_get_order($order_id);
    $order_problems = array();
    
    foreach ($order->get_items() as $item) {
        $product = $item->get_product();
        
        if (!$product) continue;
        
        if (!$product->is_in_stock()) {
            $order_problems[] = $product->get_name() . " (Stok tukendi)";
        } elseif ($product->managing_stock() && $product->get_stock_quantity() < $item->get_quantity()) {
            $order_problems[] = $product->get_name() . " (Yeterli stok yok: " . $product->get_stock_quantity() . " adet mevcut, " . $item->get_quantity() . " adet gerekli)";
        }
    }
    
    if (!empty($order_problems)) {
        $problems[] = "Siparis #$order_id - Musteri: " . $order->get_billing_email() . "n  " . implode("n  ", $order_problems);
    }
}

if (!empty($problems)) {
    echo implode("nn", $problems);
}
' --allow-root 2>/dev/null)

if [ ! -z "$PROBLEMATIC_ORDERS" ]; then
    MAIL_CONTENT="STOK UYARISI - $(date '+%Y-%m-%d %H:%M')

Asagidaki siparisler stok sorunu icermektedir:

$PROBLEMATIC_ORDERS

Lutfen en kisa surede mudahale ediniz."

    echo "$MAIL_CONTENT" | mail -s "[STOK UYARISI] WooCommerce Stok Problemi" $ALERT_EMAIL
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Stok uyarisi gonderildi." >> $LOG_FILE
else
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] Stok sorunu bulunmadi." >> $LOG_FILE
fi

Senaryo 5: Toplu Sipariş Durumu Güncelleme

Bazen bir ödeme servis sağlayıcısında sorun çıkar ve onlarca sipariş yanlış durumda kalır. Bu script toplu güncelleme yapmanızı sağlar.

#!/bin/bash
# /usr/local/bin/wc-bulk-status-update.sh
# Kullanim: ./wc-bulk-status-update.sh <kaynak-durum> <hedef-durum> [siparis-id-listesi.txt]

WP_PATH="/var/www/html/wordpress"
SOURCE_STATUS=${1:-"on-hold"}
TARGET_STATUS=${2:-"processing"}
ID_FILE=$3
LOG_FILE="/var/log/woocommerce/bulk-update.log"

mkdir -p /var/log/woocommerce

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Toplu guncelleme basliyor: $SOURCE_STATUS -> $TARGET_STATUS" >> $LOG_FILE

if [ ! -z "$ID_FILE" ] && [ -f "$ID_FILE" ]; then
    # Dosyadan ID listesi oku
    ORDER_IDS=$(cat $ID_FILE | tr 'n' ' ')
    echo "Dosyadan ${ORDER_IDS} siparisi okundu."
else
    # Otomatik olarak duruma gore siparisleri bul
    ORDER_IDS=$(cd $WP_PATH && wp wc shop_order list 
        --status=$SOURCE_STATUS 
        --user=1 
        --format=ids 
        --allow-root 2>/dev/null)
fi

if [ -z "$ORDER_IDS" ]; then
    echo "Guncellenecek siparis bulunamadi."
    exit 0
fi

SUCCESS=0
FAILED=0

for ORDER_ID in $ORDER_IDS; do
    RESULT=$(cd $WP_PATH && wp eval "
        $order = wc_get_order($ORDER_ID);
        if ($order && $order->get_status() === '$SOURCE_STATUS') {
            $order->update_status('$TARGET_STATUS', 'Toplu durum guncellemesi yapildi.');
            $order->add_order_note('Durum otomatik olarak guncellendi: $SOURCE_STATUS -> $TARGET_STATUS');
            $order->save();
            echo 'SUCCESS';
        } else {
            echo 'SKIP';
        }
    " --allow-root 2>/dev/null)

    if [ "$RESULT" = "SUCCESS" ]; then
        SUCCESS=$((SUCCESS + 1))
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] #$ORDER_ID guncellendi." >> $LOG_FILE
    else
        FAILED=$((FAILED + 1))
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] #$ORDER_ID atlandi veya hata." >> $LOG_FILE
    fi
    
    # Sunucuya yük bindirmemek için küçük bekleme
    sleep 0.1
done

echo ""
echo "Tamamlandi: $SUCCESS basarili, $FAILED atlandi/hata"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Tamamlandi: $SUCCESS basarili, $FAILED atlandi/hata" >> $LOG_FILE

Kullanım örnekleri:

# On-hold durumundaki tüm siparişleri processing'e al
bash /usr/local/bin/wc-bulk-status-update.sh on-hold processing

# Belirli ID'leri içeren dosyadan güncelle
echo -e "12345n12346n12347" > /tmp/order-ids.txt
bash /usr/local/bin/wc-bulk-status-update.sh on-hold processing /tmp/order-ids.txt

Scriptleri Güvenli Hale Getirmek

Üretim ortamında bu scriptleri çalıştırmadan önce birkaç kritik noktaya dikkat etmek gerekiyor.

WordPress path doğrulama:

#!/bin/bash
# Her scriptin başına ekleyin

WP_PATH="/var/www/html/wordpress"

# WordPress kurulumunu doğrula
if [ ! -f "$WP_PATH/wp-config.php" ]; then
    echo "HATA: WordPress dizini bulunamadi: $WP_PATH"
    exit 1
fi

# WP-CLI'nin çalıştığını doğrula
if ! command -v wp &> /dev/null; then
    echo "HATA: WP-CLI bulunamadi. PATH: $PATH"
    exit 1
fi

# WooCommerce'in aktif olduğunu doğrula
IS_ACTIVE=$(cd $WP_PATH && wp plugin is-active woocommerce --allow-root 2>&1)
if [ $? -ne 0 ]; then
    echo "HATA: WooCommerce aktif degil veya erisim sorunu var."
    exit 1
fi

echo "Ortam dogrulama basarili."

Log Rotasyonu ve İzleme

Scriptlerin ürettiği logları yönetmek için logrotate konfigürasyonu:

# /etc/logrotate.d/woocommerce dosyasını oluşturun
cat > /etc/logrotate.d/woocommerce << 'EOF'
/var/log/woocommerce/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 www-data www-data
}
EOF

# Logrotate'i test et
logrotate --debug /etc/logrotate.d/woocommerce

Crontab’ı düzenli scriptlerle doldurmamak için merkezi bir zamanlama scripti oluşturmak mantıklı:

# /usr/local/bin/wc-scheduler.sh
#!/bin/bash

HOUR=$(date '+%H')
MINUTE=$(date '+%M')

# Saatlik: Bekleyen sipariş kontrolü
bash /usr/local/bin/wc-pending-to-processing.sh

# Her sabah 08:00: Günlük rapor
if [ "$HOUR" = "08" ] && [ "$MINUTE" = "00" ]; then
    bash /usr/local/bin/wc-daily-report.sh
fi

# Her sabah 06:00: Stok uyarısı
if [ "$HOUR" = "06" ] && [ "$MINUTE" = "00" ]; then
    bash /usr/local/bin/wc-stock-order-alert.sh
fi

# Pazar 03:00: Eski iptal siparişlerini temizle
if [ "$(date '+%u')" = "7" ] && [ "$HOUR" = "03" ] && [ "$MINUTE" = "00" ]; then
    bash /usr/local/bin/wc-cleanup-cancelled-orders.sh
fi

Crontab’a tek satır eklemek yeterli:

# Crontab
* * * * * /usr/local/bin/wc-scheduler.sh >> /var/log/woocommerce/scheduler.log 2>&1

Dikkat Edilmesi Gereken Noktalar

--allow-root parametresi: Scriptler root kullanıcısıyla çalışıyorsa bu parametreyi eklemeniz gerekir. Üretimde mümkünse www-data kullanıcısıyla çalıştırmak daha güvenlidir.

Veritabanı yedekleme: Toplu işlem yapan her script öncesinde mutlaka veritabanı yedeği alın:

  • wp db export /var/backups/woocommerce/pre-bulk-update-$(date +%Y%m%d).sql --allow-root

WooCommerce aksiyonları: update_status() metodu otomatik olarak ilgili email’leri ve aksiyonları tetikler. Toplu işlemlerde müşterilere çok fazla mail göndermek istemiyorsanız wc_update_order_status() yerine doğrudan post meta güncellemesi yapmayı düşünebilirsiniz.

Rate limiting: Çok sayıda siparişi işlerken aralarına küçük bekleme süresi koyun (sleep 0.1). Aksi halde veritabanını zorlayabilirsiniz.

Test ortamı: Bu scriptleri production’a almadan önce mutlaka staging ortamında test edin. WP-CLI’nin --url parametresini kullanarak multisite kurulumlarında doğru siteyi hedeflediğinizden emin olun.

Sonuç

WP-CLI ile WooCommerce sipariş yönetimini otomatize etmek, küçük bir yatırımla büyük operasyonel kazanımlar sağlıyor. Özellikle günlük rapor scripti ve stok uyarı sistemi, müşteri şikayetleri gelmeden problemi yakalamanızı sağlıyor.

Bu scriptlerin hepsini production’da kullanıyorum ve her biri gerçek ihtiyaçlardan doğdu. Başlangıç olarak günlük rapor scriptini kurun, logları bir süre izleyin, sonra diğerlerini ekleyin. Scriptleri kendi iş süreçlerinize göre uyarlayın; her WooCommerce kurulumu biraz farklı davranır.

WP-CLI belgelerini ve WooCommerce’in PHP API referanslarını sürekli açık tutmak işinizi kolaylaştıracak. wp eval içinde çalışan her PHP kodu WooCommerce’in tüm API’sine erişebilir, bu sayede yapabileceğiniz işlemlerin sınırı neredeyse yok.

Bir yanıt yazın

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