4
votes

I've used the awesome snippet of https://jeroensormani.com/custom-stock-quantity-reduction/ to add an additional setting to variations that reduces the main inventory stock by the set amount in the variation.

The problem I'm facing now is that it doesn't check if those variations are out of stock (for example main inventory is 10, and the bundle setting is set to 12 bottles).

The code I've used to add the the multiplier for the total stock reduction is:

// For implementation instructions see: https://aceplugins.com/how-to-add-a-code-snippet/

/**
 * Simple product setting.
 */
function ace_add_stock_inventory_multiplier_setting() {

    ?><div class='options_group'><?php

        woocommerce_wp_text_input( array(
            'id'                => '_stock_multiplier',
            'label'             => __( 'Inventory reduction per quantity sold', 'woocommerce' ),
            'desc_tip'          => 'true',
            'description'       => __( 'Enter the quantity multiplier used for reducing stock levels when purchased.', 'woocommerce' ),
            'type'              => 'number',
            'custom_attributes' => array(
                'min'   => '1',
                'step'  => '1',
            ),
        ) );

    ?></div><?php

}
add_action( 'woocommerce_product_options_inventory_product_data', 'ace_add_stock_inventory_multiplier_setting' );

/**
 * Add variable setting.
 *
 * @param $loop
 * @param $variation_data
 * @param $variation
 */
function ace_add_variation_stock_inventory_multiplier_setting( $loop, $variation_data, $variation ) {

    $variation = wc_get_product( $variation );
    woocommerce_wp_text_input( array(
        'id'                => "stock_multiplier{$loop}",
        'name'              => "stock_multiplier[{$loop}]",
        'value'             => $variation->get_meta( '_stock_multiplier' ),
        'label'             => __( 'Inventory reduction per quantity sold', 'woocommerce' ),
        'desc_tip'          => 'true',
        'description'       => __( 'Enter the quantity multiplier used for reducing stock levels when purchased.', 'woocommerce' ),
        'type'              => 'number',
        'custom_attributes' => array(
            'min'   => '1',
            'step'  => '1',
        ),
    ) );

}
add_action( 'woocommerce_variation_options_pricing', 'ace_add_variation_stock_inventory_multiplier_setting', 50, 3 );

/**
 * Save the custom fields.
 *
 * @param WC_Product $product
 */
function ace_save_custom_stock_reduction_setting( $product ) {

    if ( ! empty( $_POST['_stock_multiplier'] ) ) {
        $product->update_meta_data( '_stock_multiplier', absint( $_POST['_stock_multiplier'] ) );
    }
}
add_action( 'woocommerce_admin_process_product_object', 'ace_save_custom_stock_reduction_setting'  );

/**
 * Save custom variable fields.
 *
 * @param int $variation_id
 * @param $i
 */
function ace_save_variable_custom_stock_reduction_setting( $variation_id, $i ) {
    $variation = wc_get_product( $variation_id );
    if ( ! empty( $_POST['stock_multiplier'] ) && ! empty( $_POST['stock_multiplier'][ $i ] ) ) {
        $variation->update_meta_data( '_stock_multiplier', absint( $_POST['stock_multiplier'][ $i ] ) );
        $variation->save();
    }
}
add_action( 'woocommerce_save_product_variation', 'ace_save_variable_custom_stock_reduction_setting', 10, 2 );

The code that reduces the quantity then is the following:

// For implementation instructions see: https://aceplugins.com/how-to-add-a-code-snippet/

/**
 * Reduce with custom stock quantity based on the settings.
 *
 * @param $quantity
 * @param $order
 * @param $item
 * @return mixed
 */
function ace_custom_stock_reduction( $quantity, $order, $item ) {

    /** @var WC_Order_Item_Product $product */
    $multiplier = $item->get_product()->get_meta( '_stock_multiplier' );

    if ( empty( $multiplier ) && $item->get_product()->is_type( 'variation' ) ) {
        $product = wc_get_product( $item->get_product()->get_parent_id() );
        $multiplier = $product->get_meta( '_stock_multiplier' );
    }

    if ( ! empty( $multiplier ) ) {
        $quantity = $multiplier * $quantity;
    }

    return $quantity;
}
add_filter( 'woocommerce_order_item_quantity', 'ace_custom_stock_reduction', 10, 3 );

What I've tried to do is add an "If" Snippet to check the quantity

add_filter( ‘woocommerce_variation_is_active’, ‘my_jazzy_function’, 10, 2 );

function my_jazzy_function( $active, $variation ) {
    // Get Multiplier
    $multiplier = $item->get_product()->get_meta( '_stock_multiplier' );

    $var_stock_count = $variation->get_stock_quantity();

    // if there are 5 or less, disable the variant, could always just set to 0.
    if( $var_stock_count <= $multiplier ) {
        return false;
    }
    else {
        return true;
    }
}

But this doesn't work, I think it only checks the variations quantity (if you set the variation to its own quantity instead of global).

How can I compare the total stock count to the newly added setting $multiplier?

Any help would be great.

2

2 Answers

5
votes
  • Compare the total stock quantity to the newly added setting $multiplier
  • Comment with explanation added to the code
function filter_woocommerce_variation_is_active( $active, $variation ) {    
    // Get multiplier
    $multiplier = get_post_meta( $variation->get_variation_id(), '_stock_multiplier', true );   
    
    // NOT empty
    if ( ! empty( $multiplier ) ) {
        // Get stock quantity
        $var_stock_count = $variation->get_stock_quantity();
        
        // Stock quantity < multiplier
        if( $var_stock_count < $multiplier ) {
            $active = false;
        }
    }
    
    return $active;
}
add_filter( 'woocommerce_variation_is_active', 'filter_woocommerce_variation_is_active', 10, 2 );
1
votes

It doesn't work because:

  • $item variable is not defined in your code.
  • your custom field is defined in the parent variable product.

So you need to replace:

$multiplier = $item->get_product()->get_meta( '_stock_multiplier' );

by the folling (getting the data from the parent variable product):

$multiplier = get_post_meta( $variation->get_parent_id(), '_stock_multiplier', true );

So in your code:

add_filter( 'woocommerce_variation_is_active', 'my_jazzy_function', 10, 2 ); 
function my_jazzy_function( $active, $variation ) {    
    // Get multiplier
    if( $multiplier = get_post_meta( $variation->get_parent_id(), '_stock_multiplier', true ) {
        // Get stock quantity
        $var_stock_count = (int) $variation->get_stock_quantity();
    
        // if there are 5 or less, disable the variant, could always just set to 0
        return $var_stock_count <= $multiplier ? false : $active;
    }
    return  $active;
}

It should work now.