Skip to content

feat(place/booking_approver): optionally reject bookings for undefined assets - #643

Merged
w-le merged 1 commit into
masterfrom
feat/booking-approver
Oct 23, 2026
Merged

w-le merged 1 commit into
masterfrom
feat/booking-approver

Conversation

@w-le

@w-le w-le commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an optional mode to Place::BookingApprover that rejects bookings for assets that aren't defined in building zone metadata, instead of approving everything that matches the zone and type filters.

How it works

When reject_undefined_assets is enabled:

  • Caching. For each type in approve_booking_types, the driver collects the asset ids under metadata.<key>.details[].id from the level zones of every building (staff_api.metadata_children(building_id, key)). It stores them as a Set(String) per booking type.
    • The cache refreshes on bookable_assets_cache_cron (default 0 0 * * *, midnight, in time_zone if set) and once shortly after settings load.
  • Checking. On a create event that passes the existing zone and type filters, every asset on the booking must be in the cache.
    • If any asset is missing, the booking is rejected with utm_source: "booking_approval_driver".
    • Otherwise it's approved as before.

Safety

  • A failed cache refresh keeps the existing cache.
  • If a type's cache has never loaded, its bookings are neither approved nor rejected. The 10-minute missed-booking sweep retries them.
  • A type that loads with no assets defined rejects every booking of that type. This is intended.

New settings

reject_undefined_assets: false          # off by default, so existing behaviour is unchanged
bookable_assets_cache_cron: "0 0 * * *"
# time_zone: "Australia/Sydney"         # cron timezone; server local time if unset
asset_metadata_keys:                    # booking_type => zone metadata key ("<type>s" if missing)
  desk: desks
  parking: parking-spaces

Other changes

  • Already-rejected bookings are skipped, and the missed-booking sweep now queries with rejected: false. Without this, the sweep would re-reject the same bookings every 10 minutes. It also means the sweep no longer approves bookings that someone rejected manually, which it could do before.
  • status now also reports bookings_rejected and the number of cached assets per type. The cache size is exposed as the bookable_assets state key too.
  • Fixed @bookings_approved : Int32 = 0u32 (type mismatch) to = 0.

Testing

New booking_approver_spec.cr covers:

  • Mode off: undefined assets are still approved.
  • Caching: assets are cached across multiple buildings and levels, and entries without an id are skipped.
  • Approve/reject decisions:
    • Defined desk and parking bookings are approved.
    • These are rejected:
      • undefined assets
      • multi-asset bookings with one undefined asset
      • a desk id booked as parking
    • Already-approved bookings and unmonitored types are ignored.
  • Cache failures: a failed refresh keeps the cache, and nothing is rejected before the first successful load.
  • Empty metadata: every booking of that type is rejected.

The spec passes locally (Crystal 1.22.1, placeos-driver 8.1.7).

Known limitations (unchanged)

  • The 10-minute missed-booking sweep only queries the first entry in approve_booking_types.
  • It only searches this system's building.

🤖 Generated with Claude Code

…d assets

Adds a `reject_undefined_assets` mode. When enabled, the driver caches the
asset ids defined in the level zone metadata of every building (refreshed
on `bookable_assets_cache_cron`, default midnight) for each type in
`approve_booking_types`. New bookings whose assets aren't in the cache are
rejected; the rest are approved as before.

- booking_type => metadata key is configurable via `asset_metadata_keys`
- a failed refresh keeps the existing cache; bookings are never rejected
  before the cache has loaded
- already rejected bookings are skipped and excluded from the missed sweep
- adds a spec

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@w-le w-le self-assigned this Oct 23, 2026
@w-le
w-le requested a review from stakach October 23, 2026 10:39
@w-le

w-le commented Oct 23, 2026

Copy link
Copy Markdown
Contributor Author

Tested e2e OK on a UAT cluster

@w-le
w-le merged commit 45163e0 into master Oct 23, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant