woocommerce add line item meta to main order meta - wordpress

I have a created a simple gift wrapping plugin, which adds a gift wrap product to the user cart and when they enter a message it adds it as meta data to the line item, this is fine for the woocommerce system, but our backoffice needs this meta data to be on the order and not the line item, is there a way I can add the data to the order also?
function checkout_create_order_line_item($item, $cart_item_key, $values, $order)
{
if (isset($values['_gift_wrap_message'])) {
$item->add_meta_data(__('Your message', '_gift_wrap_message'), $values['_gift_wrap_message'], true);
}
}
add_action('woocommerce_checkout_create_order_line_item', 'checkout_create_order_line_item', 10, 4);
I have the above and and I have tried the folllowing,
function checkout_create_order_line_item($item, $cart_item_key, $values, $order)
{
if (isset($values['_gift_wrap_message'])) {
$item->add_meta_data(__('Your message', '_gift_wrap_message'), $values['_gift_wrap_message'], true);
$order->update_meta_data('_gift_wrap_message', $values['_gift_wrap_message');
$order->save();
}
}
add_action('woocommerce_checkout_create_order_line_item', 'checkout_create_order_line_item', 10, 4);
But this does not work. I would really apprieciate some guidance as to how to get $values['_gift_wrap_message'] (or at least it's contents) into the order meta data

For any dynamic order line meta, you should follow 3 steps
1) Add custom meta fields on the checkout page from where customers can pass their message like this -
/**
* Add a custom field to the checkout page
*/
add_action('woocommerce_after_order_notes', 'custom_gift_wrap_message_field');
function custom_gift_wrap_message_field($checkout)
{
echo '<div id="custom_gift_wrap_message_field"><h2>' . __('Gift Message') . '</h2>';
woocommerce_form_field('_gift_wrap_message', array(
'type' => 'text',
'class' => array(
'my-field-class form-row-wide'
),
'label' => __('Custom Additional Field') ,
'placeholder' => __('Write your message here...') ,
),
$checkout->get_value('_gift_wrap_message'));
echo '</div>';
}
2) Save your custom field data when placing an order from the checkout page
/**
* Save your checkout page custom field value
*/
add_action('woocommerce_checkout_update_order_meta', 'custom_checkout_field_update_order_meta', 20, 2);
function custom_checkout_field_update_order_meta( $order_id ) {
update_post_meta($order_id, '_gift_wrap_message', sanitize_text_field($_POST['_gift_wrap_message']) );
}
3) Fetch or display your custom field value
/**
* You can get your gift message directly anywhere from $order_id like this -
*/
<?php echo get_post_meta( $order_id, '_gift_wrap_message', true ); ?>
Example:
Show custom fields value on the welcome page (after checkout page)
/**
* Display Custom Checkout Fields Data on Thankyou page
*/
function gift_wrap_message_display_order_data( $order_id ){ ?>
<table class="shop_table shop_table_responsive additional_info">
<tbody>
<tr>
<th><?php _e( 'Your Gift Message:' ); ?></th>
<td><?php echo get_post_meta( $order_id, '_gift_wrap_message', true ); ?></td>
</tr>
</tbody>
</table>
<?php }
add_action( 'woocommerce_thankyou', 'gift_wrap_message_display_order_data', 20 );
Add the above code to your currently active theme functions.php
Complete refrence URL is - https://www.cloudways.com/blog/how-to-edit-delete-fields-and-email-in-woocommerce-custom-checkout-fields/

Related

Woocommerce - Adding Custom Fields to Checkout & Custom Dashboard Tab

