-- Slot-level availability fact: one row per deduplicated available slot. -- Event grain: (snapshot_date, tenant_id, resource_id, slot_start_time). -- -- "Available" means the slot was NOT booked at capture time. -- Recheck-aware: for each (date, tenant, resource, start_time), prefer the -- latest recheck snapshot over the morning snapshot. If a slot was present -- in the morning but absent in the recheck, that means it was booked between -- snapshots — and it will simply not appear in this model (correct behaviour: -- unavailable slots are not in the available-slots fact). -- -- is_peak: convenience flag for 17:00–21:00 slots (main evening rush). -- Downstream models (fct_daily_availability) use this to avoid re-computing -- the peak window condition on every aggregation. MODEL ( name foundation.fct_availability_slot, kind FULL, cron '@daily', grain (snapshot_date, tenant_id, resource_id, slot_start_time) ); WITH deduped AS ( SELECT snapshot_date, tenant_id, resource_id, slot_start_time, price_amount, price_currency, snapshot_type, captured_at_utc, -- Prefer recheck over morning; within same snapshot_type prefer latest capture ROW_NUMBER() OVER ( PARTITION BY snapshot_date, tenant_id, resource_id, slot_start_time ORDER BY CASE WHEN snapshot_type = 'recheck' THEN 1 ELSE 2 END, captured_at_utc DESC ) AS rn FROM staging.stg_playtomic_availability WHERE price_amount IS NOT NULL AND price_amount > 0 ) SELECT snapshot_date, tenant_id, resource_id, slot_start_time, price_amount, price_currency, snapshot_type, captured_at_utc, ( slot_start_time::TIME >= '17:00:00' AND slot_start_time::TIME < '21:00:00' ) AS is_peak FROM deduped WHERE rn = 1