Home > Back-end >  Minimum order amount depending on postcode and shipping method on WooCommerce
Minimum order amount depending on postcode and shipping method on WooCommerce

Time:02-13

How can I set a minimum order amount only for Delivery/Shipments (but not for local pickup) and depending on specific post codes?

Use Case: A Restaurant delivers in the local village without minimum amount. But the neighbor villages should have an order amount. Pickup is always without any minimum amount.

Based on Minimum order amount except for specific shipping method in WooCommerce answer code, this is my attempt:

add_action( 'woocommerce_check_cart_items', 'wc_minimum_required_order_amount' );
function wc_minimum_required_order_amount() {

// HERE Your settings
$minimum_amount     = 50; // The minimum cart total amount
$shipping_method_id = 'local_pickup'; // The targeted shipping method Id (exception)
$postcodes = array('82065', '82057', '82067'); // Define your targeted postcodes in the array
$postcode  = '82069'; // Initializing

// Get some variables
$cart_total     = (float) WC()->cart->total; // Total cart amount
$chosen_methods = (array) WC()->session->get( 'chosen_shipping_methods' ); // Chosen shipping method rate Ids (array)

// Only when a shipping method has been chosen
if ( ! empty($chosen_methods) ) {
    $chosen_method  = explode(':', reset($chosen_methods)); // Get the chosen shipping method Id (array)
    $chosen_method_id = reset($chosen_method); // Get the chosen shipping method Id
}

// If "Local pickup" shipping method is chosen, exit (no minimun is required)
if ( isset($chosen_method_id) && $chosen_method_id === $shipping_method_id ) {
    return; // exit
}

if ( isset($_POST['shipping_postcode']) && ! empty($_POST['shipping_postcode']) ) {
    $postcode = $_POST['shipping_postcode'];
    if ( empty($postcode) && isset($_POST['billing_postcode']) && ! empty($_POST['billing_postcode']) ) {
        $postcode = $_POST['billing_postcode'];
    }
} elseif ( $postcode = WC()->customer->get_shipping_postcode() ) {
    if ( empty($postcode) ) {
        $postcode = WC()->customer->get_billing_postcode();
    }
}

// Add an error notice is cart total is less than the minimum required
if ( $cart_total < $minimum_amount && ! empty($postcode) && in_array( $postcode, $postcodes ) ) {
    wc_add_notice( sprintf(
        __("The minimum required order amount is %s (your current order amount is %s).", "woocommerce"), // Text message
        wc_price( $minimum_amount ),
        wc_price( $cart_total )
    ), 'error' );
}
}

CodePudding user response:

You are close with your solution, what is missing, however, is the use of in_array(), with which you can check the postcode

So you get:

function action_woocommerce_check_cart_items() {
    // HERE Your settings
    $minimum_amount = 50; // The minimum cart total amount
    $shipping_method_id = 'local_pickup'; // The targeted shipping method Id (exception)
    $postcodes = array( 82065, 82057, 82067, 9800 ); // Define your targeted postcodes in the array

    // Get some variables
    $cart_total     = (float) WC()->cart->total; // Total cart amount
    $chosen_methods = (array) WC()->session->get( 'chosen_shipping_methods' ); // Chosen shipping method rate Ids (array)
    
    // Initialize
    $postcode = '';

    // Only when a shipping method has been chosen
    if ( ! empty($chosen_methods) ) {
        $chosen_method  = explode( ':', reset( $chosen_methods ) ); // Get the chosen shipping method Id (array)
        $chosen_method_id = reset( $chosen_method ); // Get the chosen shipping method Id
    }

    // If "Local pickup" shipping method is chosen, exit (no minimun is required)
    if ( isset($chosen_method_id) && $chosen_method_id === $shipping_method_id ) {
        return; // exit
    }
    
    // Get shipping postode
    $postcode = WC()->customer->get_shipping_postcode();
    
    // When empty
    if ( empty ( $postcode ) ) {
        if ( isset( $_POST['shipping_postcode'] ) ) {
            $postcode = $_POST['shipping_postcode'];
        } else {
            if ( isset( $_POST['billing_postcode'] ) ) {
                $postcode = $_POST['billing_postcode'];
            } else {
                $postcode = WC()->customer->get_billing_postcode();
            }
        }
    }
    
    // Still empty, exit
    if ( empty ( $postcode ) ) return;

    // Add an error notice is cart total is less than the minimum required and postcode occurs in the array
    if ( $cart_total < $minimum_amount && in_array( $postcode, $postcodes ) ) {
        // Your error message
        wc_add_notice( sprintf(
            __( 'The minimum required order amount is %s (your current order amount is %s).', 'woocommerce' ), // Text message
            wc_price( $minimum_amount ),
            wc_price( $cart_total )
        ), 'error' );
        
        // Optional: remove proceed to checkout button
        remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
    }
}
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );
  • Related