Сделать продукт для покупки только один раз или нет, если какой-либо элемент из определенной категории продукта был куплен в Woocommerce.

В woocommerce я использую только простые продукты, и у меня есть специальный продукт «бесплатный пробный пакет» из категории продуктов «A», который я готов:

  1. позволить клиенту приобрести этот «бесплатный пробный пакет» только один раз
  2. если клиент сначала купит другие продукты из той же категории продуктов "A", он больше не сможет приобрести этот "бесплатный пробный пакет"

Это означает, что клиент сможет получить «бесплатный пробный пакет» только в том случае, если это первая покупка продукта категории «А».

Мой код, похоже, не работает должным образом, и он выполняет только первую точку.

Другая проблема заключается в том, что если заказ пользователя завершается, в следующий раз, когда пользователь откроет корзину, появится странное сообщение: «вы больше не можете выбрать этот продукт, вы уже купили этот пакет». Это похоже на проблему с кешем Woocommerce или что-то…

Вот мой код:

function sv_disable_repeat_purchase( $purchasable, $product ) {
    $non_purchasable = 190;

    $product_id = $product->is_type( 'variation' ) ? $product->variation_id : $product->id;

    if ( $product_id != $non_purchasable ) {
        $purchasable = true;
    }

    if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $product_id ) ) {
        $purchasable = false;
    }

    if ( $purchasable && $product->is_type( 'variation' ) ) {
        $purchasable = $product->parent->is_purchasable();
    }

    return $purchasable;
}
add_filter( 'woocommerce_variation_is_purchasable', 'sv_disable_repeat_purchase', 10, 2 );
add_filter( 'woocommerce_is_purchasable', 'sv_disable_repeat_purchase', 10, 2 );

Любая помощь приветствуется.


person iKamy    schedule 26.03.2019    source источник


Ответы (2)


Обновление 2

На основе "Проверьте, приобрел ли клиент определенные продукты в WooCommerce ", код ответа, следующее предотвратит покупки из продукта« пробного пакета », если он уже был приобретен один раз, или если какой-либо продукт для определенная категория продукта «А» уже куплена.

Ваш фактический код устарел после Woocommerce 3, и есть некоторые ошибки ...

Я использую настраиваемую условную функцию, вдохновленную wc_customer_bought_product() исходным кодом < / a>, чтобы проверить, может ли покупатель приобрести «бесплатную пробную версию». Эта функция также будет проверять идентификатор продукта или категорию продукта:

function has_bought_items( $user_id = 0, $product_ids = 0, $categories_slugs = '' ) {
    global $wpdb;
    $customer_id = $user_id == 0 || $user_id == '' ? get_current_user_id() : $user_id;
    $statuses    = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    if ( is_array( $product_ids ) ) {
        $product_ids = implode(',', $product_ids);
    }

    if ( $product_ids !=  ( 0 || '' ) ) {
        $query_in = "IN ($product_ids)";
    }
    else {
        $categories = is_array( $categories_slugs ) ? implode("','", $categories_slugs) : $categories_slugs;

        $query_in = "IN (
        SELECT DISTINCT products.ID  FROM {$wpdb->prefix}posts AS products
        INNER JOIN {$wpdb->prefix}term_relationships as term_rel
            ON products.ID = term_rel.object_id
        INNER JOIN {$wpdb->prefix}term_taxonomy as term_tax
            ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
        INNER JOIN {$wpdb->prefix}terms as terms
            ON term_tax.term_taxonomy_id = terms.term_id
        WHERE products.post_status = 'publish'
        AND term_tax.taxonomy = 'product_cat'
        AND terms.slug IN ('$categories')
        )";
    }

    // Count the number of products
    $product_count_query = $wpdb->get_var( "
        SELECT DISTINCT COUNT(orders.ID)
        FROM {$wpdb->prefix}posts AS orders
        INNER JOIN {$wpdb->prefix}postmeta AS order_meta
            ON orders.ID = order_meta.post_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items
            ON orders.ID = order_items.order_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
            ON order_items.order_item_id = order_itemmeta.order_item_id
        WHERE orders.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
        AND order_meta.meta_key = '_customer_user'
        AND order_meta.meta_value = $customer_id
        AND order_itemmeta.meta_key IN ( '_product_id', '_variation_id' )
        AND order_itemmeta.meta_value $query_in
    " );

    // Return a boolean value if count is higher than 0
    return $product_count_query > 0 ? true : false;
}

Ваш обновленный код с использованием пользовательской условной функции выше:

// add_filter( 'woocommerce_variation_is_purchasable', 'trial_package_purchasable_once', 10, 2 );
add_filter( 'woocommerce_is_purchasable', 'trial_package_purchasable_once', 10, 2 );
function trial_package_purchasable_once( $purchasable, $product ) {
    // HERE set the free trial product Id to be purchased only once (can be an array of Ids too)
    $free_trial_id = 50;

    // HERE set the specific product category SLUG (could be an array of slugs too)
    $categories = array('lettering'); // Only slug terms

        if ( $product->get_id() == $free_trial_id ) {
            // Check if any item of the specific product category has already been purchased once
            if ( has_bought_items( get_current_user_id(), '', $categories ) ) {
                return false;
            }
            // Check if the free trial product has already been purchased once
            elseif ( has_bought_items( get_current_user_id(), $free_trial_id ) ) {
                return false;
            }
        }
    }

    return $purchasable;
}

