3

So, my website involves a booking system and the flow looks like this:

  1. Guest selects dates for booking a product (location).
  2. Upon submitting the request, a message is sent to the host for review.
  3. If accepted, I want the order to be payed by the guest. // my issues are here

I have successfully created orders. Ideally, I'd like to be able to send the guest to their "Cart" page, with the booking order they placed (ONLY AFTER, the host has approved the booking). This way, everything can be handled by WooCommerce except the initial ACCEPT or DECLINE by the host.

Question:

  1. Do I need to add the order to the user's cart when this process starts (step 1)? If so, how do I disable payment until the host has approved the order?

Code:

On the initial booking page:

$y_booking_order = wc_create_order();
$y_booking_order->add_product( get_product( $san_y_id ), $san_num_days);
$y_booking_order->calculate_totals();
$y_booking_order->update_status('on-hold');
update_post_meta($y_booking_order->id, '_arrival_date', $san_date_arr);
update_post_meta($y_booking_order->id, '_departure_date', $san_date_dep);
update_post_meta($y_booking_order->id, '_request_sender', $san_user_id);
update_post_meta($y_booking_order->id, '_customer_user', get_current_user_id());
// do I add to cart here? If so, how to stop guest from paying until after host approves?

So far, once the order is created, I'm just letting the host change the status of the order from 'on-hold' to 'pending'. Now I just want to let the guest pay...

Thoughts?

Kaji
  • 2,220
  • 6
  • 30
  • 45
Daltron
  • 1,729
  • 3
  • 20
  • 37

1 Answers1

2

If you're not collecting a pre-authorization of some sort, 'pending' is where the status should be.

As far as sending out the invoice goes, digging through WooCommerce's code and reorganizing it a bit to trim the fat yields the following function, which should allow you to programmatically send out an invoice e-mail in the same manner as if you had told it to send the invoice from the menu when editing the order:

function send_invoice_email($post_id) {
    $order = wc_get_order($post_id);

    wc_switch_to_site_locale();

    do_action('woocommerce_before_resend_order_emails', $order);

    // Ensure gateways are loaded in case they need to insert data into the emails.
    WC()->payment_gateways();
    WC()->shipping();

    // Load mailer.
    $mailer = WC()->mailer();
    $email_to_send = 'customer_invoice';
    $mails = $mailer->get_emails();

    if (!empty($mails)) {
        foreach ($mails as $mail) {
            if ($mail->id == $email_to_send) {
                $mail->trigger($order->get_id(), $order);
                $order->add_order_note( sprintf( __('%s email notification manually sent.', 'woocommerce'), $mail->title), false, true);
            }
        }
    }

    do_action('woocommerce_after_resend_order_email', $order, $email_to_send);

    wc_restore_locale();
}
Kaji
  • 2,220
  • 6
  • 30
  • 45
  • 1
    Thank you for this piece of code, it works perfectly, also could you elaborate why do_action('woocommerce_before_resend_order_emails', $order); and do_action('woocommerce_after_resend_order_email', $order, $email_to_send); is used? I commented out these lines of code and it still works as expected. So not sure why it is needed here? And also why it's needed to loop through mails? I see that it is possible to get customer_invoice by accessing a particular key in the array, so not sure if looping through emails is intentional here. Thanks for your work :) – Erasus Nov 20 '20 at 00:21
  • @Erasus Glad you found it useful! I'm revisiting this 3 years after I posted it, but from what I recall I trimmed this code from the part in WooCommerce where the invoice gets sent out when you perform the "Send Invoice" order action from the order view on the back end. – Kaji Nov 21 '20 at 12:09
  • 1
    More specifically, the `do_action()` calls are being kept here to ensure that any action hooks tied to sending these e-mails get run (e.g. tracking that the e-mails were sent, plugin actions tied to sending the invoices out, etc.). The safest method is to leave these calls in here and then if there are actions you don't want being performed alongside sending the e-mails you can review what's getting run with a plugin like Query Monitor and run `remove_action()` and `add_action()` to remove and re-hook the actions so they don't run when you're doing your special call to send out the invoices. – Kaji Nov 21 '20 at 12:12
  • 1
    That makes total sense now :) Thank you so much for the clarification, I was actually thinking similarly, the way you described it works but wasn't sure enough. – Erasus Nov 22 '20 at 14:23