In WooCommerce, I understand well that woocommerce_get_order_item_totals filter kook is used to customize order total rows like reordering them.
add_filter( 'woocommerce_get_order_item_totals', 'custom_order_of_from_order_table', 10, 2 );
function woocommerce_get_order_item_totals( $total_rows, $order ) {
// code here
return $total_rows;
}
I have tried to reorder the subtotal over the total, and the payment method below the total without success on WooCommerce ThankYou page. My PHP knowledge is very limited and I appreciate any help.
How to customize total rows from order table, reordering them on WooCommerce thankyou page?
The following will reorder items totals as desired on Woocommerce thankyou (order received) page only:
add_filter( 'woocommerce_get_order_item_totals', 'reordering_order_item_totals', 10, 3 );
function reordering_order_item_totals( $total_rows, $order, $tax_display = '' ){
// Only on "order received" thankyou page
if ( ! is_wc_endpoint_url('order-received') )
return $total_rows;
$sorted_items_end = array('cart_subtotal', 'order_total', 'payment_method');
$sorted_total_rows = array(); // Initializing
// Loop through sorted totals item keys
foreach( $sorted_items_end as $item_key ) {
if( isset($total_rows[$item_key]) ) {
$sorted_total_rows[$item_key] = $total_rows[$item_key]; // Save sorted data in a new array
unset($total_rows[$item_key]); // Remove sorted data from default array
}
}
return array_merge( $total_rows, $sorted_total_rows); // merge arrays
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
To make that work everywhere for customer orders and email notifications, just remove:
// Only on "order received" thankyou page
if ( ! is_wc_endpoint_url('order-received') )
return $total_rows;
Related
I would like to add a function that is triggered every time that the stock quantity of a product will be changed in the admin product page, such that this function will not allow any reduce of the stock value - but only increase.
This is to prevent an admin user to reduce the stock quantity of the products.
Of course, this function should not be triggered if a product will be in an order, since then of course I would like the stock quantity to be reduced.
I tried the following function in the functions.php but unfortunately did not work.
Since I'm new to woocommerce and php, any ideas that could provide a solid solution to the problem?
// get old and new product stock quantity
function get_old_and_new_product_quantity_stock( $sql, $product_id_with_stock, $new_stock, $operation ) {
$product = wc_get_product( $product_id_with_stock );
$old_stock_quantity = $product->get_stock_quantity();
$new_stock_quantity = $new_stock;
echo $old_stock_quantity, $new_stock_quantity;
if ($new_stock_quantity < $old_stock_quantity) {
$new_stock = $old_stock_quantity;
$new_stock_quantity = $old_stock_quantity;
}
return $sql;
}
add_filter( 'woocommerce_update_product_stock_query', 'get_old_and_new_product_quantity_stock', 10, 4 );
You can use the update_post_meta action hook to check if the new value is less than the previous value and display error message.
This will work for quick edit and for product edit page. But the wp_die on product page will look bad so use the javascript to prevent submitting on product edit page (there was another question about it yesterday)
Be sure to test this snippet and create some orders that will reduce the stock automatically. I added is_admin() check but please do a good test.
add_action( 'update_post_meta', 'prevent_reducing_stock_metadata', 10, 4 );
function prevent_reducing_stock_metadata( $meta_id, $post_id, $meta_key, $meta_value ) {
// Check if the meta key is _stock and the new value is less than the previous value
if ( '_stock' == $meta_key && $meta_value < get_post_meta( $post_id, '_stock', true ) ) {
// Check if this is an update from the WordPress admin area
if ( is_admin() ) {
wp_die( __( 'Error: You cannot reduce the stock level for this product.' ), 'error' );
}
}
}
i want see attributes in the back end on the all products page.
and can it shows the quanity vs in stock out of stock?
many plugins tried so far none suitable
I don't know about any plugin for these kind of functionality. But, I've created this functionality. Let me share the details with you.
Add following snippets of code to your active child-theme's functions.php file.
Below displayed snippets will add new columns to All Products page's Product Table. i.e. Stock Quantity and Color. Here Color is my product's attribute.
add_filter( 'manage_edit-product_columns', 'admin_products_column', 9999 );
function admin_products_column( $columns ){
$columns['stock_quantity'] = 'Stock Quantity'; // Stock
$columns['color'] = 'Color'; // Attribute
return $columns;
}
Now we need to bring the data in these columns, So for the Stock Quantity use below mentioned code snippets.
add_action( 'manage_product_posts_custom_column', 'admin_products_stock_column_content', 10, 2 );
function admin_products_stock_column_content( $column, $product_id ){
if ( $column == 'stock_quantity' ) { // condition to check stock qty. column.
$product = wc_get_product( $product_id );
echo $product->get_stock_quantity();
}
}
To get data in color attribute column use below mentioned code snippets.
add_action( 'manage_product_posts_custom_column', 'admin_products_attribute_color_column_content', 10, 2 );
function admin_products_attribute_color_column_content( $column, $product_id ){
if ( $column == 'color' ) { // condition to check color attribute column
$product = wc_get_product( $product_id );
echo $product->get_attribute('pa_color'); // 'pa_color' is Slug of Color Attribute.
}
}
Final result will look like this image.
I would like to set a 50% discount when and only when the admin adds a product to the existing order via the admin area.
I've tried with this:
function admin_set_custom_price( $item, $item_id ) {
$item->set_subtotal( ( ( ( 100 - 50 ) * $item->get_subtotal() ) / 100 ) );
$item->set_total( ( ( ( 100 - 50 ) * $item->get_total() ) / 100 ) );
$item->apply_changes();
$item->save();
return $item;
}
add_filter( 'woocommerce_ajax_order_item', 'admin_set_custom_price', 10, 2 );
And the result is that when the item is added the price is the original price.
If I then simply refresh the page, it shows the prices with 50% discount.
What else do I need to do show the price with discount right away when it is added without the need to refresh the page?
Looks like something is overriding it as it is saved I would guess since the price is correct on refresh.
Talking about simple/variation product types.
So I've used this hook instead:
woocommerce_ajax_added_order_items
And then in the function:
foreach ( $order->get_items() as $order_item_id => $order_item_data ) {
// Set custom price.
}
Seems to work just fine.
UPDATE:
It turns out that the above hook only get the last item in case you want to add multiple items at once.
A better hook which is executed in the loop ONLY for the items added via ajax (not affecting the existing ones) is:
woocommerce_ajax_add_order_item_meta
Then in the loop you can do a loop over the items in the cart and if the cart id matches, you can change the product.
function update_order_prices_on_admin_ajax( $item_id, $item, $order )
foreach ( $order->get_items() as $order_item_id => $order_item_data ) {
if ( $order_item_id == $item_id ) {
// Do changes here.
// Runs this after making a change to $order_item_data
$order->apply_changes();
$order->save();
}
}
}
add_action( 'woocommerce_ajax_add_order_item_meta', 'update_order_prices_on_admin_ajax', 99, 3 );
I want to remove the price range that is shown for variable products in the WooCommerce site I'm working on. On non-product pages I want to replace it with "from: [lowest price]" and on the product page I'd like to replace it simply with the price of the selected variation.
Any ideas how I can get it working that way?
Thanks,
Darren
The best possible way to do what you want is that you change it on non-product page and remove it from product page. On product page when you select a variaion, its price and remaining stock is shown below the dropdown. So there is no need for you to show it above. If you still want to do it you will need a js solution.
Try this, this is tested solution. I have commented the cases for better guidance and changing if you want.
function sr_change_variable_price($price, $product)
{
if ( $product->is_type( 'variable' ) && !is_product() )
{
return 'From: '.$product->get_variation_price( 'min' ); // if variable product and non-product page
} else if ( $product->is_type( 'variable' ) && is_product() )
{
return ''; // if variable product and product page
} else
{
return $price; // other cases
}
}
add_filter( 'woocommerce_get_price_html', 'sr_change_variable_price', 10, 2 );
I've seen many examples of adding an item to the WC cart with a customer price, but none dynamically. I am trying to do in a shortcode function that receives a POST variables....
if (isset($_POST['wmnf_add_donation'])) {
global $woocommerce;
$cart_object = $woocommerce->cart;
$custom_price = ($_POST['donation_amount'] > 0 ? $_POST['donation_amount'] : 0);
$target_product_id = 65986;
$cart_object->add_to_cart($target_product_id, "1");
foreach ( $cart_object->cart_contents as $key => $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->price = $custom_price;
}
}
}
This adds the item to the cart of course, but the price is zero and I realize I need to somehow save this array back to the WC cart data. Is this method even possible or can it only be done via a filter or action hook? If so, how can I save the changed array back to the cart contents or make it work to add the one item with its posted price? Any guidance greatly appreciated.
Thanks for that answer doublesharp, I was not able to get it to work as described because the form was posting to the page with my shortcode, which has my form, instead of posting directly to the cart. The $_POST was not being seen and the product ended up zero. I did find another approach, but having a problem using wp_redirect. I changed the above shortcode to this:
if (isset($_POST['wmnf_add_donation'])) {
global $woocommerce;
$custom_price = ($_POST['donation_amount'] > 0 ? $_POST['donation_amount'] : 0);
$target_product_id = 65986;
$_SESSION['donation_amount'] = $custom_price;
$woocommerce->cart->add_to_cart($target_product_id, "1");
wp_redirect( site_url() . '/gifts/swag-bag/');
}
Then I added the following filters to functions.php:
add_filter('woocommerce_get_price','donation_price', 10, 2);
add_filter('woocommerce_get_regular_price','donation_price', 10, 2);
add_filter('woocommerce_get_sale_price','donation_price', 10, 2);
function donation_price($price, $productd){
if($productd->id == '65986'){
$price = $_SESSION['donation_amount'];
}
return $price;
}
This does not work except when wp_redirect is commented out, hence, not redirecting. The above redirects to the cart, but its empty. If I comment out the wp_redirect line and then manually go to the cart, the product is there with my custom price. Actually, I would like to apply a custom price and redirect directly to the checkout page instead of the cart, if possible?
You can use the woocommerce_before_calculate_totals action hook to modify the contents of the cart, including the product prices.
add_action( 'woocommerce_before_calculate_totals', 'before_calculate_totals' );
function before_calculate_totals( $_cart ){
// loop through the cart_contents
foreach ( $_cart->cart_contents as $cart_item_key => &$item ) {
// you will need to determine the product id you want to modify, only when the "donation_amount" is passed
if ( $item['id'] == 65986 && isset( $_POST['donation_amount'] ) ){
// custom price from POST
$custom_price = $_POST['donation_amount'] > 0 ? $_POST['donation_amount'] : 0;
// save to the cart data
$item['data']->price = $custom_price;
// new versions of WooCommerce may require (instead of line above)...
// $item['data']->set_price($custom_price);
}
}
}