我努力寻找一种方法来更新产品类似版本的库存。
我的所有产品都有一个主要的变体,例如“黑色”(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;
答案 0 :(得分:1)
好的,在这种情况下,如果不使用元数据/属性,而不是使用变体,这似乎有点奇怪。但是,与变化相比,我在变化方面做了更多不寻常的事情,因此无需判断您的决定:
首先,您必须找到一个合适的动作挂钩,该挂钩在下订单后触发。其中一些是:
woocommerce_order_status_completed
)我对代码进行了一些改进:
在我最初的回答中,我使用了带有meta_query参数的WordPress get_posts函数(使用WP_Query),出于性能方面的考虑,在这种情况下,您绝对应该将其更改为tax_query。我们也知道,最好在可能的地方使用wc_get_products and WC_Product_Query。但是,在这种情况下,甚至不需要对db进行直接后置查询,并且可以从WC_Product_Variable
的
get_available_variations
方法获得变化
现在它检查订单物料上的数量,并将其用于其他日期变化库存更新。
现在,它尽可能使用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_date
和attribute_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)
}
}
}
}