Zum Inhalt springen

How scheduling works

Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.

This page follows a pickup booking end to end: how the time slots are produced, how availability is enforced, what happens on submit, and where the chosen pickup shows up afterwards.

When a shopper selects Local Pickup at the classic checkout, Pickup renders a Pickup details block after the order notes: a location dropdown, a native date field, and a time dropdown. JavaScript shows the block the moment Local Pickup becomes the active method and hides it for any other method, but the block is always present in the page, so server-side validation applies even with JavaScript off.

The date field’s range is bounded: its min is today and its max is today plus your booking horizon, so the browser’s date picker cannot offer a date outside the bookable window.

2. Slots load for the chosen location and date

Section titled “2. Slots load for the chosen location and date”

Pick a location, then a date. The Pickup time dropdown reloads over AJAX (the pickup_slots action) and lists only the times that are genuinely bookable for that location and date. While it loads, an aria-live status announces “Loading times…”; if none are available it announces “No times available on this date.” The list also pre-renders on a posted-back page so a failed checkout keeps your selection.

Slots are built from your weekly opening hours and slot length:

A 09:00-12:00 window with a 30-minute slot length offers 09:00, 09:30, 10:00, 10:30 and 11:00 (11:30 is also offered when the window ends at 12:00, each start strictly before the end is included).

A generated slot is offered only if it survives three checks, applied in the store timezone:

  • Lead time, slots earlier than “now + lead-time hours” are dropped, so a customer cannot book one minutes from now when staff need notice.
  • Booking horizon, only dates within “today + horizon days” are generated.
  • Capacity, Pickup counts existing orders holding that exact location + date + slot (across the pending, processing, on-hold and completed states); once the count reaches your per-slot capacity, the slot is dropped. Two customers therefore cannot book past a slot’s capacity, there is no double-booking.

Because the count is read from order meta at checkout, there is no queue, cron or custom table to maintain. (Note the capacity count does not reserve a slot during checkout, so under heavy simultaneous load two shoppers could in theory both pass the check for the last spot; the server re-validates on submit but does not lock.)

When the order is placed, Pickup re-runs the checks server-side: it verifies the nonce, confirms the location exists and is enabled, requires a non-empty date and slot, and confirms the slot is still bookable in the live schedule. Any failure adds a WooCommerce checkout error and blocks the order, so the data saved is always trustworthy. This runs only when Local Pickup is the chosen method; otherwise it is skipped.

Once saved, the chosen location and “when” (date in your WordPress date format, plus the slot time) appear:

  • on the admin order screen, in a Pickup box after the shipping address (HPOS and legacy);
  • on the customer’s order details / thank-you page;
  • in order emails, in both the HTML and plain-text variants.

The location’s name is snapshotted onto the order at checkout, so these surfaces stay correct even if the location is later renamed or removed.

Pickup places its fields through WooCommerce checkout hooks (woocommerce_after_order_notes) and its order display through standard WooCommerce order/email hooks. There are no shortcodes and no template to copy, placement is automatic and not configurable.

Every field has a real <label> and is marked required with an abbr. The time dropdown and its status text sit in aria-live="polite" regions, so screen-reader users hear “Loading times…”, the result, or an error without losing focus. The checkout script is dependency-free vanilla JavaScript, loaded defer, and re-binds itself after WooCommerce’s updated_checkout AJAX refresh.