1
votes

I need to be able to add admin data to subscription product variations (Woo Subscriptions extension) in order to pass this data on to fulfilment centres when an order is placed.

The issue I have is getting these values out from the product and passing them into the order and email notifications such that they can be properly exported, added to shipping labels and emailed via the various woo notifications.

I have custom meta fields added to variations on a subscription product. I can add data into these and they save data properly into the database on the correct variation ID. No problem there.

I can show custom test data on the cart and checkout page and also save this data into the order as you'll see in the code.

For brevity, the code is reduced below but there are in fact 6 text fields:

// Add custom field inputs to each product variation
add_action( 'woocommerce_variation_options_pricing', 'add_custom_field_to_variations', 10, 3 );

function add_custom_field_to_variations( $loop, $variation_data, $variation ) {
    woocommerce_wp_text_input( 
        array(
            'id' => '_dose_customer_field[' . $loop . ']',
            'label'       => __( 'Dose (Customer)', 'woocommerce' ), 
            'placeholder' => __('Enter the treatment dosage','woocommerce' ),
            'desc_tip'    => 'true',
            'description' => __( 'Enter dosage info for this variation', 'woocommerce' ),
            'class' => '',
            'value' => get_post_meta( $variation->ID, '_dose_customer_field', true )
        )
    );
}

// Save custom field on product variation save 
add_action( 'woocommerce_save_product_variation', 'save_custom_field_variations', 10, 2 );

function save_custom_field_variations( $variation_id, $i ) {
    $_dose_customer_field = $_POST['_dose_customer_field'][$i];
    if ( isset( $_dose_customer_field ) ) update_post_meta( $variation_id, '_dose_customer_field', esc_attr( $_dose_customer_field ) );   
}

// Add metadata to cart item post.
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_fields_cart_item_data', 10, 2 );

function add_custom_fields_cart_item_data( $cart_item_data, $product_id ){    

    $cart_item_data['custom_data']['_dose_customer_field'] = 'TEST DATA' /* HOW TO GET DATA FROM CUSTOM FIELD HERE */       

    $cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
    WC()->session->set( 'custom_data', $cart_item_data['custom_data'] );

    return $cart_item_data;
}

// Display custom meta data on cart and checkout page.
add_filter( 'woocommerce_get_item_data', 'display_custom_fields_cart_item_data', 10, 2 );

function display_custom_fields_cart_item_data($item_data, $cart_item){

    if( ! array_key_exists( 'custom_data', $cart_item ) )
        return $item_data;

    if( array_key_exists( '_dose_customer_field', $cart_item['custom_data'] ) )
        $item_data[] = array(
            'key'   => __('Dose (Customer)', 'woocommerce'),
            'value' => $cart_item['custom_data']['_dose_customer_field']
        );

    return $item_data;
}

// Add metadata to the order.
add_action('woocommerce_checkout_create_order_line_item', 'save_custom_fields_as_order_item_meta', 20, 4);

function save_custom_fields_as_order_item_meta($item, $cart_item_key, $values, $order) {
    if( ! isset($values['custom_data']) )
        return;

    $text_domain ='woocommerce';

    if( array_key_exists('_dose_customer_field', $values['custom_data']) ){
        $item->update_meta_data( __('Dose (Customer)', $text_domain), $values['custom_data']['_dose_customer_field'] );
    }    
}

// Frontend & emails: Display data on notifications
add_action( 'woocommerce_order_item_meta_start', 'vp_order_item_display_commodity_code', 10, 4 );
function vp_order_item_display_commodity_code( $item_id, $item, $order, $plain_text ) {
    // Not on admin
    //if( is_admin() ) return;

    if( $value = $item->get_meta('_dose_customer_field') ) {
        $value = '<strong>' . __("Dose (Customer)", "woocommerce") . ':</strong> ' . esc_attr( $value );

        // On orders
        if( is_wc_endpoint_url() )
            echo '<div class="vp-ccode"><small>' . $value . '</small></div>';
        // On Emails
        else
            echo '<div>' . $value . '</div>';
    }
}

So everything is working except getting the data from the custom fields. It seems odd that I have to create a new array (here called 'custom_data') and add it to the cart_item_data, when the data is already available on the product variation, albeit private.

My question is how do get the metadata within add_custom_fields_cart_item_data()? Is this even the correct approach?

Many thanks

1

1 Answers

2
votes

As this custom data exist for the product, you can get it easily and save it as order item custom data (so it will be displayed everywhere):

The complete code (changed the 2 last functions):

// Add custom field inputs to each product variation
add_action( 'woocommerce_variation_options_pricing', 'add_custom_field_to_variations', 10, 3 );
function add_custom_field_to_variations( $loop, $variation_data, $variation ) {
    woocommerce_wp_text_input( 
        array(
            'id' => '_dose_customer_field[' . $loop . ']',
            'label'       => __( 'Dose (Customer)', 'woocommerce' ), 
            'placeholder' => __('Enter the treatment dosage','woocommerce' ),
            'desc_tip'    => 'true',
            'description' => __( 'Enter dosage info for this variation', 'woocommerce' ),
            'class' => '',
            'value' => get_post_meta( $variation->ID, '_dose_customer_field', true )
        )
    );
}

// Save custom field on product variation save 
add_action( 'woocommerce_save_product_variation', 'save_custom_field_variations', 10, 2 );
function save_custom_field_variations( $variation_id, $i ) {
    $_dose_customer_field = $_POST['_dose_customer_field'][$i];
    if ( isset( $_dose_customer_field ) ) update_post_meta( $variation_id, '_dose_customer_field', esc_attr( $_dose_customer_field ) );   
}

// Display custom meta data on cart and checkout page.
add_filter( 'woocommerce_get_item_data', 'display_custom_fields_cart_item_data', 10, 2 );
function display_custom_fields_cart_item_data( $item_data, $cart_item ) {
    if( $value = $cart_item['data']->get_meta( '_dose_customer_field' ) )
        $item_data[] = array(
            'key'   => __('Dose (Customer)', 'woocommerce'),
            'value' => $value
        );

    return $item_data;
}

// Add metadata to the order item (and display it everywhere).
add_action('woocommerce_checkout_create_order_line_item', 'save_custom_fields_as_order_item_meta', 10, 4);
function save_custom_fields_as_order_item_meta( $item, $cart_item_key, $values, $order ) {
    if( $meta_value = $values['data']->get_meta( '_dose_customer_field' ) )
        $item->update_meta_data( __('Dose (Customer)', 'woocommerce'), $meta_value );  
}

Code goes in functions.php file of your active child theme (or active theme). It should work.