Как обновить аналогичный вариант акции после покупки в Woocommerce - PullRequest
0 голосов
/ 20 июня 2019

Я изо всех сил пытаюсь найти способ обновить запас аналогичного варианта продукта.

Все мои продукты имеют, скажем, основной вариант, «черный» (30 $) или «белый» (250 $), но иногда они имеют другой вариант, который является «датой начала», поэтому date_start: «12 июня» , date_start: "30 июля" и т. д. Мне нужно обновить запас варианта "date", когда он присутствует (если даты нет, woocommerce обновит основной запас, нет проблем). Если кто-то выберет «черный» + «12 июня», мне нужно уменьшить акцию «12 июня» и на «белый» ...

Прежде чем кто-то спросит, у "черного" и "белого" разные цены на продукт ... И "дата" меняется также на продукт, поэтому мне нужно использовать вариант (а не атрибут аддона с плагином). Может быть, у кого-то есть лучшая идея для организации этого, но я пробую много других решений, всегда предостережение. Это кажется более простым, просто нужно найти хороший "крючок" и "код"

Вот некоторый псевдокод, который я сделал для этого:

if(Product is sold):
VarSoldVariation = getSoldVariation(product->ID);
OtherVariationWithSameDate = getVariations (VarSoldVariation->pa_dates);
foreach(OtherVariationWithSameDate)updateStockVariation();
endif;

Ответы [ 2 ]

1 голос
/ 22 июня 2019

ОК, это немного странно, если не использовать метаданные / атрибуты для этого случая вместо вариантов. Тем не менее, я сделал более необычные вещи с вариациями, чем этот, поэтому без суждения о вашем решении:

Сначала вы должны найти подходящий крюк действия, который срабатывает после выполнения заказа. Вот некоторые из них:

Обновление 2:

Я переписал код с некоторыми улучшениями:

  1. В своем первоначальном ответе я использовал функцию get_posts в WordPress (которая использует WP_Query) с параметром meta_query, который в этом случае вам непременно следует изменить на tax_query из соображений производительности. И мы также знаем, что лучше использовать wc_get_products и WC_Product_Query , где это возможно. Однако в этом случае даже нет необходимости делать прямой пост-запрос к БД, и можно получить варианты из get_available_variations метода WC_Product_Variable

  2. Теперь он проверяет количество в позиции заказа и использует его для обновления запаса других изменений даты.

  3. Теперь он использует классы и функции WC везде, где это возможно, вместо прямого обновления метаданных, количества запаса, состояния запаса и т. Д.

Обновленный код:

add_action('woocommerce_order_status_processing', 'sync_variations_stock');

/**
 * Update same date variations on customer order place
 * @param $order_id
 * @return void
 */
function sync_variations_stock($order_id)
{
    if (is_admin()) return; // make sure it's a user order and we aren't on admin dashboard
    $order = wc_get_order( $order_id );
    foreach( $order->get_items() as $item ) {
        if ($item->get_type() !== 'line_item') continue;    //if $item is not a product or variation
        $order_variation_count   = $item->get_quantity();
        $order_product_id        = $item->get_product_id();
        $order_variation_id      = $item->get_variation_id();

        if ( ! $order_variation_id ) continue;    // if the item isn't a variation

        $order_variation         = wc_get_product($order_variation_id);
        $order_variation_attribs = $order_variation->get_variation_attributes();
        if ( isset($order_variation_attribs['attribute_pa_date']) ) {
            $current_date_attrib = $order_variation_attribs['attribute_pa_date'];
        } else {
            continue; // stop if the variation in the order doesn't have 'pa_date' attrib
        }

        $product    = wc_get_product( $order_product_id );
        $variations = $product->get_available_variations();
        foreach ( $variations as $variation ) {
            if ( $variation['variation_id'] == $order_variation_id ) {
                continue;   //if this variation is the one we have in our order
            }
            if ( ! isset( $variation['attributes']['attribute_pa_color'] ) || !isset( $variation['attributes']['attribute_pa_date'] ) ) {
                continue;   //if this variation does not have the color or date attrib
            }

            if ( $variation['attributes']['attribute_pa_date'] == $current_date_attrib ) {

                /*
                 * wc_update_product_stock function sets the stock quantity if the variation stock management is enabled
                 * NOTE: This function may cause a negative stock even if the variation backorder is set to false
                 */
                wc_update_product_stock( $variation['variation_id'], $order_variation_count, 'decrease' );
                wc_delete_product_transients($variation['variation_id']); // Clear/refresh the variation cache (optionally if needed)
            }
        }
    }
}

Проверено и работает!

Мой первый ответ:

В этом примере я буду использовать последний. Однако вам следует быть осторожным с этим хуком, так как он срабатывает при каждой загрузке страницы "Спасибо вам за страницу". Было бы неплохо использовать вместо этого один из следующих хуков:
woocommerce_order_status_processing
woocommerce_order_status_completed
woocommerce_payment_complete

Финальный код будет выглядеть примерно так:

add_action('woocommerce_thankyou', 'sync_variations_stock');

