在Woocommerce中购买后如何更新类似的变化库存

时间:2019-06-20 16:33:59

标签: wordpress woocommerce hook-woocommerce

我努力寻找一种方法来更新产品类似版本的库存。

我的所有产品都有一个主要的变体,例如“黑色”(30美元)或“白色”(250美元),但有时它们还有另一个变体,即“日期开始”,因此date_start:“ 6月12日” ,date_start:“ 7月30日”等。我需要更新“ date”变体的库存(如果没有日期,则woocommerce更新主要库存,没有问题)。 如果有人选择“黑色” +“ 6月12日”,我还需要减少“白色”的“ 6月12日”库存...

在有人问之前,“黑色”和“白色”每种产品的价格都不同...而且每种产品的“日期”也有所变化,这就是为什么我需要使用变体(而不是插件的addon属性)的原因。 也许有人对此有一个更好的主意,但是我尝试了许多其他解决方案,始终是警告。这个似乎更简单,只需要找到好的“钩子”和“代码”

这是我为此编写的一些伪代码:

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

2 个答案:

答案 0 :(得分:1)

好的,在这种情况下,如果不使用元数据/属性,而不是使用变体,这似乎有点奇怪。但是,与变化相比,我在变化方面做了更多不寻常的事情,因此无需判断您的决定:

首先,您必须找到一个合适的动作挂钩,该挂钩在下订单后触发。其中一些是:

更新2:

我对代码进行了一些改进:

  1. 在我最初的回答中,我使用了带有meta_query参数的WordPress get_posts函数(使用WP_Query),出于性能方面的考虑,在这种情况下,您绝对应该将其更改为tax_query。我们也知道,最好在可能的地方使用wc_get_products and WC_Product_Query。但是,在这种情况下,甚至不需要对db进行直接后置查询,并且可以从WC_Product_Variable

  2. get_available_variations方法获得变化
  3. 现在它检查订单物料上的数量,并将其用于其他日期变化库存更新。

  4. 现在,它尽可能使用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)
            }
        }
    }
}

经过测试,可以正常工作!

我的第一个答案:

在此示例中,我将使用最后一个。但是,您应该对此挂钩小心,因为它会在“ WC Thank You页面”的每个页面加载时触发。最好使用以下其中一个挂钩:
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_dateattribute_pa_color才能匹配属性段。

更新1
此主题还有其他考虑事项。在其他情况下,例如,在仪表板上进行订单编辑,订单退款,直接产品编辑等,可能会更改WC Variation库存数量。在上线之前,您也必须考虑这些问题。
正如我所说的,可能还有其他方法可以完成您尝试做的事情。但是我无法理解您的设置以及变体和日期之间的关系。我认为最好在WB.SE上提出与方法相关的问题

答案 1 :(得分:0)

我也做了一点零钱。在您的代码中,如果人们刷新页面,则其他版本的库存将减少...由于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)
                }
            }
        }
    }