I have an Multistep Checkout and for that reason i have created a new custom step called "Card-Data", where i want the customer to fill the inputs. This inputs should also appear on a Tab in My Account. I already created a new custom tab for My Account Dashboard.
Can you tell me please, how i can create Custom Fields in the checkout process and and make them visible in the Custom Dashboard Tab. The customer should has the possibility to change data entries on his own through the dashboard.
Many Thanks
// i use multistep checkout wizzard plugin. here i create a step, where user
enters the card data
add_action('woocommerce_multistep_checkout_before', 'add_visica_step');
function add_visica_step() {
$contents = '<h1>Visica Daten</h1>';
$contents .= '<div class="visica-step"> Please Enter something </div>';
echo $contents;
}
add_filter ( 'woocommerce_account_menu_items', 'one_more_link' );
function one_more_link( $menu_links ){
$new = array( 'carddata' => 'Card Data' );
$menu_links = array_slice( $menu_links, 0, 1, true )
+ $new
+ array_slice( $menu_links, 1, NULL, true );
return $menu_links;
}
/*
* Step 2. Register Permalink Endpoint
*/
add_action( 'init', 'add_endpoint' );
function add_endpoint() {
// WP_Rewrite is my Achilles' heel, so please do not ask me for detailed
explanation
add_rewrite_endpoint( 'visicadata', EP_PAGES );
}
/*
* Step 3. Content for the new page in My Account, woocommerce_account_{ENDPOINT
NAME}_endpoint
*/
add_action( 'woocommerce_account_visicadata_endpoint',
'my_account_endpoint_content' );
function my_account_endpoint_content() {
echo 'Here I want do display custom fields from checkout';
}
add_filter( 'woocommerce_checkout_fields' ,
'woocommerce_checkout_field_editor' );
// Our hooked in function - $fields is passed via the filter!
function woocommerce_checkout_field_editor( $fields ) {
$fields['shipping']['shipping_field_value'] = array(
'label' => __('Field Value', 'woocommerce'),
'placeholder' => _x('Field Value', 'placeholder', 'woocommerce'),
'required' => true
);
return $fields;
}
// Display Field on Order Page, but i would like to display it on custom tab
add_action( 'woocommerce_admin_order_data_after_shipping_address',
'edit_woocommerce_checkout_page', 10, 1 );
function edit_woocommerce_checkout_page($order){
global $post_id;
$order = new WC_Order( $post_id );
echo '<p><strong>'.__('Field Value').':</strong> ' . get_post_meta($order->get_id(), '_shipping_field_value', true ) . '</p>';

WooCommerce:: id was called incorrectly error for custom checkout fields

I'm trying to display a custom checkout field I created in functions.php for WooCommerce and I get this error (along with the actual custom field text as follows:
Notice: id was called incorrectly. Order properties should not be accessed directly. Backtrace: include('wp-admin/edit-form-advanced.php'), do_meta_boxes, WC_Meta_Box_Order_Data::output, do_action('woocommerce_admin_order_data_after_billing_address'), WP_Hook->do_action, WP_Hook->apply_filters, cdm_custom_checkout_field_display_admin_order_meta, WC_Abstract_Legacy_Order->__get, wc_doing_it_wrong Please see Debugging in WordPress for more information. (This message was added in version 3.0.) in /www/webroot/cafed/wordpress/wp-includes/functions.php on line 4778
Here's the code that is generating this error.
add_action( 'woocommerce_admin_order_data_after_billing_address', 'so_custom_checkout_field_display_admin_order_meta', 10, 1 );
function so_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('Gift Message').':</strong> ' . get_post_meta( $order->id, 'Gift Message', true ) . '</p>';
}
add_filter('woocommerce_email_order_meta_keys', 'my_custom_order_meta_keys');
function my_custom_order_meta_keys( $keys ) {
$keys[] = 'Gift Message';
return $keys;
}
I believe this has something to do in regards to updates with Woo's code but I'm not sure how to alter it.
Similar thing i have worked on before is working for me
/**
* Add the field to the checkout
*/
add_action('woocommerce_before_order_notes', 'my_custom_checkout_field');
function my_custom_checkout_field( $checkout ) {
echo '<div id="my_custom_checkout_field"><h5>'.__('Time Slot: ').'</h5>';
echo '<h6>'.__('Every Day 09:00AM - 05:00PM').'</h6>';
woocommerce_form_field( 'gv_time_slot', array(
'type' => 'hidden',
'class' => array('my-field-class form-row-wide woocommerce-validated'),
'label' => __('Every Day 04:00Pm - 09:00PM'),
'required' => false,
'placeholder' => __('Check this'),
), $checkout->get_value( 'gv_time_slot' ));
echo '</div>';
}
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
global $woocommerce;
// Check if set, if its not set add an error.
if (!$_POST['gv_time_slot'])
$woocommerce->add_error( __('Please enter something into this new shiny field.') );
}
/**
* Update the order meta with field value
*/
add_action('woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta');
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ($_POST['gv_time_slot']) update_post_meta( $order_id, 'Time Slot', esc_attr($_POST['gv_time_slot']));
}
// display the extra data on order recieved page and my-account order review
function sri_display_order_data( $order_id ){ ?>
<h2><?php _e( 'Time Slot' ); ?></h2>
<table class="shop_table shop_table_responsive additional_info">
<tbody>
<tr>
<th><?php _e( 'Your Order will be delivered between' ); ?></th>
<td><?php echo 'Every Day 09:00AM - 05:00PM'; ?></td>
</tr>
<tr>
<th><?php _e( '*Please Note:' ); ?></th>
<td><?php echo 'All orders placed before 3pm in the website/WhatsApp will be delivered on the same day. Orders after 3 pm will be moved to next day.'; ?></td>
</tr>
</tbody>
</table>
<?php }
add_action( 'woocommerce_thankyou', 'sri_display_order_data', 20 );
add_action( 'woocommerce_view_order', 'sri_display_order_data', 20 );

How to correctly call a function in one plugin, from another plugin, which relies on WooCommerce variables

