Как мне предотвратить сокращение запаса вдвое с помощью этого кода разделенного заказа в Woocommerce?

Вопрос или проблема

Я использую этот код, который разделяет элементы заказов WooCommerce на отдельные заказы. Я нашел это на WP Answers, который я модифицировал для плагина билетирования событий.

Все работает отлично, на каждом билете есть QR-код, который проверяет и предотвращает дублирование билетов, с пользовательским статусом заказа, поэтому мне нужно, чтобы каждый билет был отдельным заказом. Я не могу понять, как остановить уменьшение запасов на оригинальном заказе, а также на запасах, которые уменьшаются для новых заказов. Например, если я покупаю 3 билета, то уменьшается 6 с общего запаса.

Это код, я буду признателен любому, кто сможет помочь.

add_action("woocommerce_thankyou", "action_woocommerce_checkout_order_processed", 10, 1);

function action_woocommerce_checkout_order_processed($order_id) {
    // Получите объект заказа
    $order = wc_get_order($order_id);
    $taxonomy = "product_tag";
    $items_to_remove = array();

    // Перебираем каждый элемент в заказе
    foreach ($order->get_items() as $item_key => $item) {
        $product = $item->get_product();
        $product_id = $item->get_product_id();
        $quantity = $item->get_quantity();

        // Проверяем, есть ли у продукта тег 'ticket'
        if (has_term('ticket', $taxonomy, $product_id)) {
            $items_to_remove[] = $item->get_id(); // Отметить этот элемент для удаления

            // Отметить запас как уже уменьшенный для этого элемента
            wc_update_order_item_meta($item->get_id(), '_stock_reduced', 'yes');

            // Создать новые заказы для каждого количества билетов
            for ($i = 1; $i <= $quantity; $i++) {
                $new_order = wc_create_order();

                // Добавить продукт в новый заказ с количеством 1
                $new_order->add_product($product, 1);

                // Скопировать информацию о выставлении и доставке
                $new_order->set_address($order->get_address('billing'), 'billing');
                $new_order->set_address($order->get_address('shipping'), 'shipping');
                $new_order->set_currency($order->get_currency());
                $new_order->set_payment_method($order->get_payment_method());
                $new_order->set_payment_method_title($order->get_payment_method_title());
                $new_order->set_date_paid(current_time('mysql')); // Отметить как оплаченный

                // Уменьшить запас вручную на 1
                if ($product->managing_stock()) {
                    wc_update_product_stock($product, $product->get_stock_quantity() - 1);
                }

                // Скопировать пользовательские поля для каждого билета (имя и электронная почта)
                $ticket_name_meta_key = "ticket_name_{$item_key}_{$i}";
                $ticket_email_meta_key = "ticket_email_{$item_key}_{$i}";

                $ticket_name = get_post_meta($order_id, $ticket_name_meta_key, true);
                $ticket_email = get_post_meta($order_id, $ticket_email_meta_key, true);

                if (!empty($ticket_name)) {
                    update_post_meta($new_order->get_id(), 'ticket_name', $ticket_name);
                }
                if (!empty($ticket_email)) {
                    update_post_meta($new_order->get_id(), 'ticket_email', $ticket_email);
                }

                // Рассчитать итоги и сохранить новый заказ
                $new_order->calculate_totals();
                $new_order->save();

                // Добавить заметку о заказе для отслеживания
                $new_order->add_order_note(
                    'Автоматический заказ "билета". Создан из оригинального заказа ID: ' . $order_id
                );
            }
        }
    }

    // Удалить элементы билетов из оригинального заказа, чтобы предотвратить дублирование записей
    foreach ($items_to_remove as $item_id) {
        $order->remove_item($item_id);
    }

    // Пересчитать и сохранить оригинальный заказ
    $order->calculate_totals();
    $order->save();
}

Ответ или решение

Как предотвратить двойное снижение запасов при использовании кода для разделения заказов в WooCommerce?

В процессе написания кода для вашего плагина Event Ticket вы столкнулись с проблемой уменьшения запасов на складском учете. Давайте проанализируем ваш код и предложим решение, которое предотвратит двойное снижение запасов, когда пользователи покупают билеты.

