在Woocommerce中购买后如何更新类似的变化量库存 [英] How to update similar variation stock after purchase in Woocommerce

查看:83
本文介绍了在Woocommerce中购买后如何更新类似的变化量库存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I struggle to find a way to update the stock of the similar variation of a product.

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

All my product have, say, a main variation, "Black" (30$) or "white" (250$) but sometimes they have another variation which is a "date start", so date_start:"12th june", date_start: "30th july", etc. I need to update the stock of the "date" variation when it's present (if there is no date, woocommerce update the main stock, no problem). If someone choose "Black"+"12th June" I need the stock of "12 June" to be decreased also for "white"...

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

Before someone ask, "black" and "white" have different price per product... And "date" change also per product, that's why I need to use variation (and not addon attribute with a plugin). Maybe someone have a better idea for organising this, but I try many other solution, always a caveat. This one seems the simpler, just have to find the good "hook" and "code"

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

Here is some pseudo code I made for this:

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

推荐答案

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

OK, it seems a little weird for not using metadata/attributes for this case, instead of variations. However, I've done more unusual stuff with variations than this one, so without judging your decision:

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

At first, you have to find a suitable action hook which fires after an order takes place. Some of them are:

  • woocommerce_order_status_$STATUS_TRANSITION[from]_to_$STATUS_TRANSITION[to]
  • woocommerce_order_status_$STATUS_TRANSITION[to] (e.g. woocommerce_order_status_completed)
  • woocommerce_order_status_changed
  • woocommerce_payment_complete
  • woocommerce_thankyou

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

I rewrite the code with some improvements:

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

  1. In my initial answer, I used a WordPress get_posts function (which uses WP_Query) with a meta_query parameter, which you should definitely change to tax_query in this case, due to performance considerations. And we also know that it's better practice to use wc_get_products and WC_Product_Query where it's possible. However in this case it's not even needed to do a direct post query on db and it's possible to get the variations from get_available_variations method of WC_Product_Variable

现在,它检查订单物料上的数量,并将其用于其他日期变化库存更新.

Now it checks for quantity on order item and uses it on other date variations stock update.

现在,它尽可能使用WC类和函数,而不是直接更新元数据,库存数量,库存状态等.

Now it uses WC classes and functions wherever is possible, instead of direct updating of metadata, stock quantity, stock status, etc.

更新后的代码:

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

For this example, I will use the last one. However you should be careful about this hook, since it fires on every page load of the 'WC Thank You page'. It would be a good idea to use one of these hooks instead:
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以匹配您的属性段.

Note: You have to replace attribute_pa_date & attribute_pa_color to match your attribute slugs.

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

Update 1
There are other consideration in this topic. WC Variation stock quantities may be changed in other senarios and circumstances, such as order edit on dashboard, order refunds, direct product edit, etc. Before going live, you have to think about these too.
Whoever as I said, there may be other ways to do what you are trying to. But I couldn't understand your setup and the relation between your variations and the dates. I think it's better to ask a approach related question for this, on WB.SE

这篇关于在Woocommerce中购买后如何更新类似的变化量库存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