I am using WooCommerce with two plugins:
Yith Gift Card and
WooCommerce Pos.
Yith Gift Card plugin, allows you to sell Gift Card tokens for your store.
When someone purchases a gift card the WooCommerce order confirmation has the Gift Code printed on it.
The WooCommerce POS plugin, allows you to print a receipt from a printer. The problem is the coupon code does not display on this printed receipt.
How the coupon code is added to the WooCommerce e-mail
The Yith Gift Card Plugin adds an action via a WooCommerce e-mail hook, here is the code, excerpted from the Yith Plugin php:
class YITH_WooCommerce_Gift_Cards {
...
add_action( 'woocommerce_order_item_meta_start', array(
$this,
'show_gift_card_code',
), 10, 3 );
}
public function show_gift_card_code( $order_item_id, $item, $order ) {
$code = wc_get_order_item_meta( $order_item_id, YWGC_META_GIFT_CARD_NUMBER );
if ( ! empty( $code ) ) {
printf( '<br>' . __( 'Gift card code: %s', 'yith-woocommerce-gift-cards' ), $code );
}
}
This results in the coupon code being displayed on the WooCommerce order e-mail.
I want the same coupon code to appear on the printed POS receipt.
How the printed POS receipt is generated
I've found the file responsible for printing the printed POS receipt.
It is here: https://github.com/kilbot/WooCommerce-POS/blob/master/includes/views/print/receipt-html.php
How can I call the show_gift_card_code function from within receipt-html.php? So that it successfully displays the Gift Card Coupon code?
<table class="order-items">
<thead>
<tr>
<th class="product"><?php /* translators: woocommerce */ _e( 'Product', 'woocommerce' ); ?></th>
<th class="qty"><?php _ex( 'Qty', 'Abbreviation of Quantity', 'woocommerce-pos' ); ?></th>
<th class="price"><?php /* translators: woocommerce */ _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
{{#each line_items}}
<tr>
<td class="product">
{{name}}
[*I WOULD LIKE THE COUPON CODE DISPLAYED HERE*]
{{#with meta}}
<dl class="meta">
{{#each []}}
<dt>{{label}}:</dt>
<dd>{{value}}</dd>
{{/each}}
</dl>
{{/with}}
</td>
WooCommerce POS is a javascript application, so the receipt template is rendered once and then populated with each order retrieved from the WC REST API. Trying to insert data for a specific order will not work as expected.
For this case, your order item meta is stored with the key _ywgc_gift_card_number. Meta with an underscore at the front are generally considered private so most templates (including WooCommerce POS) will not display this meta data.
One solution would be to filter the WC REST API response to change the meta key to something without the underscore. Some example code is shown below, you would need to place this in your theme functions.php file.
function my_custom_wc_rest_shop_order_object($response)
{
if (function_exists('is_pos') && is_pos()) {
$data = $response->get_data();
if (is_array($data['line_items'])) : foreach ($data['line_items'] as &$line_item) :
if ($code = wc_get_order_item_meta($line_item['id'], '_ywgc_gift_card_number')) {
$line_item['meta_data'][] = new WC_Meta_Data(array(
'id' => '',
'key' => 'Gift Card',
'value' => $code,
));
}
endforeach; endif;
$response->set_data($data);
}
return $response;
}
add_filter('woocommerce_rest_prepare_shop_order_object', 'my_custom_wc_rest_shop_order_object');

How to add default value in custom taxonomy field in wordpress

I've created custom taxonomy name "Front List" using Custom Post Type UI then add a custom field called "Order". I'm trying to set a default value for order. When I create any frontlist using the frontlist panel,
it's adding a default value, but when I create frontlist from "Add Post" page it's not adding any default value for "Order field".
How to I add default value when "Front List" created from "Add Post" page?
This is the code for adding a custom field to Frontlist taxonomy.
<?php
/**
* Adding Custom Field to Taxonomy
* #return void
*/
function frontlists_add_order( $term ) {
?>
<div class="form-field">
<label for="taxOrder"><?php _e( 'Order', 'yourtextdomain' ); ?></label>
<input type="text" name="taxOrder" id="taxOrder" value="">
<p>Your front List item will be sorted by this "Order". The default value is "1".</p>
</div>
<?php
}
add_action( 'frontlists_add_form_fields', 'frontlists_add_order', 10, 2 );
/**
* Adding Custom Field to Taxonomy in Edit Panel
* #return void
*/
function frontlists_edit_order( $term ) {
$term_order = get_term_meta( $term->term_id, 'order', true );
?>
<tr class="form-field">
<th><label for="taxOrder"><?php _e( 'Order', 'yourtextdomain' ); ?></label></th>
<td>
<input type="text" name="taxOrder" id="taxOrder" value="<?php echo esc_attr( $term_order ) ? esc_attr( $term_order ) : ''; ?>">
<p>Your front List item will be sorted by this "Order".</p>
</td>
</tr>
<?php
}
add_action( 'frontlists_edit_form_fields', 'frontlists_edit_order', 10 );
/**
* Saving Custom Field to Taxonomy
*/
function frontlists_save_order( $term_id ) {
if ( isset( $_POST['taxOrder'] ) ) {
$term_order = $_POST['taxOrder'];
if( $term_order ) {
update_term_meta( $term_id, 'order', $term_order );
} else {
update_term_meta( $term_id, 'order', 1 );
}
}
}
add_action( 'edited_frontlists', 'frontlists_save_order' );
add_action( 'create_frontlists', 'frontlists_save_order' );
You can use the created_term action hook to add the new taxonomy term once it's already been added to the database. This action hook is inside the wp_insert_term function. Either put this in your theme (not advised), or inside a plugin.
function so_add_order_field( $term_id, $tt_id, $taxonomy ) {
// The default order value
$default = 1;
// Stop if it's not the right taxonomy
if ( 'frontlists' != $taxonomy ) {
return false;
}
// Get the existing value if exists
$order = get_term_meta( $term_id, 'taxOrder', true );
if ( false === $order ) {
// Add the term meta default
add_term_meta( $term_id, 'taxOrder', $default );
}
}
add_action( 'created_term', 'so_add_order_field', 10, 3 );
Then change the $default value to whatever you'd like it to be. This uses the add_term_meta function which safely adds the meta data to the database for you. Check out the documentation for further info.

New billing fields not showing on User page (Poor Guys Swiss Knife plugin for WooCommerce)

Using Poor Guys Swiss Knife plugin for WooCommerce, I created 3 new Billing fields: birthday (date), newsletter (select: yes/no) and terms & conditions (select: yes/no). I successfully registered as a new customer on the site and filled these new fields.
However when checking the account thus created in the dashboard, I see all the regular fields except the 3 ones I created with the Poor Guys Swiss Knife plugin. Why is that ?
Clearly plugin is not sending fields data to user account.
You can achieve same results using woocommerce custom fields in your functions.php file.
// Hook in
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
// Our hooked in function - $fields is passed via the filter!
function custom_override_checkout_fields( $fields ) {
$fields['shipping']['shipping_phone'] = array(
'label' => __('Phone', 'woocommerce'),
'placeholder' => _x('Phone', 'placeholder', 'woocommerce'),
'required' => false,
'class' => array('form-row-wide'),
'clear' => true
);
return $fields;
}
To make it required use this code:
/**
* Process the checkout
*/
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['my_field_name'] )
wc_add_notice( __( 'Please enter something into this new shiny field.' ), 'error' );
}
you can find more on this website:
http://docs.woothemes.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
Here is a solution that I came up with and it has been working fine for me, hope it helps you as well.
I created a few new fields for the billing form using that plugin but let's just use one as an example:
-Resale License # ( billing_resale_license_ )
Now, the plugin ( or the code from the first answer ) will add the field to the form for you, in my case, I end up with:
<input type="text" class="input-text " name="billing_resale_license_" id="billing_resale_license_" placeholder="" value="" display="text">
Now, we need to save the value of that field to the user_meta table, like so:
add_action( 'woocommerce_checkout_process', 'ws_billing_fields_save', 10, 1 );
function ws_billing_fields_save( $user_id ){
if ( isset( $_POST['billing_resale_license_'] ) ) {
update_user_meta($user_id, 'billing_resale_license_', $_POST['billing_resale_license_']);
}
}
Now that data is stored in user_meta, we need to hook in to the profile area to display it and allow it to be edited by the user or admins.
add_action( 'show_user_profile', 'ws_update_user_profile' );
add_action( 'edit_user_profile', 'ws_update_user_profile' );
function ws_update_user_profile( $user ){ ?>
<h3>Additional Fields</h3>
<table class="form-table">
<tr>
<th><label for="billing_resale_license_">Resale #</label></th>
<td><input type="text" name="billing_resale_license_" value="<?php echo esc_attr(get_the_author_meta( 'billing_resale_license_', $user->ID )); ?>" class="regular-text" /></td>
</tr>
</table>
add_action( 'personal_options_update', 'save_extra_fields' );
add_action( 'edit_user_profile_update', 'save_extra_fields' );
function save_extra_fields( $user_id ){
update_user_meta( $user_id,'billing_resale_license_', sanitize_text_field( $_POST['billing_resale_license_'] ) );
}
I chose to break my additional fields into their own table just above the default Woocommerce fields as I have many of them and they are more specific to the user rather than the order processing itself, so I keep them organized in their own table titled "Additional Fields".
I think the billing fields are visible on the order only, not the user. User fields are available through the register_form and user_register hooks.

Resources