skip to Main Content

I have a Woocommerce store and I’m trying to add prefixes to the order number based on if the order contains a product within one of two different categories.

The two categories are Customs and Refurbished.

This code works perfectly if the order only contains a Custom or a Refurbished product, but the problem occurs when an order contains both a Custom and Refurbished product. This code will just apply the prefix of CPC- or REF- depending on whatever item is first in the order.

I want to make it so that if an order contains both of these categories, that the system defaults to adding the Custom prefix of CPC- but I can’t figure out how to do that.

Below is my code, look for the 💩 to find my failed attempt to fix this

add_filter( 'woocommerce_order_number', 'change_woocommerce_order_number' );

function change_woocommerce_order_number( $order_id ) {
      
   // 1. Get order object
   $order = wc_get_order( $order_id );
  
   // 2. Initialize $cat_in_order variable
   $cat_in_order = '';
  
   // 3. Get order items and loop through them...
   // ... if product in category, edit $cat_in_order
   $items = $order->get_items(); 
     
   foreach ( $items as $item ) {
      $product_id = $item->get_product_id();
      if ( has_term( 'refurbished', 'product_cat', $product_id )) {
         $cat_in_order = 'refurbished';
         break;
      }  elseif ( has_term( 'customs', 'product_cat', $product_id )) {
         $cat_in_order = 'customs';
         break;
//
// 💩 Here's my attempt to fix this, but it's not working 💩
//
      }  elseif ( has_term( 'customs', 'product_cat', $product_id ) && has_term( 'refurbished', 'product_cat', $product_id )) {
         $cat_in_order = 'customs';
         break;
      }
   }
  
   // 4. Add Order Prefix if in Customs Category 
   if ( $cat_in_order == 'refurbished' ) {
        $prefix = 'REF-';
        $new_order_id = $prefix . $order_id;
        return $new_order_id;
   } elseif ( $cat_in_order == 'customs' ) {
        $prefix = 'CPC-';
        $new_order_id = $prefix . $order_id;
        return $new_order_id;
   } else {
       return $order_id;
   }
    
}

3

Answers


  1. There are multiple ways to set this up, but since you’re already using if statement, I’ll take the same approach!

    The simple answer would be to add another condition to your if/elseif statements.

    So replace your first conditional check with this line:

    if (has_term('refurbished', 'product_cat', $product_id) && !has_term('customs', 'product_cat', $product_id))
    

    Replace the second condition with this one:

    elseif (has_term('customs', 'product_cat', $product_id) && !has_term('refurbished', 'product_cat', $product_id))
    

    And the last condition stays intact!

    elseif (has_term('customs', 'product_cat', $product_id) && has_term('refurbished', 'product_cat', $product_id))
    

    So the entire conditional section of your snippet would be something like this:

    foreach ($items as $item) 
    {
        $product_id = $item->get_product_id();
        if 
        (
            has_term('refurbished', 'product_cat', $product_id) 
            && 
            !has_term('customs', 'product_cat', $product_id)
        )
        {
            $cat_in_order = 'refurbished';
        } 
        elseif 
          (
            has_term('customs', 'product_cat', $product_id) 
            && 
            !has_term('refurbished', 'product_cat', $product_id)
          )
        {
            $cat_in_order = 'customs';
        } 
        elseif 
          (
            has_term('customs', 'product_cat', $product_id) 
            && 
            has_term('refurbished', 'product_cat', $product_id)
          ) 
        {
            $cat_in_order = 'customs';
        }
    }
    
    Login or Signup to reply.
  2. Starting from answer of Ruvee there is some tuning we can perform.

    The problem is implicity you set a hierarchy in your choice.

    So if Custom attribute is set this has precedence.

    in this case we can simply the code in this way.

    foreach ($items as $item) {
    $product_id = $item->get_product_id();
    if (  has_term('customs', 'product_cat', $product_id) ){
        $cat_in_order = 'customs';
    
    } elseif ( has_term('refurbished', 'product_cat', $product_id) )  {
        $cat_in_order = 'refurbished';
    }  else {
        
        // Manage the exception!
    }
    

    }

    So if Custom is true elseif is not processed and we don’t need to set other conditions.

    However, pay attantion on the break usage, is not needed in if / elseif statement, and it’s wrong.

    Login or Signup to reply.
  3. foreach ( $items as $item ) {
          $product_id = $item->get_product_id();
          if ( has_term( 'customs', 'product_cat', $product_id ) && has_term( 'refurbished', 'product_cat', $product_id )) {
             $cat_in_order = 'customs';
             
          }
          elseif ( has_term( 'refurbished', 'product_cat', $product_id )) {
             $cat_in_order = 'refurbished';
             
          }  elseif ( has_term( 'customs', 'product_cat', $product_id )) {
             $cat_in_order = 'customs';
             ;
    
          }  
       }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search