I tried to call in the mini cart woocommerce_cart_totals() to get a coupon discount. But in mini cart it's not working. It's working only when I go to the cart page and refresh the page.
After this, discount in mini cart is working fine. But now I want to know, why it's not working in another page? And not working without cart page refresh?
<?php foreach ( WC()->cart->get_coupons() as $code => $coupon ) : ?>
<tr class="cart-discount coupon-<?php echo esc_attr( sanitize_title( $code ) ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td data-title="<?php echo esc_attr( wc_cart_totals_coupon_label( $coupon, false ) ); ?>"><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
Related
i am using this following code to show the option to add an additional fee (product) to the cart on the "cart" page. It is working great but it is now showing on the cart page, but how do i get it to show on the checkout page additionally:
<?php
/* ADD custom theme functions here */
add_filter( 'woocommerce_price_trim_zeros', 'wc_hide_trailing_zeros', 10, 1 );
function wc_hide_trailing_zeros( $trim ) {
return true;
}
add_action('woocommerce_cart_totals_after_shipping', 'wc_shipping_insurance_note_after_cart');
function wc_shipping_insurance_note_after_cart() {
global $woocommerce;
$product_id = 971;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found ):
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php else: ?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php endif;
}
I have tried different methods, and it should be pretty basic but i am rusty on my Functions.php skills.
You could try copying the function and giving it a new name. Then change the hook depending on where you want it on the checkout page.
Here is a great visual guide to the hooks on the checkout page: https://www.businessbloomer.com/woocommerce-visual-hook-guide-checkout-page/
Try something like this:
Notice how I changed the hook from woocommerce_cart_totals_after_shipping to woocommerce_before_checkout_form here you can experiment using the hooks on the guide I linked to. I also changed the name of the function from wc_shipping_insurance_note_after_cart to wc_shipping_insurance_note_after_checkout to avoid conflicts.
add_action('woocommerce_before_checkout_form', 'wc_shipping_insurance_note_after_checkout');
function wc_shipping_insurance_note_after_checkout() {
global $woocommerce;
$product_id = 971;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found ):
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php else: ?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php endif;
}
Edit per comment. You could try something like this if you only want to add the table row if a product in the cart has a certain category.
You will have to change "example-category" in $categories = array('example-category'); to your category slug.
add_action('woocommerce_before_checkout_form','wc_shipping_insurance_note_after_checkout');
function wc_shipping_insurance_note_after_checkout() {
global $woocommerce;
$categories = array('example-category');
$found = false;
//loop trough cart items
foreach ( WC()->cart->get_cart_contents() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
//Check if product has category
if ( has_term( $categories, 'product_cat', $product_id ) ) {
$found = true;
}
}
// Do this if product has category
if ( $found ) {
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php
} else {
//If product does not have category do this instead
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php
}
}
I'm using a coupon for a calculation in the Woocommerce cart. It automatically adds a discount to the total so the right amount can be sent to payments gateways.
I'd like to hide all infos about this coupons/discount from visitors.
Problem: The only method I've found (see below) hides the coupon field, row (from totals) and messages, but also disable the coupon...
add_filter( 'woocommerce_coupons_enabled', 'hide_coupon_field' );
function hide_coupon_field( $enabled ) {
if ( is_cart() || is_checkout() ) {
$enabled = false;
}
return $enabled;
}
Is there a hook allowing to hide everything related to the discount without canceling the coupon?
EDIT:
Looks like it's impossible to simply remove the discount line in the order-details. So a simple solution, inspired by helgatheviking suggestion, might be to remove all the totals generated by this part
<?php if ( $totals = $order->get_order_item_totals() ) foreach ( $totals as $total ) : ?>
<tr>
<th scope="row"><?php echo $total['label']; ?></th>
<td><?php echo $total['value']; ?></td>
</tr>
<?php endforeach; ?>
And then to echo them one by one the way I need it. I'm already able to show the order total with this
<td><?php echo number_format($order->get_total(),2,'.','')."€"; ?></td>
but now I'm trying to retrieve the order subtotal, and this code
<td><?php echo number_format($order->get_item_subtotal(),2,'.','')."€"; ?></td>
gives me a Warning: Missing argument 1 for WC_Order::get_item_subtotal().
I'm not sure if get_item_subtotal() is the right way to get the order subtotal. And if so, what argument is missing? Or should I search around get_line_subtotal or get_subtotal_to_display?
No, there does not seem to be as there is no filter in the get_coupons() method of the cart class. If you went to the WooCommerce git repo and sent a pull request with a filter here and an explanation as to why it should be there, they might consider merging it in. I've done that a few times.
You could also, copy the checkout/review-order.php and cart/cart-totals.php templates into your theme and remove the following two blocks of code:
<?php foreach ( WC()->cart->get_coupons( 'cart' ) as $code => $coupon ) : ?>
<tr class="cart-discount coupon-<?php echo esc_attr( $code ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
and
<?php foreach ( WC()->cart->get_coupons( 'order' ) as $code => $coupon ) : ?>
<tr class="order-discount coupon-<?php echo esc_attr( $code ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
Keep in mind that this prevents the display of ALL coupon discounts and will end up looking like the following screenshots:
I'm not a fan of overriding the more complex WC templates... especially not the ones pertaining to the checkout process. I've had to fix many sites that stopped working when their theme template overrides became obsolete as WooCommerce develops.
Edit
I tracked down the Discount row in the order/order-details.php template. It is from the function $order->get_order_item_totals()... this returns an array of rows and can be filtered. So, this removes the row from the order received page:
function so_25714509_get_order_item_totals( $total_rows ){
unset( $total_rows['order_discount'] );
return $total_rows;
}
add_filter( 'woocommerce_get_order_item_totals', 'so_25714509_get_order_item_totals' );
I am using WordPress with WooCommerce and WooCommerce subscriptions plugins and below is my code in which I have added a custom field called (Mindesk VAR Client User - Dropdown) to show in "Edit Subscription" admin page saving to my custom field based on subscription ID.
This is how it's looking like.
And this is my working code.
<?php
// action triggered when we go to add/edit subscription page
add_action('woocommerce_admin_order_data_after_order_details', 'showWCSubscriptionCustomFields');
add_action('woocommerce_process_shop_order_meta', 'saveWCSubscriptionCustomFields');
function showWCSubscriptionCustomFields($subscription) {
$currentPage = get_current_screen();
// If page is "Edit Subscription" page, then only show
if ($currentPage->action == 'add')
return;
// Getting all the users
$mindeskUsers = getAllUsers();
?>
<br class="clear" />
<p class="form-field form-field-wide">
<label for="mindesk_wc_subscriptions_var_client_user_id">Mindesk VAR Client User:</label>
<?php
$selectedUser = get_post_meta($subscription->get_id(), 'mindesk_wc_subscriptions_var_client_user_id', true);
echo getUsersListSelect('mindesk_wc_subscriptions_var_client_user_id', $selectedUser, $mindeskUsers, 'mindesk_select2');
?>
</p>
<?php
}
function saveWCSubscriptionCustomFields($subscription_id) {
// wc_clean() and wc_sanitize_textarea() are WooCommerce sanitization functions
update_post_meta($subscription_id, 'mindesk_wc_subscriptions_var_client_user_id', wc_clean($_POST['mindesk_wc_subscriptions_var_client_user_id']));
}
This is working fine for me.
Now I have a custom requirement to add a button something called as Transfer in each row in http:://www.mywebsite.com/my-account/subscriptions/ page.
For example this page somewhere beside Total.
After clicking on that button, the popup should come with a form and I should be able to save a field "Transfer to VAR Client User" based on subscription ID same as I have shown you a working code above with my custom field.
I have tried to do R & D but most of the links suggesting to add custom fields and all in "My Account" page (/my-account) But I want to achieve the same in "my-account/subscriptions" page.
Can anyone guide me how can I achieve this? Any suggestion will be highly appreciated.
Thanks
You can copy the my-subscriptions.php file from the woocommerce-subscriptions/templates/myaccount and add it to your active theme woocommerce folder create folder myaccount and paste my-subscriptions.php. and then modify as per your requirement.
<?php if ( ! empty( $subscriptions ) ) : ?>
<table class="my_account_subscriptions my_account_orders woocommerce-orders-table woocommerce-MyAccount-subscriptions shop_table shop_table_responsive woocommerce-orders-table--subscriptions">
<thead>
<tr>
<th class="subscription-id order-number woocommerce-orders-table__header woocommerce-orders-table__header-order-number woocommerce-orders-table__header-subscription-id"><span class="nobr"><?php esc_html_e( 'Subscription', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-status order-status woocommerce-orders-table__header woocommerce-orders-table__header-order-status woocommerce-orders-table__header-subscription-status"><span class="nobr"><?php esc_html_e( 'Status', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-next-payment order-date woocommerce-orders-table__header woocommerce-orders-table__header-order-date woocommerce-orders-table__header-subscription-next-payment"><span class="nobr"><?php echo esc_html_x( 'Next payment', 'table heading', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-total order-total woocommerce-orders-table__header woocommerce-orders-table__header-order-total woocommerce-orders-table__header-subscription-total"><span class="nobr"><?php echo esc_html_x( 'Total', 'table heading', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-total order-total woocommerce-orders-table__header woocommerce-orders-table__header-order-total woocommerce-orders-table__header-subscription-total"><span class="nobr"><?php echo esc_html_x( 'Transfer', 'table heading', 'woocommerce-subscriptions' ); ?></span></th>
<th class="subscription-actions order-actions woocommerce-orders-table__header woocommerce-orders-table__header-order-actions woocommerce-orders-table__header-subscription-actions"> </th>
</tr>
</thead>
<tbody>
<?php /** #var WC_Subscription $subscription */ ?>
<?php foreach ( $subscriptions as $subscription_id => $subscription ) : ?>
<tr class="order woocommerce-orders-table__row woocommerce-orders-table__row--status-<?php echo esc_attr( $subscription->get_status() ); ?>">
<td class="subscription-id order-number woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-id woocommerce-orders-table__cell-order-number" data-title="<?php esc_attr_e( 'ID', 'woocommerce-subscriptions' ); ?>">
<?php echo esc_html( sprintf( _x( '#%s', 'hash before order number', 'woocommerce-subscriptions' ), $subscription->get_order_number() ) ); ?>
<?php do_action( 'woocommerce_my_subscriptions_after_subscription_id', $subscription ); ?>
</td>
<td class="subscription-status order-status woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-status woocommerce-orders-table__cell-order-status" data-title="<?php esc_attr_e( 'Status', 'woocommerce-subscriptions' ); ?>">
<?php echo esc_attr( wcs_get_subscription_status_name( $subscription->get_status() ) ); ?>
</td>
<td class="subscription-next-payment order-date woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-next-payment woocommerce-orders-table__cell-order-date" data-title="<?php echo esc_attr_x( 'Next Payment', 'table heading', 'woocommerce-subscriptions' ); ?>">
<?php echo esc_attr( $subscription->get_date_to_display( 'next_payment' ) ); ?>
<?php if ( ! $subscription->is_manual() && $subscription->has_status( 'active' ) && $subscription->get_time( 'next_payment' ) > 0 ) : ?>
<br/><small><?php echo esc_attr( $subscription->get_payment_method_to_display( 'customer' ) ); ?></small>
<?php endif; ?>
</td>
<td class="subscription-total order-total woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-total woocommerce-orders-table__cell-order-total" data-title="<?php echo esc_attr_x( 'Total', 'Used in data attribute. Escaped', 'woocommerce-subscriptions' ); ?>">
<?php echo wp_kses_post( $subscription->get_formatted_order_total() ); ?>
</td>
<td class="subscription-actions order-actions woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-actions woocommerce-orders-table__cell-order-actions">
<?php echo esc_html_x( 'Transfer', 'Transfer a subscription', 'woocommerce-subscriptions' ); ?>
</td>
<td class="subscription-actions order-actions woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-actions woocommerce-orders-table__cell-order-actions">
<?php echo esc_html_x( 'View', 'view a subscription', 'woocommerce-subscriptions' ); ?>
<?php do_action( 'woocommerce_my_subscriptions_actions', $subscription ); ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php if ( 1 < $max_num_pages ) : ?>
<div class="woocommerce-pagination woocommerce-pagination--without-numbers woocommerce-Pagination">
<?php if ( 1 !== $current_page ) : ?>
<a class="woocommerce-button woocommerce-button--previous woocommerce-Button woocommerce-Button--previous button" href="<?php echo esc_url( wc_get_endpoint_url( 'subscriptions', $current_page - 1 ) ); ?>"><?php esc_html_e( 'Previous', 'woocommerce-subscriptions' ); ?></a>
<?php endif; ?>
<?php if ( intval( $max_num_pages ) !== $current_page ) : ?>
<a class="woocommerce-button woocommerce-button--next woocommerce-Button woocommerce-Button--next button" href="<?php echo esc_url( wc_get_endpoint_url( 'subscriptions', $current_page + 1 ) ); ?>"><?php esc_html_e( 'Next', 'woocommerce-subscriptions' ); ?></a>
<?php endif; ?>
</div>
<?php endif; ?>
<?php else : ?>
<p class="no_subscriptions woocommerce-message woocommerce-message--info woocommerce-Message woocommerce-Message--info woocommerce-info">
<?php if ( 1 < $current_page ) :
printf( esc_html__( 'You have reached the end of subscriptions. Go to the %sfirst page%s.', 'woocommerce-subscriptions' ), '', '' );
else :
esc_html_e( 'You have no active subscriptions.', 'woocommerce-subscriptions' );
?>
<a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>">
<?php esc_html_e( 'Browse products', 'woocommerce-subscriptions' ); ?>
</a>
<?php
endif; ?>
</p>
<?php endif; ?>
Tested and works
I am trying to implement the code below when a discount is applied to an order on my Woocommerce store. Right now, it shows every time a product is added. I am discounting all orders 15% when 5 or more products are added to the cart. But if I only add 2 products the table row still shows (and it shows $40 which is odd). It works great when 5 or more items are added to the cart. Any help would be much appreciated.
<tr class="cart-subtotal">
<th><?php esc_html_e( '15% Discount', 'beaux' ); ?></th>
<td><?php esc_html_e( '-', 'beaux' ); ?><?php echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); ?></td>
</tr>
I think you did it using woocommerce templates, it's better to use hooks:
add_filter( 'woocommerce_cart_totals_order_total_html', 'ywp_custom_total_message_html' );
function ywp_custom_total_message_html( $value ) {
global $woocommerce;
$cart_item_count = $woocommerce->cart->cart_contents_count;
if( $cart_item_count >= 5 ) {
$value .= esc_html_e( '15% Discount', 'beaux' ) . '<br />';
}
return $value;
}
Code goes in functions.php of your active theme/child theme. Tested and works.
You can check the number of items in the cart using WC()->cart->get_cart_contents_count().
<?php if ( WC()->cart->get_cart_contents_count() >= 5 ): ?>
<tr class="cart-subtotal">
<th><?php esc_html_e( '15% Discount', 'beaux' ); ?></th>
<td><?php esc_html_e( '-', 'beaux' ); ?><?php echo apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key ); ?></td>
</tr>
<?php endif; ?>
Just replace your snippet by this one. If less than 5 items are in the cart, the discount won't show.
I'm using a coupon for a calculation in the Woocommerce cart. It automatically adds a discount to the total so the right amount can be sent to payments gateways.
I'd like to hide all infos about this coupons/discount from visitors.
Problem: The only method I've found (see below) hides the coupon field, row (from totals) and messages, but also disable the coupon...
add_filter( 'woocommerce_coupons_enabled', 'hide_coupon_field' );
function hide_coupon_field( $enabled ) {
if ( is_cart() || is_checkout() ) {
$enabled = false;
}
return $enabled;
}
Is there a hook allowing to hide everything related to the discount without canceling the coupon?
EDIT:
Looks like it's impossible to simply remove the discount line in the order-details. So a simple solution, inspired by helgatheviking suggestion, might be to remove all the totals generated by this part
<?php if ( $totals = $order->get_order_item_totals() ) foreach ( $totals as $total ) : ?>
<tr>
<th scope="row"><?php echo $total['label']; ?></th>
<td><?php echo $total['value']; ?></td>
</tr>
<?php endforeach; ?>
And then to echo them one by one the way I need it. I'm already able to show the order total with this
<td><?php echo number_format($order->get_total(),2,'.','')."€"; ?></td>
but now I'm trying to retrieve the order subtotal, and this code
<td><?php echo number_format($order->get_item_subtotal(),2,'.','')."€"; ?></td>
gives me a Warning: Missing argument 1 for WC_Order::get_item_subtotal().
I'm not sure if get_item_subtotal() is the right way to get the order subtotal. And if so, what argument is missing? Or should I search around get_line_subtotal or get_subtotal_to_display?
No, there does not seem to be as there is no filter in the get_coupons() method of the cart class. If you went to the WooCommerce git repo and sent a pull request with a filter here and an explanation as to why it should be there, they might consider merging it in. I've done that a few times.
You could also, copy the checkout/review-order.php and cart/cart-totals.php templates into your theme and remove the following two blocks of code:
<?php foreach ( WC()->cart->get_coupons( 'cart' ) as $code => $coupon ) : ?>
<tr class="cart-discount coupon-<?php echo esc_attr( $code ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
and
<?php foreach ( WC()->cart->get_coupons( 'order' ) as $code => $coupon ) : ?>
<tr class="order-discount coupon-<?php echo esc_attr( $code ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
Keep in mind that this prevents the display of ALL coupon discounts and will end up looking like the following screenshots:
I'm not a fan of overriding the more complex WC templates... especially not the ones pertaining to the checkout process. I've had to fix many sites that stopped working when their theme template overrides became obsolete as WooCommerce develops.
Edit
I tracked down the Discount row in the order/order-details.php template. It is from the function $order->get_order_item_totals()... this returns an array of rows and can be filtered. So, this removes the row from the order received page:
function so_25714509_get_order_item_totals( $total_rows ){
unset( $total_rows['order_discount'] );
return $total_rows;
}
add_filter( 'woocommerce_get_order_item_totals', 'so_25714509_get_order_item_totals' );