Create a shipping method for free items on woocommerce - php

I'm looking to create two separate shipping sets based on items that are in the cart.
I want free shipping on shipping class "holiday packages" and free shipping on product category "coffee" when there are more than 2 bags of coffee in the cart. Then I want the rest of the items to be put into a different shipping "container".
I currently can get it all to work when there are two different coffees in there (thus is up ticking the coffee count) but when there are two of one type of coffee it doesn't separate it.
/* Puts items with "holiday-package" shipping class into a different shipping package. */
function hdm_woocommerce_cart_shipping_packages( $packages ) {
// Reset the packages
$packages = array();
// Free items
$freeshipping_items = array();
$regular_items = array();
$coffee_count = 0;
//get product category and count up each item in that category
foreach ( WC()->cart->get_cart() as $item ) {
$quantity = $item['quantity'];
if ($item['data']->get_shipping_class() == 'coffee') {
$coffee_count++; }
elseif ($quantity >= 2 && $item['data']->get_shipping_class() == 'coffee') {
$coffee_count = 2;
}
}
// Sort free from regular.
foreach( WC()->cart->get_cart() as $item ) {
if( $item['data']->needs_shipping() ) {
if( $item['data']->get_shipping_class() == 'holiday-packages' ) {
$freeshipping_items[] = $item;
}
elseif ($item['data']->get_shipping_class() == 'coffee' && $coffee_count >= 2){
$freeshipping_items[] = $item;
}
else {
$regular_items[] = $item;
}
}
}
// Put inside packages:
if( $regular_items ) {
$packages[] = array(
'ship_via' => array(),
'contents' => $regular_items,
'contents_cost' => array_sum(wp_list_pluck($regular_items, 'line_total')),
'applied_coupons' => WC()->cart->applied_coupons,
'destination' => array(
'country' => WC()->customer->get_shipping_country(),
'state' => WC()->customer->get_shipping_state(),
'postcode' => WC()->customer->get_shipping_postcode(),
'city' => WC()->customer->get_shipping_city(),
'address' => WC()->customer->get_shipping_address(),
'address_2' => WC()->customer->get_shipping_address_2()
)
);
}
if( $freeshipping_items ) {
$packages[] = array(
'ship_via' => array( 'flat_rate' ),
'contents' => $freeshipping_items,
'contents_cost' => array_sum(wp_list_pluck($freeshipping_items, 'line_total')),
'applied_coupons' => WC()->cart->applied_coupons,
'destination' => array(
'country' => WC()->customer->get_shipping_country(),
'state' => WC()->customer->get_shipping_state(),
'postcode' => WC()->customer->get_shipping_postcode(),
'city' => WC()->customer->get_shipping_city(),
'address' => WC()->customer->get_shipping_address(),
'address_2' => WC()->customer->get_shipping_address_2()
)
);
}
return $packages;
}
add_filter('woocommerce_cart_shipping_packages', 'hdm_woocommerce_cart_shipping_packages');

UPDATE: I was about to fix it by changing
elseif ($quantity >= 2 && $item['data']->get_shipping_class() == 'coffee') {
$coffee_count = 2;
}
to
if ($quantity >= 2 && $item['data']->get_shipping_class() == 'coffee') {
$coffee_count = 2;
}
I don't think it will come up with the correct quantities, but it works for my needs. If anyone has any advice on how to better write this it would be much appreciated.

Related

Woocommerce multi Vendor Split Shipping without plugin or custom plugin

