diff --git a/OPENAPI_DOC.yml b/OPENAPI_DOC.yml index 3413ffec..2d29e73e 100644 --- a/OPENAPI_DOC.yml +++ b/OPENAPI_DOC.yml @@ -6481,38 +6481,22 @@ paths: will return a list of system_ids that are already booked during the specified time range - if system_ids is set, then it will only return booked systems from that list' + if system_id is set on the event, then it will only return booked systems + from that list' tags: - Events operationId: Events_clashing_assets - parameters: - - name: period_start - in: query - description: event period start as a unix epoch - example: "1661725146" - required: true - schema: - type: integer - format: Int64 - - name: period_end - in: query - description: event period end as a unix epoch - example: "1661743123" + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/PlaceCalendar__Event' required: true - schema: - type: integer - format: Int64 - - name: system_ids - in: query - description: comma separated list of system_ids to check for clashes - example: sys-1234,sys-5678 - schema: - type: string - nullable: true + parameters: - name: return_available in: query - description: return available systems, this requires system_ids be set to - the full list + description: return available systems, this requires system_id be set on the + event example: "false" schema: type: boolean diff --git a/spec/controllers/events_spec.cr b/spec/controllers/events_spec.cr index c94b6d32..81797e79 100644 --- a/spec/controllers/events_spec.cr +++ b/spec/controllers/events_spec.cr @@ -1348,9 +1348,18 @@ describe Events, tags: ["event"] do EventMetadatasHelper.create_event(tenant.id, system_id: "sys-5678", event_start: event_start + 5, event_end: event_end + 5) EventMetadatasHelper.create_event(tenant.id, system_id: "sys-9999", event_start: event_end + 100, event_end: event_end + 200) + clashing_event_body = { + event_start: event_start, + event_end: event_end, + attendees: [] of String, + private: false, + all_day: false, + }.to_json + response = client.post( - "#{EVENTS_BASE}/clashing-assets?period_start=#{event_start}&period_end=#{event_end}", - headers: headers + "#{EVENTS_BASE}/clashing-assets", + headers: headers, + body: clashing_event_body ) response.status_code.should eq(200) @@ -1361,7 +1370,7 @@ describe Events, tags: ["event"] do clashing.should_not contain("sys-9999") end - it "returns only clashing system_ids from provided list" do + it "returns only clashing system_ids from provided system_id" do tenant = get_tenant event_start = 10.minutes.from_now.to_unix event_end = 30.minutes.from_now.to_unix @@ -1369,9 +1378,19 @@ describe Events, tags: ["event"] do EventMetadatasHelper.create_event(tenant.id, system_id: "sys-1234", event_start: event_start, event_end: event_end) EventMetadatasHelper.create_event(tenant.id, system_id: "sys-5678", event_start: event_start, event_end: event_end) + clashing_event_body = { + event_start: event_start, + event_end: event_end, + system_id: "sys-1234", + attendees: [] of String, + private: false, + all_day: false, + }.to_json + response = client.post( - "#{EVENTS_BASE}/clashing-assets?period_start=#{event_start}&period_end=#{event_end}&system_ids=sys-1234,sys-9999", - headers: headers + "#{EVENTS_BASE}/clashing-assets", + headers: headers, + body: clashing_event_body ) response.status_code.should eq(200) @@ -1388,16 +1407,23 @@ describe Events, tags: ["event"] do EventMetadatasHelper.create_event(tenant.id, system_id: "sys-1234", event_start: event_start, event_end: event_end) + clashing_event_body = { + event_start: event_start, + event_end: event_end, + system_id: "sys-1234", + attendees: [] of String, + private: false, + all_day: false, + }.to_json + response = client.post( - "#{EVENTS_BASE}/clashing-assets?period_start=#{event_start}&period_end=#{event_end}&system_ids=sys-1234,sys-5678,sys-9999&return_available=true", - headers: headers + "#{EVENTS_BASE}/clashing-assets?return_available=true", + headers: headers, + body: clashing_event_body ) response.status_code.should eq(200) available = Array(String).from_json(response.body) - available.size.should eq(2) - available.should contain("sys-5678") - available.should contain("sys-9999") available.should_not contain("sys-1234") end @@ -1408,9 +1434,18 @@ describe Events, tags: ["event"] do EventMetadatasHelper.create_event(tenant.id, system_id: "sys-1234", event_start: event_start, event_end: event_end) + clashing_event_body = { + event_start: event_start, + event_end: event_end, + attendees: [] of String, + private: false, + all_day: false, + }.to_json + response = client.post( - "#{EVENTS_BASE}/clashing-assets?period_start=#{event_start}&period_end=#{event_end}&include_clash_time=true", - headers: headers + "#{EVENTS_BASE}/clashing-assets?include_clash_time=true", + headers: headers, + body: clashing_event_body ) response.status_code.should eq(200) @@ -1431,9 +1466,18 @@ describe Events, tags: ["event"] do cancelled_event.cancelled = true cancelled_event.save! + clashing_event_body = { + event_start: event_start, + event_end: event_end, + attendees: [] of String, + private: false, + all_day: false, + }.to_json + response = client.post( - "#{EVENTS_BASE}/clashing-assets?period_start=#{event_start}&period_end=#{event_end}", - headers: headers + "#{EVENTS_BASE}/clashing-assets", + headers: headers, + body: clashing_event_body ) response.status_code.should eq(200) diff --git a/src/controllers/events.cr b/src/controllers/events.cr index 0852a7fe..e6d87d56 100644 --- a/src/controllers/events.cr +++ b/src/controllers/events.cr @@ -1765,30 +1765,30 @@ class Events < Application # lists conflicting system_ids based on event time range # will return a list of system_ids that are already booked during the specified time range - # if system_ids is set, then it will only return booked systems from that list - @[AC::Route::POST("/clashing-assets")] + # if system_id is set on the event, then it will only return booked systems from that list + @[AC::Route::POST("/clashing-assets", body: :input_event)] def clashing_assets( - @[AC::Param::Info(name: "period_start", description: "event period start as a unix epoch", example: "1661725146")] - starting : Int64, - @[AC::Param::Info(name: "period_end", description: "event period end as a unix epoch", example: "1661743123")] - ending : Int64, - @[AC::Param::Info(description: "comma separated list of system_ids to check for clashes", example: "sys-1234,sys-5678")] - system_ids : String? = nil, - @[AC::Param::Info(description: "return available systems, this requires system_ids be set to the full list", example: "false")] + input_event : PlaceCalendar::Event, + @[AC::Param::Info(description: "return available systems, this requires system_id be set on the event", example: "false")] return_available : Bool = false, @[AC::Param::Info(description: "include the clash times, this is not compatible with return_available", example: "false")] include_clash_time : Bool = false, ) : Array(String) | Array(NamedTuple(system_id: String, event_start: Int64, event_end: Int64)) - if return_available && system_ids.nil? - raise Error::ModelValidation.new([{field: "system_ids".as(String?), reason: "Missing system_ids"}], "error validating event data") + raise Error::BadRequest.new("event_start must be present") unless event_start = input_event.event_start + raise Error::BadRequest.new("event_end must be present") unless event_end = input_event.event_end + + sys_id = input_event.system_id || input_event.system.try(&.id) + + if return_available && sys_id.nil? + raise Error::ModelValidation.new([{field: nil.as(String?), reason: "Missing system_id"}], "error validating event data") end if return_available && include_clash_time raise AC::Route::Param::Error.new("include_clash_time and return_available cannot be used together") end - # Parse system_ids if provided - sys_ids = system_ids.try(&.split(',').map(&.strip).reject(&.empty?)) || [] of String + starting = event_start.to_unix + ending = event_end.to_unix # Query for clashing events query = EventMetadata @@ -1796,24 +1796,24 @@ class Events < Application .where("event_end > ? AND event_start < ?", starting, ending) .where("cancelled = ? OR cancelled IS NULL", false) - # Filter by system_ids if provided - query = query.where({:system_id => sys_ids}) unless sys_ids.empty? + # Filter by system_id if provided + query = query.where({:system_id => sys_id}) if sys_id.try(&.presence) clashing_events = query.to_a if include_clash_time result = [] of NamedTuple(system_id: String, event_start: Int64, event_end: Int64) - clashing_events.each do |event| - if sys_id = event.system_id - result << {system_id: sys_id, event_start: event.event_start, event_end: event.event_end} + clashing_events.each do |evt| + if clashing_sys_id = evt.system_id + result << {system_id: clashing_sys_id, event_start: evt.event_start, event_end: evt.event_end} end end result else - clashing_system_ids = clashing_events.compact_map(&.system_id).uniq + clashing_system_ids = clashing_events.compact_map(&.system_id).uniq! if return_available - clashing_system_ids = sys_ids - clashing_system_ids + clashing_system_ids = [sys_id].compact - clashing_system_ids end clashing_system_ids