Проблема

При покупке 3 билетов замечаете, что запасы уменьшаются на 6 единиц. Это происходит из-за того, что вместо того, чтобы уменьшать запасы только на индивидуальные заказы билетов, код также продолжает уменьшать запасы оригинального заказа. Рассмотрим, как исправить эту ситуацию.

Решение

  1. Отменить снижение запасов для оригинального заказа:
    В вашем коде, когда каждый новый заказ создается из оригинального заказа, происходит снижение запасов. Это ведет к ненужному уменьшению. Нам нужно убедиться, что запас уменьшается только один раз для каждого нового заказа, который вы создаете.

  2. Добавление проверки на уменьшение запасов:
    Вам необходимо добавить логику, которая будет управлять состоянием запаса и предотвращать его дальнейшее уменьшение с оригинального заказа.

Обновленный Код

Вот пример кода с внесенными изменениями:

add_action("woocommerce_thankyou", "action_woocommerce_checkout_order_processed", 10, 1);

function action_woocommerce_checkout_order_processed($order_id) {
    $order = wc_get_order($order_id);
    $taxonomy = "product_tag";
    $items_to_remove = array();

    foreach ($order->get_items() as $item_key => $item) {
        $product = $item->get_product();
        $product_id = $item->get_product_id();
        $quantity = $item->get_quantity();

        if (has_term('ticket', $taxonomy, $product_id)) {
            $items_to_remove[] = $item->get_id(); // Mark this item for removal

            // Создаем новый заказ для каждого билета
            for ($i = 1; $i <= $quantity; $i++) {
                $new_order = wc_create_order();

                $new_order->add_product($product, 1);

                // Копируем данные о покупке
                $new_order->set_address($order->get_address('billing'), 'billing');
                $new_order->set_address($order->get_address('shipping'), 'shipping');
                $new_order->set_currency($order->get_currency());
                $new_order->set_payment_method($order->get_payment_method());
                $new_order->set_payment_method_title($order->get_payment_method_title());
                $new_order->set_date_paid(current_time('mysql'));

                // Проверяем, управляет ли продукт запасом
                if ($product->managing_stock()) {
                    // Уменьшаем запасы лишь для нового заказа
                    $new_order_stock_quantity = $product->get_stock_quantity() - 1;
                    wc_update_product_stock($product, $new_order_stock_quantity);
                }

                // Копируем покупательские данные
                $ticket_name_meta_key = "ticket_name_{$item_key}_{$i}";
                $ticket_email_meta_key = "ticket_email_{$item_key}_{$i}";

                $ticket_name = get_post_meta($order_id, $ticket_name_meta_key, true);
                $ticket_email = get_post_meta($order_id, $ticket_email_meta_key, true);

                if (!empty($ticket_name)) {
                    update_post_meta($new_order->get_id(), 'ticket_name', $ticket_name);
                }
                if (!empty($ticket_email)) {
                    update_post_meta($new_order->get_id(), 'ticket_email', $ticket_email);
                }

                $new_order->calculate_totals();
                $new_order->save();

                $new_order->add_order_note(
                    'Автоматический "билетный" заказ. Создан из оригинального заказа ID: ' . $order_id
                );
            }
        }
    }

    // Удаление элементов билетов из оригинального заказа
    foreach ($items_to_remove as $item_id) {
        $order->remove_item($item_id);
    }

    // Пересчитываем и сохраняем оригинальный заказ
    $order->calculate_totals();
    $order->save();
}

Объяснение изменений

  1. Убрали логику снижения запасов из оригинального заказа. Теперь снижение запасов происходит только для новых заказов.

  2. Добавлена проверка управления запасами. Убедитесь, что у каждого продукта включен режим управления запасами, прежде чем уменьшать количество.

Заключение

С этой модификацией ваш код будет корректно обрабатывать заказы на билеты, предотвращая двойное снижение запасов. Вы также можете дополнительно протестировать новый функционал, чтобы убедиться в его корректности. Внедряя такие изменения, вы оптимизируете систему управления запасами в вашей WooCommerce среде, что способствует более эффективному обслуживанию клиентов и более точному учету.

Оцените материал
Добавить комментарий

Капча загружается...