I Want To Calculate Shipping Rates and Display WooCommerce Shipping Methods on the Cart & Checkout Page (Either Calculate & Display WooCommerce Shipping Rates Separately for Each Vendor, Or, Add WooCommerce Shipping Cost for Each Vendor, and Display Final Shipping Cost on Cart Page).
There are many plugins available but I want to do it without a plugin(functions.php) or create my own plugin.
$packages[] = array(
'ship_via' => $shipping_method_ids ?: array('flat_rate', 'local_pickup', 'free_shipping'),
'name' => $shipping_class_name,
'contents' => $new_package,
'contents_cost' => array_sum(wp_list_pluck($new_package, 'line_total')),
'applied_coupons' => WC()->cart->applied_coupons,
'destination' => array(
'country' => WC()->customer->get_shipping_country(),
'state' => WC()->customer->get_shipping_state(),
'postcode' => WC()->customer->get_shipping_postcode(),
'city' => WC()->customer->get_shipping_city(),
'address' => WC()->customer->get_shipping_address(),
'address_2' => WC()->customer->get_shipping_address_2()
)
);
I have done create Separate package shipping wise. but I want to create the same (slipt shipping) according to Vendor Wise.
In short
Vendor A -> Shipping(1,2,3..)
Vendor B -> Shipping(1,2,3..)
Vendor C -> Shipping(1,2,3..)
.
.
.
etc...
See screenshoot for more Info.
Finally, we got an answer to this question.
First of all, we should get vendors associated with cart products.
// Get Vendor ID from Prduct ID - Method 1 (Compatible with woocommerce-product-vendors plugin)
function get_product_vendors_1( $product_id = null ) {
if ( null === $product_id ) {
return null;
}
$term = wp_get_object_terms( $product_id, WC_PRODUCT_VENDORS_TAXONOMY, array( 'fields' => 'ids' ) );
if ( is_wp_error( $term ) || empty( $term ) ) {
return null;
}
return $term[0];
}
// Get Vendor ID from Prduct ID - Method 2
function get_user_roles_by_user_id( $user_id = null, $role = array('vendors') ) {
$user = get_userdata( $user_id );
$user_roles = array_intersect($user->roles,$role);
if (isset($user_roles) && !empty($user_roles)) {
return $user_id;
}
return false;
}
function get_product_vendors_2($product_id = null){
// Vendors roles - you can change accordingly
$role = array(
'wc_product_vendors_pending_vendor',
'wc_product_vendors_manager_vendor',
'wc_product_vendors_admin_vendor'
);
$user_id = get_post_field( 'post_author', $product_id );
if(get_user_roles_by_user_id( $user_id, $role)){
return $user_id;
}
return false;
}
// Now you can use one of them
get_product_vendors_1($product_id)
or
get_product_vendors_2($product_id)
Now Multi-Vendor Split Shipping full Source code.
add_filter('woocommerce_cart_shipping_packages', 'woo_multi_vendors_shipping_packages');
function woo_multi_vendors_shipping_packages($packages)
{
$i = 1;
$packages = $vendor_items_map = array();
foreach (WC()->cart->get_cart() as $cart_item)
{
if ($cart_item['data']->needs_shipping())
{
$product_id = $cart_item['product_id'];
// Get vendors for each product.
// $vendor = get_product_vendors_2( $product_id);
$vendor = get_product_vendors_1( $product_id);
$vendor_id = isset($vendor) ? (int)$vendor : 0;
$vendor_items_map[$vendor_id][] = $cart_item;
}
}
foreach($vendor_items_map as $vendor_id => $vendor_items) {
if(!empty($vendor_items)){
$packages_name = null;
if($vendor_id){
$user_displayname = get_term($vendor_id)->name ?: '';
if($user_displayname){
$packages_name = '<span class="ship-name">Shipping #'.$i.'</span><span class="vendor-name">'.$user_displayname.'</span>';
}
}
$packages[] = array(
//'ship_via' => array( 'flat_rate' ),
'name' => $packages_name ?: null,
'contents' => $vendor_items,
'contents_cost' => array_sum( wp_list_pluck( $vendor_items, 'line_total' ) ),
'applied_coupons' => WC()->cart->applied_coupons,
'destination' => array(
'country' => WC()->customer->get_shipping_country(),
'state' => WC()->customer->get_shipping_state(),
'postcode' => WC()->customer->get_shipping_postcode(),
'city' => WC()->customer->get_shipping_city(),
'address' => WC()->customer->get_shipping_address(),
'address_2' => WC()->customer->get_shipping_address_2()
)
);
}
$i++;
}
return $packages;
}

