wpovernight / woocommerce-pdf-invoices-packing-slips

Create, print & automatically email PDF invoices & packing slips for WooCommerce orders.
https://wordpress.org/plugins/woocommerce-pdf-invoices-packing-slips/
Other
99 stars 45 forks source link

WooCommerce Rental & Booking System discount not showing on invoice #788

Closed BrunoPavlinic98 closed 1 month ago

BrunoPavlinic98 commented 2 months ago

WooCommerce Rental & Booking System by RedQ Team is a plugin that manages rental and booking systems. If you create a new Rental product, you can go to the Price discount tab and set the discount for that product. I have tested that the user gets 10% discount if he rents the product for more than 3 days. Once the user rents something, the discount gets deducted from the total price, however, there is no discount shown on the invoice.

This plugin is not HPOS compatible!

BrunoPavlinic98 commented 2 months ago

This issue might be solvable using the following 2 hooks:

add_action( 'woocommerce_store_api_checkout_order_processed', function ( $order ) {
    $discount_total = 0;
    foreach ( $order->get_items() as $item_id => $item ) {
        $price_breakdown = $item->get_meta( 'rnb_price_breakdown' );
        if ( ! empty( $price_breakdown ) && isset( $price_breakdown['discount_total'] ) && 'redq_rental' === WC_Product_Factory::get_product_type( $item->get_product_id() ) ) {
            $discount_total += $price_breakdown['discount_total'];
        }
    }

    if ( 0 !== $discount_total ) {
        update_post_meta( $order->get_id(), '_redq_rental_order_discount', $discount_total );
    }

} , 10, 1 );

add_filter( 'wpo_wcpdf_woocommerce_totals', function( $totals, $order, $type ) {
    $new_totals = $totals;
    $discount = absint( $order->get_meta( '_redq_rental_order_discount' ) );
    if ( 0 !== $discount && isset( $totals['cart_subtotal'] ) ) {
        $subtotal = absint( $order->get_total() ) + $discount;
        $order->set_discount_total( $order->get_total_discount() + $discount );
        $new_totals = $order->get_order_item_totals();
        $new_totals['cart_subtotal']['value'] = wc_price( $subtotal );
    }
    return $new_totals;
}, 10, 3 );

The idea is to put a new meta data to the order after the order was placed in the checkout and put to the processing state(woocommerce_store_api_checkout_order_processed hook). The good thing is that RedQ placed rnb_price_breakdown meta to each order item, and therefore, we can sum them all and get the total discount, which can be saved to _redq_rental_order_discount order's meta data.

Then, the _redq_rental_order_discount order's meta data can be used by the wpo_wcpdf_woocommerce_totals hook in a way that it checks if the RedQ discount exists, and if yes, append that discount to already existing order discount and increase the order's subtotal by the RedQ discount value.

I tried this, and it works on my end.

@Terminator-Barbapapa @alexmigf @MohamadNateqi What do you think, should we first send this solution to the customer so that he can try it out and provide testing? If his tests are positive, we could consider adding this functionality to our PRO plugin, as a part of a compatibility with other plugins.

What do you think? And of course, feel free to provide code review for the provided snippets.

alexmigf commented 1 month ago

What are the order totals after the discount being applied? Can you show me the order items + totals from the order page?

Terminator-Barbapapa commented 1 month ago

@BrunoPavlinic98 If the discount is stored in the item meta I don't think we need to store it again in the order meta. We should be able to show it on the invoice with the currently available filters.

BrunoPavlinic98 commented 1 month ago

@alexmigf Here is the information you requested: The RedQ plugin's order info before confirming the order: Duration Cost 100,00 € Discount amount - 10,00 € Subtotal 90,00 € Grand Total 90,00 €

And the images from order backend and invoice: Capture Capture1

@Terminator-Barbapapa I think that this could work only with wpo_wcpdf_woocommerce_totals hook, without appending data to order meta. I will create a new snippet, and then, we can try to see if it will solve the issue.

BrunoPavlinic98 commented 1 month ago

@alexmigf @Terminator-Barbapapa Here is the new snippet:

add_filter( 'wpo_wcpdf_woocommerce_totals', function( $totals, $order, $type ) {
    $new_totals = $totals;

    $discount_total = 0;
    foreach ( $order->get_items() as $item_id => $item ) {
        $price_breakdown = $item->get_meta( 'rnb_price_breakdown' );
        if ( ! empty( $price_breakdown ) && isset( $price_breakdown['discount_total'] ) && 'redq_rental' === WC_Product_Factory::get_product_type( $item->get_product_id() ) ) {
            $discount_total += $price_breakdown['discount_total'];
        }
    }

    if ( 0 !== $discount_total && isset( $totals['cart_subtotal'] ) ) {
        $subtotal = absint( $order->get_total() ) + $discount_total;
        $order->set_discount_total( $order->get_total_discount() + $discount_total );
        $new_totals = $order->get_order_item_totals();
        $new_totals['cart_subtotal']['value'] = wc_price( $subtotal );
    }
    return $new_totals;
}, 10, 3 );

Works in the same way as with the two snippets.

BrunoPavlinic98 commented 1 month ago

I am closing this issue because it was fixed using custom snippets.