ОК, это немного странно, если не использовать метаданные / атрибуты для этого случая вместо вариантов. Тем не менее, я сделал более необычные вещи с вариациями, чем этот, поэтому без суждения о вашем решении:
Сначала вы должны найти подходящий крюк действия, который срабатывает после выполнения заказа. Вот некоторые из них:
Обновление 2:
Я переписал код с некоторыми улучшениями:
В своем первоначальном ответе я использовал функцию get_posts в WordPress (которая использует WP_Query) с параметром meta_query, который в этом случае вам непременно следует изменить на tax_query из соображений производительности. И мы также знаем, что лучше использовать wc_get_products и WC_Product_Query , где это возможно. Однако в этом случае даже нет необходимости делать прямой пост-запрос к БД, и можно получить варианты из get_available_variations
метода WC_Product_Variable
Теперь он проверяет количество в позиции заказа и использует его для обновления запаса других изменений даты.
Теперь он использует классы и функции 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