'WooCommerce how to perform conditional checks for custom categories

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;
   }
    
}


Solution 1:[1]

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.

Solution 2:[2]

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';
         ;

      }  
   }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Domenico Lorusso
Solution 2 Maulik patel