Bypass all resource restrictions, passwords, and keys? Read here!
BookingWP WooCommerce Appointments v5.4.4 Nulled
= [5.4.4] - July 27, 2026
1 improvement · 2 fixes — Product Add-ons integration, Admin calendarImprovement
- PHPStan raised to level 5 — type narrowing, expanded plugin and WordPress stubs, and dead-code cleanup across admin, data stores, API, GCal, and integrations (clean baseline).
Fixes
- Product Add-ons integration: decode jQuery .serialize() form payloads with wp_unslash() before parse_str() in legacy cost filter.
- Admin calendar: guest customer labels on HPOS stores read billing from wc_order_addresses (not legacy _billing_* order meta), restoring "Name (Guest)" on calendar preload and SSE updates.
BookingWP WooCommerce Appointments v5.4.3 Nulled
= [5.4.3] - July 26, 2026
9 improvements · 10 fixes — Admin calendar, ICS export, Admin calendar preload, PHPCS, +10 moreImprovements
- Admin calendar preload: eligible-ID query plus batched postmeta hydration; batched order meta (no per-order WC_Order hydration). Recurring series package summary on bulk fetch (get_panel_preload, one load per series id); full appointment panel still loads on open.
- PHPCS: WPCS security ruleset (phpcs.security.ruleset.xml, npm run lint
hp:security), shared path rulesets and request helpers; lint
hp / build gate runs security scan + PHPStan; optional lint
hp:standards / lint
hp:quality; PHP-CS-Fixer via format
hp.
- PHPStan raised to level 4 — dead-code cleanup across admin, slots, API, GCal, and core (clean baseline).
- Rate limiting: filterable enabled, guest_only, and strict_max_requests; named guest-read defaults on WC_Appointments_Rate_Limiter.
- Tests: PublicAjaxSecurityLiveTest, PhpstanLevel4RegressionLiveTest, IcsExporterStaleEntryRegressionLiveTest, MyAccountRescheduleContractLiveTest, CalendarPreloadParityLiveTest (calendar preload vs independent eligibility SQL; non-UTC and all-day; attribute term labels), RequestBoundaryRegressionLiveTest, SanitizerBeforeParseGuardTest, and SseTopicContractVerificationTest (request transport boundaries, PHP/JS SSE topic contract, FC week/day header zone).
- WC_Product_Appointment_Rule_Manager::get_minutes_from_rules() remains as a compatibility shim; use WC_Appointment_Slots_Rule_Resolver::build_minute_mask() instead.
- Admin panel: remove Cancel from create/edit footer (close via X / backdrop).
- Admin calendar: Google-style grid (horizontal week lines only in month, stacked week/day headers, centered month dates); neutral toolbar chrome (admin body text/borders), segmented view switcher, primary + Add New beside Filters (icon-only; label on hover/aria).
- ICS export: log a warning when unloadable entries are skipped (WooCommerce → Status → Logs).
Fixes
- Admin calendar: toolbar spans full wrap width below Screen Options/Help; staff without WooCommerce header get Add New in the toolbar; staff/creator filter uses EXISTS (not INNER JOINs); Fake UTC civil preload range and YmdHis row parsing (not strtotime); shared excluded-status list (cancelled visible; holds/trash/drafts hidden) on SQL query, legacy API, and frontend; orphan/deleted post_parent order IDs pre-filtered before batch order load; availability rule background stripes reload when switching months.
- REST API: appointments get_item_schema() extends the parent schema instead of starting from null.
- Security: sanitize/unslash POST/GET at origin across storefront AJAX, data stores, cart, SSE, cron, widget, admin (AJAX, settings, calendar, list table, exporters, meta boxes, product edit), WPML, Google Calendar, and integrations; prepared SQL for lookups and migrations; escape output in admin views; guest-only rate limit preserved for cached pages with optional nonces.
- Storefront/admin AJAX: parse jQuery .serialize() form payloads before per-field sanitization (not sanitize_text_field() on the encoded string — destroys %XX sequences for timezones, times, and add-on text).
- SSE: preserve dotted event names (appointment.created) in the stream; sanitize_key() stripped dots and broke admin calendar live updates.
- Availability rules JSON: decode unslashed payloads first (callers pass wp_unslash( $_POST )); double-unslash broke rule titles containing quotes.
- Admin calendar: week/day column headers use browser-local date (not UTC parts); legacy week/day data-time and calendar_day= links use site timezone (not gmdate); batched order line item meta resolves global attribute term names (not raw slugs) in the appointment panel.
- Add Appointment and My Account series actions: read REQUEST_METHOD from $_SERVER (not filter_input( INPUT_SERVER ), unreliable under some SAPIs).
- Legacy install migration: delete product availability post meta by key after table migration (not a single rule value).
- ICS export: skip unloadable appointment entries so stale IDs do not fatal calendar generation.
BookingWP WooCommerce Appointments v5.4.2 Nulled
2026.07.18 - version 5.4.2
* Dev - PHPStan raised to level 3 (phpVersion 7.4).
* Dev - Tests: regression coverage for range_type RRULE routing parity and orphan `rrule` field cleanup.
* Dev - Tests: lock GCal failure-path contracts (`make_gcal_request()` → `WP_Error`, `sync_event_resource()` → `false`) and rule-minutes payload shape across all `compute_rule_minutes()` branches.
* Fix - Indexed availability: RRULE expansion follows `range_type` (same as dynamic); orphan `rrule` on non-`rrule` rules uses the non-RRULE path and purges legacy expand rows on background passes.
* Fix - Google Calendar: inbound sync clears `rrule` when an event is stored as non-recurring (`custom` / `custom:daterange`).
BookingWP WooCommerce Appointments v5.4.1 Nulled
[5.4.1] - July 16, 2026
5 improvements · 5 fixes — Orders, Indexed availability, PHPStan, Storefront calendar, +3 moreImprovements
- PHPStan: level 2 with a clean baseline — expanded plugin and integration stubs plus PHPDoc/type fixes across core.
- Indexed availability: occupancy reads from appointment cache when healthy (live fallback during backfill; in-cart recurring holds merged); backfill batches gap-only missing appointments.
- Storefront calendar: data-engine reports rules/occupancy source (1 indexed, 2 dynamic, 3 indexed + appointment cache).
- Orders: get_appointment_ids_from_order_and_item_id() deprecated — use get_appointment_ids_from_order_item_id( $order_item_id, true, $order_id ).
- Orders: get_appointment_ids_from_order_item_id() triggers wc_doing_it_wrong when $order_id is omitted (except opt-in order-line _appointment_id cache).
Fixes
- Indexed availability: weekday time:N rules count only matching days; re-enable no longer wipes inline indexing; backfill pending flag clears/re-queues stale jobs and stops on zero-gap batches.
- Google Calendar: scheduled sync is forward-only unless admin full re-sync; inbound sync skips stale events (event ID / site_url mismatch).
- Availability / slots: overlap day keys use Fake UTC civil midnight so 00:00 wall slots stay on the correct day on negative-offset stores.
- Orders: order-scoped line-item lookup ($order_id on get_appointment_ids_from_order_item_id) — orphaned _appointment_order_item_id no longer shows another customer’s appointment; line delete clears the link before ID reuse.
- Cart: session load removes holds tied to terminal orders or past start dates and releases in-cart appointments to was-in-cart.
BookingWP WooCommerce Appointments v5.3.12 Nulled
*** WooCommerce Appointments Changelog ***
2026.07.10 - version 5.4.0
* Improvement - Settings → Indexing: combined section intro with scannable structure (benefit, when to use, warning, maintenance).
* Improvement - Pricing: `calculate_appointment_cost()` can skip `is_appointable()` for display-only quotes — post `wc_appointments_field_quote_only` or filter `woocommerce_appointments_calculate_cost_validate_appointable`; add-to-cart still validates separately.
* Performance - Removed ~1 MB of unused Moment.js from storefront scripts.
* Dev - PHPStan: third-party and WP-CLI stubs, admin include `@var` docblocks, Sprint 5–6 cleanup — baseline cleared (0 suppressed errors).
* Fix - REST API: allowlist availability `filter` column keys before SQL (closes unauthenticated injection on public `/availabilities`).
* Fix - Storefront timezone **Default**: persist site-timezone choice via `appointments_use_site_timezone` (not a fixed IANA string); custom zones still use `appointments_time_zone`; first visit uses timezone AJAX.
* Fix - Availability / slots: past-date guard uses Fake UTC civil day (`gmdate`, not `wp_date`) for minute/hour tokens; day/month posts omit `_time` so same-day all-day add-to-cart is not rejected after midnight; legacy timed data stores the same Fake UTC instant as listed slots.
* Fix - Availability rules: initialize `$rule_val` each iteration; `offsetSet( 'id', … )` assigns the posted id (was parameterless `set_id()`).
* Fix - Pricing: multi-day day-unit totals sum each civil day in the span (checkout uses same per-day engine as slot preview; PAO duration flat prices skipped when already billed per day).
* Improvement - Recurring package footer: single cost summary list (no duplicate Total/Due today on prepaid); session count under the hero price; deposits excluded from package preview (matches admin). Series preview summary no longer returns deprecated `checkout_footer_html` (use `total_price_html` only).
* Fix - Per-day inventory: in-cart recurring `session_starts` occupancy included when marking civil days sold out (calendar/conflict checks match slots overlap index).
* Fix - Storefront: unavailable `?time=HHMM` shows selected time with "(Selected time is unavailable)" instead of auto-picking first slot.
* Fix - Admin add appointment: reject missing posted date before parsing year/month/day.
* Fix - Admin panel: create panel anchors beside the calendar slot when **Add New Appointment** is opened first and a date/time is picked afterward (clear centered mode on calendar trigger).
* Fix - Admin product staff panel: fix assign-staff AJAX scope (`$staff_base_cost`, `$staff_qty`) and staff view `self::` call (`WC_Appointments_Admin::get_appointment_staff()`).
* Fix - Google Calendar: sync errors log exception messages; HTTP backoff returns explicit error when retry loop exits without a response.
* Fix - Partial refunds: each reduced-qty appointment keeps the correct per-line-item `$remaining_qty`.
* Fix - Series My Account: invalid action redirect no longer leaves `$result` / `$notice` undefined.
* Fix - Helpers: remove undefined `$gmt_offset` / `$cart_item` reads in `wc_appointment_get_timezone_offset()` and `wc_appointment_pretty_addon_duration()`.
* Fix - Privacy: exporter registration returns exporters array from `register_exporters()`.
* Fix - CRM integration: initialize note strings before appending comment HTML.
* Fix - Webtomizer deposits: check `$appointment_ids` array before updating partial-payment status.
* Fix - Product Vendors integration: declare `global $wp_roles` before role cap setup.
* Fix - Follow-Up Emails: pass `null` appointment to variable-replacement filter when queue item has no appointment context.
* Fix - Admin calendar: server preload always spans prev/current/next month grids regardless of default view (day/week/month/list), so switching views serves preloaded appointments instantly instead of refetching via REST.
* Fix - Availability rules: priority input fills column width on global (Settings → Appointments) and staff availability tables (site and synced tabs).
BookingWP WooCommerce Appointments v5.3.11 Nulled
= [5.3.11] - June 9, 2026
Latest
Fixes
- Twilio SMS integration: restore hook registration removed in 5.1.0 (Appointments SMS settings, scheduling, and notifications with WooCommerce Twilio SMS Notifications 1.12+); {appointment_date} / time tokens use get_start_date() / get_end_date() so all-day civil dates match emails and order summary on non-UTC stores.
- All-day (day/month duration) appointments after checkout: order summary, emails, and My Account show the same civil date as cart/checkout — get_start_date() / get_end_date() and email formatters use Fake UTC civil digits (gmdate + date_i18n) instead of wp_date() on stored midnight tokens, which shifted the calendar day on non-UTC site timezones.
- All-day bookings: _local_timezone is written only for timed products in wc_appointments_get_posted_data(); WC_Appointment::set_all_day() / set_local_timezone() and the data store drop customer TZ meta on all-day saves — civil dates stay timezone-agnostic without per-caller guards.
BookingWP WooCommerce Appointments v5.3.10 Nulled
=[5.3.10] - June 2, 2026
Latest
Fixes
- Storefront appointment cost quote when catalog prices are entered inclusive of tax: footer HTML uses the same display amount as AJAX raw_price (not tax-stripped line_net), so logged-out customers see the correct gross total.
- Availability / add-to-cart: day- and month-unit checks use Fake UTC civil tokens (gmdate / shared slot-token helpers) for past-date guards, span end calculation, and day-slot capacity keys — not wp_date() / site-TZ DateTime on the posted timestamp — so same-day bookings and slot lookup stay aligned on non-UTC stores (e.g. America/Vancouver).
- Storefront calendar (no staff preference, day/month + staff): multi-staff indexed slot generation no longer runs the minute-mask loop on day/month products — use per-staff civil-day slots and union merge instead; no-preference day summary uses per-staff OR (max), not summed slot counts across merged fragments.
- Admin panel create: day/month availability check and save use Fake UTC civil midnights for date/month ranges (matches storefront slots and get_day_civil_span_capacity keys); admin month calendar bounds for day/month products use the same civil UTC axis.
- is_appointable() past-date guard for day/month products uses wc_appointments_is_past_request_date() (Fake UTC civil axis) instead of date() on _date, matching availability checks.
- Admin panel create success message formats saved day/month ranges from appointment timestamps via wp_date() (not strtotime() on date strings).
BookingWP WooCommerce Appointments v5.3.9 Nulled
= [5.3.9] - May 25, 2026
Latest
Improvements
- Improved admin panel styling with bigger input selection.
- Admin panel create/edit: datetime row shows a loading state while product details, first-available auto-pick, day slots, or availability AJAX run; success/error only after the check completes.
- Admin panel create: first-available auto-pick scans the bookable horizon in 14-day chunks and stops at the first slot instead of loading the full range up front.
Fixes
- Admin panel create: availability no longer flashes loading twice or clears to blank before first-available prefill; date-only calendar prefill waits for day slots before checking; browse does not re-open after the user closes it during the same unavailable episode.
- Admin panel: datetime loading no longer sticks when day-slot AJAX fails or returns empty, when a superseded availability request aborts, or while bootstrap waits only on an in-flight slots request (not missing cached data).
- Slots / day & month products: timed global RRULE blocks (e.g. weekly Tue 4–6pm) block the whole civil day again — date-level checks use RRULE occurrence expansion, not midnight-only overlap, so higher-priority global rules override product day rules (RuleMinutesRruleCivilDayTest).
- Admin panel browse: slot chips show remaining capacity (e.g. 1 available) on multi-capacity products when only one place is left, not only when two or more remain.
- Slots: dynamic availability (indexing off) paints full half-open unappointable ranges on the minute mask — priority blocks no longer leave appointable boundary minutes (e.g. 10:00–11:00 block showing 10:59 slots); matches indexed mask painting.
- Slots / calendars: minute/hour bookings that start at site midnight (including long durations such as 12 hours) block capacity again — timed overlap day-keys use Fake UTC site civil buckets for both occupancy indexing and slot lookup instead of mixing wp_date() site midnight with the civil UTC-midnight fast path.
- Slots / calendars: multi-day day-unit occupancy for admin-created (site-local midnight) bookings — civil overlap keys use the site calendar date (Fake UTC) so every booked day blocks correctly (e.g. June 4–5 for a 2-day booking starting June 4); wc_appointments_get_posted_data() stores matching Fake UTC start/end for new day/month appointments.
- Slots / calendars: multi-day day-unit products block every booked civil day again — occupancy uses live appointments; overlap day-keys use timezone-agnostic civil dates (gmdate on stored tokens), matching slot tokens, not wp_date() site-local midnight.
- Admin panel create: first available date/time via one AJAX call (WC_Appointment_Slots_Provider::get_first_available_slot, same as storefront), including when the first slot is outside the current month; calendar day click/drag date-only prefill auto-picks the first time or opens browse once with noSlotsOnDateSelect when that day has no slots; browse auto-opens only on unavailable validation (not during silent auto-pick) and stays dismissible (no immediate re-open after close until date or product changes); live preview placeholder while slots load; panel expands when the product form is ready.
- Slots / calendars: minute/hour day availability (storefront day_data, admin mini-calendar, time-slot lists) counts only bookable slot starts via shared WC_Appointment_Slots_Collection::slots_for_day_summary() on the same get_collection() engine — fully booked days no longer stay selectable when only sub-duration engine segments remain.
- Slots / time picker: Availability check → The starting slot only no longer lists grid starts in appointable fragments shorter than the booking duration (phantom evening slots such as 19:00 on 12h/12h products when the index leaves a tail after a gap); full-day ranges still allow starts when duration exceeds the window (e.g. 25h in 24h).
- Checkout validation (WC_Appointment_Cart_Manager::validate_appointment_order): re-validates cart slots via WC_Appointments_Controller::get_indexed_total_available_for_range() (same slot_matches_requested_range tolerance as add-to-cart) instead of strict start_ts equality; all staff together uses staff id 0 fan-out like is_appointable(); in-cart holds are excluded from overlap during the check.
- Staff all together: cart booking no longer collapses multi-staff _staff_ids to a single _staff_id during WC_Appointment_Booking_Handler::create_appointment() availability merge.
- Admin panel: WooCommerce Deposits on create — calculate_costs / create_appointment honour deposit choice and tax display (incl./excl. catalog); deposit footer quote and order item meta (_deposit_full_amount, etc.) match storefront; pay-deposit hides footer price edit (product deposit rules); pay-in-full edits full service price via raw_full_price; mistaken deposit-only overrides corrected on save.
BookingWP WooCommerce Appointments v5.3.8 Nulled
= [5.3.8] - May 8, 2026
Feature
- WooCommerce block email editor support for appointment transactional emails (synced block templates under templates/emails/block/, hook-driven parts under templates/emails/parts/, personalization tags, preview context, admin styles).
Improvements
- Date picker default date uses WC_Appointment_Slots_Provider::get_first_available_slot() which leverages Collection day summaries to skip unavailable days. Complexity reduced from O(all_slots) to O(days + slots_in_first_available_day).
- WC_Product_Appointment::get_first_available_slot() and get_slots_in_range_lazy() (and private get_slots_lazy_by_duration / get_slots_in_range_for_*_lazy helpers) removed; use WC_Appointment_Slots_Provider::get_first_available_slot().
- Removed deprecated dead code with no external calls: 11 methods from WC_Appointments_Controller (deprecated 2.4.9–4.7.0), 5 functions from wc-appointments-functions.php (deprecated 1.15.0–5.1.0), and 3 methods from WC_Appointment (deprecated 4.2.0–5.3.8). Deprecated code still in use internally was retained.
- Removed deprecated dead code from WC_Product_Appointment: get_time_slots(), get_time_slots_html(), get_slots_availability(), get_all_staff_availability(), get_min_timestamp_for_date(), get_available_appointments(), get_appointments_in_date_range(), get_unavailable_minutes(), get_minutes_from_rules(), get_available_slots(), get_slots_in_range(), get_slots_in_range_for_day(), get_slots_in_range_for_month(), get_slots_in_range_for_hour_or_minutes(), get_appointable_minute_start_and_end(), get_appointable_minute_slots_for_date(), get_max_allowed_date_into_the_future()
- Removed deprecated dead code from WC_Appointment_Slots_Legacy_Adapter: get_time_slots(), get_available_slots()
- Admin appointment panel (wcaPanel): localized incl./excl. tax short labels from WooCommerce; footer cost hint and add-on section respect wc_prices_include_tax() and whether tax is enabled; AJAX posts (wc_appointments_panel_cost_excl_tax, add-on incl./excl. flags, override excl. flag) only when the catalog is exclusive so net/gross semantics stay consistent.
- Product Add-Ons integration: panel AJAX uses filters so admin add-on price display and suffix follow the same inclusive/exclusive catalog basis as the appointment panel.
- Admin appointment block templates: admin edit link uses the same printf( esc_html__( … ), '<!--[tag]-->' ) pattern as WooCommerce core block emails (e.g. store email / customer name in default content).
- Update translations (+19 new strings).
Fixes
- Admin product Custom availability rows (html-appointment-availability-fields.php): date/time display no longer converts using get_staff_timezone( get_current_user_id() ), which applied the viewing user’s saved appointment timezone to everyone (including administrators). Uses WC_Appointments_Timezone_Helper::get_admin_user_timezone() so store admins and shop managers see site wall times; staff-only users still see their profile timezone. Google/RRule summary only treats kind_id as a staff user when the rule kind is availability#staff (not product/global kind_id).
- Admin user profiles now show a single appointment timezone selector for all users. Staff profiles use the shared field while keeping the staff profile navigation section and enhanced searchable timezone picker.
- Indexed availability: manual Re-index no longer raises per-rule limits so high (e.g. thousands of RRULE occurrences or a full year of days in one pass) that a single AJAX chunk could hit browser/proxy timeouts despite batching. WC_Appointments_Cache_Availability::run_rule_index_pass() uses modest multiples of the normal per-pass caps; rules that still need more work are re-scheduled as before.
- Unified slots when a specific staff is selected: WC_Appointment_Slots_Rule_Resolver::build_minute_mask (dynamic rules) and WC_Appointment_Slots_Data_Normalizer::build_minute_mask_from_index_rows (indexed cache) now apply matching staff-scope rows inline on the main minute mask in sorted override order, instead of replacing the mask with a staff snapshot that could resurrect minutes a higher-priority global/product not available row had already cleared. Rule priority vs. staff overrides now match between indexing on and off.
- Indexed full-day row types days / months / weeks: minute-mask painting clamps the day span at 1440 minutes (end of civil day) so the mask tail past midnight is not left appointable from index timestamps; avoids rule-blocked calendar days appearing clickable when availability indexing is enabled.
- Legacy storefront calendar payload (WC_Appointment_Slots_Legacy_Adapter::collection_to_scheduled_days): days with unavailable status are also copied into fully_scheduled_days for the same date keys, because date-picker.js treats fully_scheduled_days as non-clickable; rule-only unavailability no longer leaves those days selectable when the modern day_data path already marks them closed.
- Admin appointment panel: create success schedule line uses store date/time formats (wc_appointments_date_format / wc_appointments_time_format); when the acting user’s admin timezone differs from the site, text is derived from start/end timestamps via wc_appointment_timezone_locale so it matches the times they picked. Timezone context uses abbr.wc-appointments-tz-abbr beside the line (same pattern as the edit panel When row), not parenthetical suffix text.
- Admin appointment panel edit mode: footer no longer shows a live-calculated price (slot/product rules); it could disagree with view-mode order line totals, and cost is not editable there. View mode still shows pricing from the order.
- Admin appointment panel: create submit sends wc_appointments_field_start_date_timestamp when a slot is selected so server cost matches the footer (fixes line total 0 when the price field was never focused). Order line total always adds Product Add-Ons to the appointment base; price override prefills/commit uses appointment base only (footer raw minus addon cost) so add-ons still apply after touching the price input.
- REST GET wc-appointments/v2/appointments/{id}: embedded order_info now matches calendar batch order payloads—each line item includes subtotal_tax / total_tax, and the order includes total_tax, discount_tax, and coupon_lines. The admin appointment view panel Cost/Tax row uses these fields on first open; previously they were omitted so Tax could appear only after closing and reopening (calendar-loaded appointments already had the fuller shape).
- Admin manual appointment creation when WooCommerce prices are entered inclusive of tax: AJAX cost display and order line totals align with the inclusive/exclusive catalog basis (appointment base + Product Add-Ons as one tax-aware bundle on the line so calculate_totals() does not stack VAT on top of tax-inclusive amounts).
Decryption key:
BookingWP WooCommerce Appointments v5.3.7 Nulled
= [5.3.7] - April 29, 2026
Latest
Improvements
- Admin calendar: on expired nonce/session (REST 401/403), show an expiry banner with reload link instead of failing silently after long idle periods.
- Admin appointment panel: create/edit success step uses a light success-tinted circular badge for the checkmark (aligned with other success affordances), not a plain large icon.
- Update translations (+2 strings, −11 strings removed).
- Removed deprecated per-product customer_timezones; timezone support is site-wide. has_timezones() now reads wc_appointments_timezone_support_enabled (default true). Removed get_customer_timezones / set_customer_timezones, related data store mapping, admin and REST fields, and WCML/Polylang sync for that setting.
Fixes
- Admin timezone display: appointments_time_zone cookie no longer applies in admin/REST. Only staff (providers) may use profile timezone in admin; admins and shop managers always see site timezone. Remote staff can still set profile timezone.
- Admin create flow, existing order: order number no longer appears twice in Select2 and the selected chip—both prefixed # + internal ID onto labels that already included the display order number.
- Legacy calendar staff view: staffed appointments no longer also list under Unassigned—$is_creator matched creator_id === 0 because (int) 'unassigned' === 0; creator shortcut now requires non-zero creator_id.
- Manual appointment on existing order (admin AJAX): line meta used public appointment_id, so emails/item meta showed an extra row. New rows use _appointment_id only (checkout parity); formatted order item meta strips legacy public appointment_id for display.
- Admin browse day slots: discounted price.display (<del> / <ins>
was React-escaped; .wca-slot-price now renders with dangerouslySetInnerHTML (same as panel footer).
- Recurring time:range: same-day windows ending at 00:00 were misclassified as overnight (string order: 00:00 < 08:00, 24:00 < 08:00). WC_Product_Appointment_Rule_Manager / WC_Appointment_Slots_Rule_Minutes now use minute-based wrap helpers (is_wrap_midnight_hhmm_pair / is_wrap_midnight_time_pair); evaluate_rule_for_timestamp shares the same bounds. Availability cache indexing aligns with slot rules for 00:00 end-of-day, maps 24:00 → 1440, and sets same-day eff_to_min = 1440 when needed. time:range overnight at midnight merges evening (from–24:00) with morning (00:00–to) when the prior day is in range (RuleMinutesMidnightWrapTest).
- Unified slots + woocommerce_appointments_slots_display_pricing: WC_Appointment_Slots_Pricing::compute_slot_price_raw() returns the full filtered slot price when the filter runs (not only when below default). WC_Appointment_Slots_Collection::serialize_slots() writes price_data.display / price_formatted HTML; the lazy formatter had read a non-array price from jsonSerialize(), so strikethrough/sale never reached unified JSON.
- Availability rules: changing range_type (e.g. Date range with time → Days) clears unused from_date / to_date via apply_json_rule_to_availability() (time:range, custom:daterange, store_availability still keep dates), so weekly/monthly rules are not skewed by stale columns.
- Indexed availability cache: indexer ignores stray from_date / to_date on days, months, weeks (same as recurring time / time:N), so corrupt rows no longer shrink the cache window until re-saved.
- Admin appointment save (WC_Appointment_Meta_Box_Data::meta_box_save): failed start/end validation now sets self::$saved_meta_box before return (matches success path), avoiding duplicate admin errors or extra save_post work in the same request.
- Day-unit products when add-ons (or appointment_form_posted_total_duration) extend past base duration: WC_Appointments_Controller::get_exact_available_capacity_for_slot() no longer uses the multi-day “start row only” shortcut (it skipped later days) or get_extended_range_available_capacity() for that span (UTC civil-day mismatch caused false unavailability). Added get_addon_extended_day_span_capacity() (same UTC keys as get_multi_day_available_capacity(), min capacity across span days). Minute/hour add-on extension unchanged.