checkGroupCapAfterDurationChange(eventId: number,groupId: number): Promise<string | null>
After a duration change on a grouped event, check whether any day in any existing booking's new range now exceeds the group cap. Returns the earliest over-capacity day, or null if everything fits. Call AFTER recomputeEventBookingRanges so end_at is already updated.
One query fetches every booking row in the group; per-day occupancy is computed in JS with a boundary sweep. Occupancy only changes on days where some booking starts, so checking interval start days that fall inside this event's booked ranges finds the earliest overflow without walking (and querying) every day of every range.