Czyszczenie magazynu w woocommerce

Kolejne ciekawe zagadnienie. Klient chciałby pozbyć się końcówek towaru z magazynu. Rzecz jasna aby tego dokonać daje cenę promocyjną. I tutaj zaczyna się problem. W sklepie można dokonywać zamówień z opóźnioną dostawą przy brakach magazynowych. Jednak już nie w cenie promocyjnej. Czyli potrzebny jest kod, który usunie cenę promocyjną w momencie, gdy stan magazynowy produktu spadnie do zera.

Przyjrzymy się jednocześnie czy zastosowany kod będzie poprawny dla woocommerce z nową wersją magazynu HPOS.

function remove_sale_price_when_out_of_stock( $product_id ) {
    $product = wc_get_product( $product_id );

    if ( ! $product ) {
        return;
    }

    // Sprawdzenie, czy produkt jest prosty czy wariantowy
    if ( $product->is_type( 'simple' ) || $product->is_type( 'variation' ) ) {
        if ( $product->get_stock_quantity() === 0 ) {
            $product->set_sale_price( '' );
            $product->save();
        }
    } elseif ( $product->is_type( 'variable' ) ) {
        // Jeśli produkt jest wariantowy, sprawdzamy każdy jego wariant
        foreach ( $product->get_children() as $variation_id ) {
            $variation = wc_get_product( $variation_id );
            if ( $variation && $variation->get_stock_quantity() === 0 ) {
                $variation->set_sale_price( '' );
                $variation->save();
            }
        }
    }
}

// Akcja uruchamiająca funkcję po zmianie stanu magazynowego
add_action( 'woocommerce_product_set_stock', 'remove_sale_price_when_out_of_stock' );
add_action( 'woocommerce_product_set_stock_status', 'remove_sale_price_when_out_of_stock' );

Nasz kod działa poprawnie w klasycznej wersji WooCommerce, ale nie będzie działał poprawnie z HPOS (High-Performance Order Storage) w każdej sytuacji. HPOS przenosi dane o produktach i zamówieniach do własnych tabel w bazie danych, co może wpłynąć na sposób odczytu i zapisu informacji o stanie magazynowym.

Co poprawić, aby działało w HPOS?

  1. HPOS nie używa post meta – Operacje zapisu do bazy w HPOS są zoptymalizowane i wymagają lepszego wykorzystania metod WooCommerce.
  2. Zdarzenia stockowe w HPOS – Należy użyć nowych hooków związanych ze zmianą stanu magazynowego.

Poprawiona wersja kodu – działa na HPOS i klasycznych tabelach WooCommerce:

function remove_sale_price_when_out_of_stock( $product_id ) {
    $product = wc_get_product( $product_id );

    if ( ! $product ) {
        return;
    }

    // Pobieramy aktualny stan magazynowy
    $stock_quantity = $product->get_stock_quantity();
    $stock_status = $product->get_stock_status();

    // Jeśli produkt jest wyprzedany, usuwamy cenę promocyjną
    if ( $stock_quantity === 0 || $stock_status === 'outofstock' ) {
        $product->set_sale_price( '' );
        $product->save();
    }

    // Obsługa wariantów w produktach zmiennych
    if ( $product->is_type( 'variable' ) ) {
        foreach ( $product->get_children() as $variation_id ) {
            $variation = wc_get_product( $variation_id );

            if ( $variation ) {
                $variation_stock_quantity = $variation->get_stock_quantity();
                $variation_stock_status = $variation->get_stock_status();

                if ( $variation_stock_quantity === 0 || $variation_stock_status === 'outofstock' ) {
                    $variation->set_sale_price( '' );
                    $variation->save();
                }
            }
        }
    }
}

// HPOS + klasyczne tabele WooCommerce - obsługa zmian magazynowych
add_action( 'woocommerce_product_set_stock', 'remove_sale_price_when_out_of_stock', 10, 1 );
add_action( 'woocommerce_product_set_stock_status', 'remove_sale_price_when_out_of_stock', 10, 1 );
add_action( 'woocommerce_variation_set_stock', 'remove_sale_price_when_out_of_stock', 10, 1 ); // Dodatkowy hook dla wariantów
add_action( 'woocommerce_variation_set_stock_status', 'remove_sale_price_when_out_of_stock', 10, 1 ); // Dodatkowy hook dla wariantów

Optymalna wersja kodu – tylko dla HPOS

function remove_sale_price_when_out_of_stock_hpos( $product ) {
    if ( ! is_a( $product, 'WC_Product' ) ) {
        return;
    }

    // Pobieramy aktualny stan magazynowy
    $stock_quantity = $product->get_stock_quantity();
    $stock_status = $product->get_stock_status();

    // Jeśli produkt jest wyprzedany, usuwamy cenę promocyjną
    if ( $stock_quantity === 0 || $stock_status === 'outofstock' ) {
        $product->set_sale_price( '' );
        $product->save();
    }

    // Obsługa wariantów w produktach zmiennych
    if ( $product->is_type( 'variable' ) ) {
        foreach ( $product->get_children() as $variation_id ) {
            $variation = wc_get_product( $variation_id );

            if ( $variation ) {
                $variation_stock_quantity = $variation->get_stock_quantity();
                $variation_stock_status = $variation->get_stock_status();

                if ( $variation_stock_quantity === 0 || $variation_stock_status === 'outofstock' ) {
                    $variation->set_sale_price( '' );
                    $variation->save();
                }
            }
        }
    }
}

// Obsługa wyłącznie HPOS – WooCommerce 8.0+
add_action( 'woocommerce_product_object_updated_props', 'remove_sale_price_when_out_of_stock_hpos', 10, 1 );
add_action( 'woocommerce_variation_object_updated_props', 'remove_sale_price_when_out_of_stock_hpos', 10, 1 );

Co zmieniłem dla HPOS?

Usunięcie starych hookówwoocommerce_product_set_stock i woocommerce_product_set_stock_status są powiązane z post meta, a w HPOS przechodzimy na woocommerce_product_object_updated_props.
Optymalizacja dla HPOS – Wykorzystujemy woocommerce_product_object_updated_props, które działa na obiektach WC_Product. Jest to zgodne z nowym sposobem przechowywania zamówień i produktów.
Lżejsza i szybsza implementacja – Skupiamy się tylko na WooCommerce 8.x+ z HPOS, nie obciążając starszych systemów.

Przewijanie do góry