function sync_variations_stock($order_id)
{
    $order = wc_get_order( $order_id );
    foreach( $order->get_items() as $item ){
        $product_id = $item->get_product_id();
        $product_variation_id = $item->get_variation_id();

        if (!$product_variation_id) return; // if the item isn't a variation

        $date_variation = get_post_meta( $product_variation_id, 'attribute_pa_date', true);
        $color_variation = get_post_meta( $product_variation_id, 'attribute_pa_color', true);

        if ( ! $date_variation && ! $color_variation ) return;  //if the variation doesn't have date and color attributes

        $args = array(
            'post_parent' => $product_id,
            'post_type' => 'product_variation',
            'posts_per_page' => -1,
            'meta_query' => array(
                array(
                    'key' => 'attribute_pa_date',
                    'value' => $date_variation,
                    'compare' => '='
                ),
                array(
                    'key' => 'attribute_pa_color',
                    'value' => $color_variation,
                    'compare' => '!='
                )
            ),
        );
        $other_date_variations = get_posts($args);

        if( is_array($other_date_variations) && !empty($other_date_variations) ){
            foreach ($other_date_variations as $date_variation) {

                // do your stock updating proccess here. (updateStockVariation() as you write in your code)

                $variation_id = $date_variation->ID;
                $date_variation_stock = (int) get_post_meta( $variation_id, '_stock', true);
                if ($date_variation_stock > 0) {    //to prevent backorders
                    $date_variation_stock =  $date_variation_stock - 1;
                    update_post_meta($variation_id, '_stock', $date_variation_stock);

                    // if the variation is now out-of-stock, set it as so
                    if ($date_variation_stock === 0) {
                        update_post_meta($variation_id, '_stock_status', 'outofstock');
                        wp_set_post_terms( $variation_id, 'outofstock', 'product_visibility', true );
                    }
                }
            }
        }
    }
}

Примечание: Вы должны заменить attribute_pa_date & attribute_pa_color, чтобы соответствовать слагам вашего атрибута.

Обновление 1
Есть другие соображения в этой теме. Количество запасов в вариации WC может быть изменено в других параметрах и обстоятельствах, таких как редактирование заказа на приборной панели, возврат заказов, прямое редактирование продукта и т. Д. Прежде чем приступить к работе, вы должны подумать об этом.
У кого бы я ни говорил, могут быть другие способы сделать то, что вы пытаетесь. Но я не мог понять вашу настройку и связь между вашими вариациями и датами. Я думаю, что для этого лучше задать вопрос, связанный с подходом, на WB.SE

0 голосов
/ 26 июня 2019

Я также только что сделал небольшое изменение.В вашем коде, если люди обновляют страницу, запас другого варианта уменьшается ... Поскольку woocommerce всегда будет сначала уменьшать запас купленного варианта, я пойду, получу этот номер запаса и обновлю другой вариант.Так что я уверен, что все остается прежним.:) Вот обновленный код:

    function sync_variations_stock($order_id)
    {
        if (is_admin()) return; // make sure it's a user order and we aren't on admin dashboard
        $order = wc_get_order( $order_id );
        foreach( $order->get_items() as $item ) {
            if ($item->get_type() !== 'line_item') continue;    //if $item is not a product or variation
            $order_variation_count   = $item->get_quantity();
            $order_product_id        = $item->get_product_id();
            $order_variation_id      = $item->get_variation_id();

            if ( ! $order_variation_id ) continue;    // if the item isn't a variation

            $order_variation         = wc_get_product($order_variation_id);
            $order_variation_attribs = $order_variation->get_variation_attributes();
            if ( isset($order_variation_attribs['attribute_pa_dates']) ) {
                $current_date_attrib = $order_variation_attribs['attribute_pa_dates'];
//Get the stock of the current variation for updating others.
                $new_stock = $order_variation->get_stock_quantity();
            } else {
                continue; // stop if the variation in the order doesn't have 'pa_dates' attrib
            }

            $product    = wc_get_product( $order_product_id );
            $variations = $product->get_available_variations();
            foreach ( $variations as $variation ) {
                if ( $variation['variation_id'] == $order_variation_id ) {
                    continue;   //if this variation is the one we have in our order
                }
                if ( ! isset( $variation['attributes']['attribute_pa_admissible-emploi-quebec'] ) || !isset( $variation['attributes']['attribute_pa_dates'] ) ) {
                    continue;   //if this variation does not have the color or date attrib
                }

                if ( $variation['attributes']['attribute_pa_dates'] == $current_date_attrib ) {

                    /*
                     * wc_update_product_stock function sets the stock quantity if the variation stock management is enabled
                     * NOTE: This function may cause a negative stock even if the variation backorder is set to false
                     */
                    //wc_update_product_stock( $variation['variation_id'], $order_variation_count, 'decrease' );
//Update stock of other variation with the stock number of the one just bought
                    wc_update_product_stock( $variation['variation_id'], $new_stock, 'set' );
                    wc_delete_product_transients($variation['variation_id']); // Clear/refresh the variation cache (optionally if needed)
                }
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...