Save Woocommerce cart item custom data as order item meta data displaying it on orders and emails

Regarding Woocommerce. I have custom data that I am adding to the cart. In the functions.php file, I have the following function.
// Display cart item custom data in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_cart_item_custom_on_cart_and_checkout', 10, 2 );
function display_cart_item_custom_on_cart_and_checkout( $cart_item_data, $cart_item ){
if( isset($cart_item['custom_data']['label0']) && isset($cart_item['custom_data']['value0']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label0'],
'value' => $cart_item['custom_data']['value0'],
);
}
if( isset($cart_item['custom_data']['label']) && isset($cart_item['custom_data']['value']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label'],
'value' => $cart_item['custom_data']['value'],
);
}
if( isset($cart_item['custom_data']['label2']) && isset($cart_item['custom_data']['value2']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label2'],
'value' => $cart_item['custom_data']['value2'],
);
}
if( isset($cart_item['custom_data']['label3']) && isset($cart_item['custom_data']['value3']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label3'],
'value' => $cart_item['custom_data']['value3'],
);
}
if( isset($cart_item['custom_data']['label4']) && isset($cart_item['custom_data']['value4']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label4'],
'value' => $cart_item['custom_data']['value4'],
);
}
if( isset($cart_item['custom_data']['label5']) && isset($cart_item['custom_data']['value5']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label5'],
'value' => $cart_item['custom_data']['value5'],
);
}
if( isset($cart_item['custom_data']['label6']) && isset($cart_item['custom_data']['value6']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label6'],
'value' => $cart_item['custom_data']['value6'],
);
}
if( isset($cart_item['custom_data']['label7']) && isset($cart_item['custom_data']['value7']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label7'],
'value' => $cart_item['custom_data']['value7'],
);
}
if( isset($cart_item['custom_data']['label8']) && isset($cart_item['custom_data']['value8']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label8'],
'value' => $cart_item['custom_data']['value8'],
);
}
if( isset($cart_item['custom_data']['label9']) && isset($cart_item['custom_data']['value9']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label9'],
'value' => $cart_item['custom_data']['value9'],
);
}
if( isset($cart_item['custom_data']['label10']) && isset($cart_item['custom_data']['value10']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label10'],
'value' => $cart_item['custom_data']['value10'],
);
}
return $cart_item_data;
}
This works and the custom data is shown in the cart. However, the custom data does not show on the order and order email. I have seen, on Stackoverflow several answers that provide solutions to this problem but I cannot make them work for my situation. The solutions that I reference are.
Save and display order item custom meta data in Woocommerce
Display and save added custom cart item data on Woocommerce Cart, Checkout and Orders
Can anybody kindly show me what "my" function should be?
Thank you.
First you can optimize and compact your function this way:
// Display cart item custom data in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_cart_item_custom_on_cart_and_checkout', 10, 2 );
function display_cart_item_custom_on_cart_and_checkout( $cart_item_data, $cart_item ){
$keys = array('0','','2','3','4','5','6','7','8','9','10'); // Fields numbers part keys array
// Loop through Fields numbers part keys array
foreach( $keys as $key ) {
if( isset($cart_item['custom_data']['label'.$key]) && isset($cart_item['custom_data']['value'.$key]) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label'.$key],
'value' => $cart_item['custom_data']['value'.$key],
);
}
}
return $cart_item_data;
}
Then to save all your custom cart item data as custom order item meta data and display it everywhere on orders and emails, use the following:
// Save cart item custom data as order item meta data and display it everywhere in Orders and email notifications
add_action('woocommerce_checkout_create_order_line_item', 'save_as_custom_order_item_meta_data', 10, 4 );
function save_as_custom_order_item_meta_data( $item, $cart_item_key, $values, $order ) {
$keys = array('0','','2','3','4','5','6','7','8','9','10'); // Fields numbers part keys array()
// Loop through Fields numbers part keys array
foreach( $keys as $key ) {
if( isset( $values['custom_data']['label'.$key] ) && isset( $values['custom_data']['value'.$key] ) ) {
$item->update_meta_data( $values['custom_data']['label'.$key], $values['custom_data']['value'.$key] );
}
}
}
Code goes in functions.php file of the active child theme (or active theme). It should works.