Код находится в файле function.php вашей активной дочерней темы (или активной темы). Проверено и работает.


Для обработки категорий продуктов Term ID вместо Term Slugs используйте вместо этого следующую условную функцию:

// For Product category(ies) Id(s)
function has_bought_items( $user_id = 0, $product_ids = 0, $categories_ids = '' ) {
    global $wpdb;
    $customer_id = $user_id == 0 || $user_id == '' ? get_current_user_id() : $user_id;
    $statuses    = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    if ( is_array( $product_ids ) ) {
        $product_ids = implode(',', $product_ids);
    }

    if ( $product_ids !=  ( 0 || '' ) ) {
        $query_in = "IN ($product_ids)";
    }
    else {
        $categories = is_array( $categories_ids ) ? implode(',', $categories_ids) : $categories_ids;

        $query_in = "IN (
        SELECT DISTINCT products.ID  FROM {$wpdb->prefix}posts AS products
        INNER JOIN {$wpdb->prefix}term_relationships as term_rel
            ON products.ID = term_rel.object_id
        INNER JOIN {$wpdb->prefix}term_taxonomy as term_tax
            ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
        INNER JOIN {$wpdb->prefix}terms as terms
            ON term_tax.term_taxonomy_id = terms.term_id
        WHERE products.post_status = 'publish'
        AND term_tax.taxonomy = 'product_cat'
        AND terms.term_id IN ($categories)
        )";
    }

    // Count the number of products
    $product_count_query = $wpdb->get_var( "
        SELECT DISTINCT COUNT(orders.ID)
        FROM {$wpdb->prefix}posts AS orders
        INNER JOIN {$wpdb->prefix}postmeta AS order_meta
            ON orders.ID = order_meta.post_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items
            ON orders.ID = order_items.order_id
        INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta
            ON order_items.order_item_id = order_itemmeta.order_item_id
        WHERE orders.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' )
        AND order_meta.meta_key = '_customer_user'
        AND order_meta.meta_value = $customer_id
        AND order_itemmeta.meta_key IN ( '_product_id', '_variation_id' )
        AND order_itemmeta.meta_value $query_in
    " );

    // Return a boolean value if count is higher than 0
    return $product_count_query > 0 ? true : false;
}

Это лучшая альтернатива для иностранных языков со специальными символами.

person LoicTheAztec    schedule 26.03.2019
comment
это не работает, я сначала купил пакет за 20 долларов, затем я попытался купить бесплатный пакет, и я это сделал! - person iKamy; 26.03.2019
comment
на самом деле он делает следующее: он позволяет вам покупать все, что угодно, как только вы покупаете бесплатный пакет, вы не можете покупать ничего другого! я хочу вот это, только если вы заказываете бесплатный пакет в качестве начальной покупки, вы можете купить его, но если вы это сделаете, вы не сможете купить его снова, также если вы купите что-либо, кроме бесплатного пакета, вы не сможете снова выбрать бесплатный пакет - person iKamy; 26.03.2019
comment
Когда я покупаю бесплатный пакет, он не только не позволяет мне покупать товары из той же категории, но и не позволяет мне покупать снова! кнопка добавления в корзину полностью исчезает на всех вещах! - person iKamy; 26.03.2019
comment
хммм, кажется, что код требует какой-то отдачи в каждом случае, если - person iKamy; 26.03.2019
comment
он работает отлично, единственная проблема в том, что мой ярлык категории не английский, поэтому он как-то его не обнаруживает ... - person iKamy; 27.03.2019
comment
В конце я добавил новую заменяющую условную функцию, которая проверяет идентификаторы терминов категорий, которые должны работать для всех иностранных языков со специальными символами. - person LoicTheAztec; 27.03.2019
comment
Привет, чувак, мы недавно изменили заголовок некоторых из наших категорий для целей SEO. Есть ли способ, которым эта функция has_bought_items ($ user_id = 0, $ product_ids = 0, $ category_slugs = '') изменится таким образом, чтобы она работала с НАЗВАНИЕМ КАТЕГОРИИ, например has_term () функция ?? потому что наши ярлыки не на английском языке, и это работает только с английскими ярлыками - person iKamy; 23.05.2019
comment
В первой функции замените AND terms.slug IN ($categories) на AND terms.name IN ($categories)… Или в последней функции AND terms.term_id IN ($categories) на AND terms.name IN ($categories) - person LoicTheAztec; 23.05.2019

person    schedule
comment
куда идет идентификатор продукта ?! - person iKamy; 26.03.2019