Show sub Areas dropdown based on chosen city in WooCommerce checkout

I am creating a WooCommerce plugin and I want to display dynamically Sub Areas according to chosen customer city in checkout page.
Here is my code attempt:
add_filter( 'woocommerce_checkout_fields', 'dvs_city_list' );
function dvs_city_list( $fields ) {
$fields["billing"]["billing_city"]["type"] = 'select';
$fields["billing"]["billing_city"]["input_class"] = array(
'state_select' => 'state_select'
);
$fields["billing"]["billing_city"]["options"] = array(
'Lahore' => 'Lahore',
'Karachi' => 'Karachi'
),
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'dvs_area_list' );
function dvs_area_list( $fields ) {
$fields['billing']['billing_area']['label'] = 'Area';
$fields['billing']['billing_area']['required'] = 'True';
$fields["billing"]["billing_area"]["type"] = 'select';
$fields["billing"]["billing_area"]["class"][0] = 'form-row-last';
$fields['billing']['billing_area']['priority'] = 50;
$fields["billing"]["billing_area"]["input_class"] = array(
'state_select' => 'state_select'
);
$city = $_REQUEST['billing_city'];
if ($city == 'Lahore') {
$fields["billing"]["billing_area"]["options"] = array(
'Naval Town' => 'Naval Town',
'Bahria Town' => 'Bahria Town',
'Faisal Town' => 'Faisal Town'
);
}
else ($city == 'Karachi') {
$fields["billing"]["billing_area"]["options"] = array(
'Walton Road' => 'Walton Road',
'Zest Road' => 'Zest Road'
);
}
return $fields;
}
Here is the screenshot
But I am getting this error
Notice:
Undefined index: billing_city in …wp-content/plugins/custom-plugin/index.php on line 35
How to fixed this error? What I am doing wrong?
To synch a custom checkout select field from another select field, it requires to use jQuery.
Also you can merge both functions as they use the same hook.
Below in the first function, we keep your cities / areas settings that we can call everywhere. The last function enable dynamic options changes on the "Billing areas" dropdown depending on the chosen city:
function cities_areas_settings() {
$text_domain = 'woocommerce';
return array(
__('Lahore', $text_domain) => array(
__('Naval Town', $text_domain),
__('Bahria Town', $text_domain),
__('Faisal Town', $text_domain),
),
__('Karachi', $text_domain) => array(
__('Walton Road', $text_domain),
__('Zest Road', $text_domain),
)
);
}
add_filter( 'woocommerce_checkout_fields', 'custom_checkout_fields' );
function custom_checkout_fields( $fields ) {
// Initializing
$text_domain = 'woocommerce';
$option_cities = array();
$lahore_areas = array( '' => __('Choose your area', $text_domain) );
// Load settings and prepare options arrays
foreach( cities_areas_settings() as $city => $areas ) {
$option_cities[$city] = $city;
if( $city === 'Lahore' ) {
foreach( $areas as $area ) {
$lahore_areas[$area] = $area;
}
}
}
// 1. Billing City field
$fields['billing']['billing_city']['type'] = 'select';
$fields['billing']['billing_city']['class'] = array('form-row-first');
$fields['billing']['billing_city']['input_class'] = array('state_select');
$fields['billing']['billing_city']['options'] = $option_cities;
// 2. Billing Area Field
$fields['billing']['billing_area'] = array(
'type' => 'select',
'label' => __('Area', $text_domain),
'class' => array('form-row-last'),
'input_class' => array('state_select'),
'options' => $lahore_areas,
'required' => true,
'default' => '',
'priority' => 50,
);
return $fields;
}
add_action('wp_footer', 'custom_checkout_js_script');
function custom_checkout_js_script() {
if( is_checkout() && ! is_wc_endpoint_url() ) :
// Initializing
$text_domain = 'woocommerce';
$karachi_areas = array( '' => __('Choose your area', $text_domain) );
$settings = cities_areas_settings(); // Load settings
// Prepare 'Karachi' options dropdown
foreach( cities_areas_settings()['Karachi'] as $area ) {
$karachi_areas[$area] = $area;
}
?>
<script language="javascript">
jQuery( function($){
var a = 'select[name="billing_city"]',
b = 'select[name="billing_area"]',
o = <?php echo json_encode($karachi_areas); ?>,
s = $(b).html();
// Utility function to fill dynamically the select field options
function dynamicSelectOptions( opt ){
var options = '';
$.each( opt, function( key, value ){
options += '<option value="'+key+'">'+value+'</option>';
});
$(b).html(options);
}
// On Start (once DOM is loaded)
if ( $(a).val() === 'Karachi' ) {
dynamicSelectOptions( o );
}
console.log($(a).val());
// On billing city change live event
$('form.woocommerce-checkout').on('change', a, function() {
console.log($(this).val());
if ( $(this).val() === 'Karachi' ) {
dynamicSelectOptions( o );
} else {
$(b).html(s);
}
});
});
</script>
<?php
endif;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related: Dynamic synched custom checkout select fields in WooCommerce

Fees based from WooCommerce product categories cart item count

Based on "Minimum cart item quantity for a specific product category in WooCommerce" and "Additional price based on cart item count in WooCommerce"
I am trying to count the products from specific product categories in checkout page, i just need a code that count the products from their category like in picture and if 2 products from 'headphone' category was in the cart then add 2 $ to total price
This image will explain everything:
Here is my code attempt:
add_action( 'woocommerce_cart_calculate_fees', 'custom_packing_fee', 10, 1 );
function custom_packing_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_cart_calculate_fees' ) >= 2 )
return;
$count = $cart->get_terms('')
if ( $count->count >= 9 ){
$fee = 15;
}
elseif( $count->count >= 6 && $count < 9 ){
$fee = 14;
}
elseif( $count>count >= 4 && $count < 6 ){
$fee = 13;
}
if ( isset($fee) && $fee > 0 ) {
$label = sprintf( __('Box fee (%d items)'), $count);
$cart->add_fee( $label, $fee, false );
}
But it doesn't work.
Based on your last question code, here is the way to count items from different product categories. As you will see, the code is compact, optimized and more efficient.
Also you need to understand how hooks work when using:
function add_action( $hook_name, $function_name_to_call, $priority, $args_count )
function add_filter( $hook_name, $function_name_to_call, $priority, $args_count )
The 2 last arguments are optional… By default the priority is 10 and the arguments count is:
0 for an action hook.
1 for a filter hook.
In a filter hook, the first function argument (variable) is always returned at the end of the function.
There are multiple possibilities:
1) Adding multiple fees for each product category count (item quantity count):
add_action( 'woocommerce_cart_calculate_fees', 'custom_packing_fees' );
function custom_packing_fees( $cart ) {
if ( is_admin() && !defined('DOING_AJAX') )
return;
if ( did_action('woocommerce_cart_calculate_fees') >= 2 )
return;
// Initializing data (settings)
$data = [
['name' => __('Cupcake'), 'threshold' => 4, 'fee' => 15, 'count' => 0],
['name' => __('Cake'), 'threshold' => 3, 'fee' => 11, 'count' => 0],
['name' => __('Macaron'), 'threshold' => 6, 'fee' => 12, 'count' => 0],
];
$fee_text = __('"%s" box fee (%d items)');
// Loop through cart items (counting product categories)
foreach ( $cart->get_cart() as $item ) {
// Loop through product categories
foreach ( $data as $key => $values ) {
if ( has_term( $values['name'], 'product_cat', $item['product_id'] ) ) {
// Increase the product category count (based on quantity)
$data[$key]['count'] += (int) $item['quantity'];
}
}
}
// Loop through product categories counts
foreach ( $data as $key => $values ) {
// Add a fee for each product category (when the count threshold value is reached)
if( $values['count'] >= $values['threshold'] ) {
$cart->add_fee( sprintf( $fee_text, $values['name'], $values['count'] ), $values['fee'], false );
}
}
}
2) Adding multiple fees for each product category count (cart item count, not quantity):
add_action( 'woocommerce_cart_calculate_fees', 'custom_packing_fees' );
function custom_packing_fees( $cart ) {
if ( is_admin() && !defined('DOING_AJAX') )
return;
if ( did_action('woocommerce_cart_calculate_fees') >= 2 )
return;
// Initializing data (settings)
$data = [
['name' => __('Cupcake'), 'threshold' => 4, 'fee' => 15, 'count' => 0],
['name' => __('Cake'), 'threshold' => 3, 'fee' => 11, 'count' => 0],
['name' => __('Macaron'), 'threshold' => 6, 'fee' => 12, 'count' => 0],
];
$fee_text = __('"%s" box fee (%d items)');
// Loop through cart items (counting product categories)
foreach ( $cart->get_cart() as $item ) {
// Loop through product categories
foreach ( $data as $key => $values ) {
if ( has_term( $values['name'], 'product_cat', $item['product_id'] ) ) {
// Increase the product category count (based on cart item count)
$data[$key]['count'] += 1;
}
}
}
// Loop through product categories counts
foreach ( $data as $key => $values ) {
// Add a fee for each product category (when the count threshold value is reached)
if( $values['count'] >= $values['threshold'] ) {
$cart->add_fee( sprintf( $fee_text, $values['name'], $values['count'] ), $values['fee'], false );
}
}
}
3) Adding a unique fee for all product categories count (item quantity count):
add_action( 'woocommerce_cart_calculate_fees', 'custom_packing_fees' );
function custom_packing_fees( $cart ) {
if ( is_admin() && !defined('DOING_AJAX') )
return;
if ( did_action('woocommerce_cart_calculate_fees') >= 2 )
return;
// Initializing data (settings)
$data = [
['name' => __('Cupcake'), 'threshold' => 4, 'fee' => 15, 'count' => 0],
['name' => __('Cake'), 'threshold' => 3, 'fee' => 11, 'count' => 0],
['name' => __('Macaron'), 'threshold' => 6, 'fee' => 12, 'count' => 0],
];
$fee_text = __('Box fee (%d items)');
$fee_amount = 0;
$total_count = 0;
// Loop through cart items (counting product categories)
foreach ( $cart->get_cart() as $item ) {
// Loop through product categories
foreach ( $data as $key => $values ) {
if ( has_term( $values['name'], 'product_cat', $item['product_id'] ) ) {
// Increase the product category count (based on quantity)
$data[$key]['count'] += (int) $item['quantity'];
}
}
}
// Loop through product categories counts
foreach ( $data as $key => $values ) {
// Calculate the fee amount for all product categories (when the count threshold value is reached)
if( $values['count'] >= $values['threshold'] ) {
$fee_amount += $values['fee'];
$total_count += $values['count'];
}
}
// The unique fee merged
if ( $fee_amount > 0 ) {
$cart->add_fee( sprintf( $fee_text, $total_count ), $fee_amount, false );
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Display Products Shipping Classes in WooCommerce order edit page

I'm using a function that allows me to calculate more than one freight in the cart based on the shipping class of each product. The function has no problem, it's perfect. But when I check the request in the area of administration of woocommerce, I need to identify in the method of submission, the name of the class corresponding to each item.
That is, I need to differentiate the items for each class, because I am using the shipping class to inform different suppliers about the orders made at the store.
But I have no idea how to make this adjustment.
Below is the function I use, working with packages based on the created classes. This function is responsible for calculating the freight in the shopping cart according to the shipping class. How do I display the shipping class name on the order page in the store admin?
function custom_split_shipping_packages_shipping_class( $packages ) {
// Reset all packages
$packages = array();
$regular_package_items = array();
$split_package_items = array();
$split_shipping_class = 'da-vinci'; // Shipping class slug
foreach ( WC()->cart->get_cart() as $item_key => $item ) {
if ( $item['data']->needs_shipping() ) {
if ( $split_shipping_class == $item['data']->get_shipping_class() ) {
$split_package_items[ $item_key ] = $item;
} else {
$regular_package_items[ $item_key ] = $item;
}
}
}
// Create shipping packages
if ( $regular_package_items ) {
$packages[] = array(
'contents' => $regular_package_items,
'contents_cost' => array_sum( wp_list_pluck( $regular_package_items, 'line_total' ) ),
'applied_coupons' => WC()->cart->get_applied_coupons(),
'user' => array(
'ID' => get_current_user_id(),
),
'destination' => array(
'country' => WC()->customer->get_shipping_country(),
'state' => WC()->customer->get_shipping_state(),
'postcode' => WC()->customer->get_shipping_postcode(),
'city' => WC()->customer->get_shipping_city(),
'address' => WC()->customer->get_shipping_address(),
'address_2' => WC()->customer->get_shipping_address_2()
)
);
}
if ( $split_package_items ) {
$packages[] = array(
'contents' => $split_package_items,
'contents_cost' => array_sum( wp_list_pluck( $split_package_items, 'line_total' ) ),
'applied_coupons' => WC()->cart->get_applied_coupons(),
'user' => array(
'ID' => get_current_user_id(),
),
'destination' => array(
'country' => WC()->customer->get_shipping_country(),
'state' => WC()->customer->get_shipping_state(),
'postcode' => WC()->customer->get_shipping_postcode(),
'city' => WC()->customer->get_shipping_city(),
'address' => WC()->customer->get_shipping_address(),
'address_2' => WC()->customer->get_shipping_address_2()
)
);
}
return $packages;
}
add_filter( 'woocommerce_cart_shipping_packages', 'custom_split_shipping_packages_shipping_class' );
I can't get yet the way to to display the shipping classes in order shipping items. but I can display this shipping classes in Order edit "line_items" this way:
// Display the shipping classes names in Order edit line items
add_action( 'woocommerce_after_order_itemmeta', 'custom_admin_order_itemmeta', 15, 3 );
function custom_admin_order_itemmeta( $item_id, $item, $product ){
if( ! is_admin() ) return; // only backend
// Display the shipping class names if they exist
if( $item->is_type( 'line_item' ) ){
$label = __( 'Shipping class:', 'woocommerce' );
$class_id = $product->get_shipping_class_id();
if( $class_id > 0 ){
$term = get_term_by( 'id', $class_id, 'product_shipping_class' );
$class_name = esc_html($term->name);
}
if( isset($class_name) )
echo '<div class="wc-order-item-ship-class"><strong>' . $label . '</strong> <span style="color:#ca4a1f;">' . $class_name . '</span></div>';
}
}
Code goes in function.php file of your active child theme (or active theme) or in any plugin file.
Tested and works. You will get something like:
Note: On Woocommerce 3.2.x I get an error when checking out, related to your actual code.

Categories