From aa48405c49624b41cec0ca15c6fe102c6b2d78fd Mon Sep 17 00:00:00 2001 From: Guillaume Deconinck <113656593+GuillaumeDecMeetsMore@users.noreply.github.com> Date: Wed, 19 Feb 2025 09:36:04 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20remove=20events=5Fgroups=20-=20remo?= =?UTF-8?q?ve=20unique=20constraint=20-=20rename=20pa=E2=80=A6=20(#217)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: remove events_groups - remove unique constraint - rename parent_id * fix: remove old types * chore: add a little more docs * chore: add more docs (2) * fix: generate TS types * chore: adapt docs on the JS side --- bins/nittei/tests/api.rs | 12 +- bins/nittei/tests/api_loadtests.rs | 3 +- bins/nittei/tests/api_recurring_events.rs | 21 +-- .../tests/collective_team_scheduling.rs | 3 +- bins/nittei/tests/group_team_scheduling.rs | 12 +- bins/nittei/tests/round_robin_scheduling.rs | 15 +- clients/javascript/lib/eventClient.ts | 14 +- clients/javascript/lib/eventGroupClient.ts | 84 --------- .../lib/gen_types/CalendarEventDTO.ts | 13 +- .../gen_types/CreateEventGroupRequestBody.ts | 22 --- .../lib/gen_types/CreateEventRequestBody.ts | 13 +- .../javascript/lib/gen_types/EventGroupDTO.ts | 28 --- .../lib/gen_types/EventGroupResponse.ts | 12 -- .../GetEventsByExternalIdQueryParams.ts | 11 -- .../lib/gen_types/SearchEventsRequestBody.ts | 7 +- .../gen_types/UpdateEventGroupRequestBody.ts | 18 -- .../lib/gen_types/UpdateEventRequestBody.ts | 6 - clients/javascript/lib/gen_types/index.ts | 5 - clients/javascript/lib/index.ts | 3 - clients/javascript/tests/account.spec.ts | 2 +- .../javascript/tests/calendarEvent.spec.ts | 135 +++----------- clients/javascript/tests/eventGroup.spec.ts | 88 --------- clients/rust/src/event.rs | 13 +- .../api/src/account/account_search_events.rs | 13 +- crates/api/src/event/create_event.rs | 12 +- .../api/src/event/get_event_by_external_id.rs | 9 +- crates/api/src/event/search_events.rs | 13 +- crates/api/src/event/update_event.rs | 20 +- .../api/src/event_group/create_event_group.rs | 174 ------------------ .../api/src/event_group/delete_event_group.rs | 87 --------- crates/api/src/event_group/get_event_group.rs | 77 -------- .../get_event_group_by_external_id.rs | 76 -------- crates/api/src/event_group/mod.rs | 45 ----- .../api/src/event_group/update_event_group.rs | 133 ------------- crates/api/src/lib.rs | 2 - crates/api/src/shared/auth/mod.rs | 1 - crates/api/src/shared/auth/route_guards.rs | 27 +-- crates/api_structs/src/event/api.rs | 40 +--- crates/api_structs/src/event/dtos.rs | 15 +- crates/api_structs/src/event_group/api.rs | 124 ------------- crates/api_structs/src/event_group/dtos.rs | 37 ---- crates/api_structs/src/event_group/mod.rs | 2 - crates/api_structs/src/lib.rs | 3 - crates/domain/src/event.rs | 3 +- ...013fbc1f2a5c828edb319edab1b2d291db878.json | 16 +- ...eead8f4690d55c3c1d1dc03616f88731e63ee.json | 37 ---- ...427005768ac1df02c3c219242996daff2d6fe.json | 16 +- ...9473c40af70dc79441291c72ec2922a2cbf95.json | 52 ------ ...02ba307b2cd707444a2713b9c18014018358e.json | 36 ++++ ...12b6ccb688c76e357fc81828e20e58ca917e3.json | 36 ---- ...857ecda868db3abd1001a642c30549cb487b5.json | 16 +- ...21d81e95b0e816df63beaf8a2e9b486068eb7.json | 16 -- ...4abdef01b81c9bba68250ed6ca2766be91adf.json | 12 +- ...5973d637db2af2519cf59aa8a3b1ad9278308.json | 16 +- ...b98d9993127ede389814e6800822b0a7b7b57.json | 173 ----------------- ...cfffcd3014c10f352a53393ba321d0df83e2d.json | 16 +- ...2997c23f74627d2e5b3e13a1cd582bded7ea8.json | 16 +- ...ac26d8a6269be7d3c01fcd576000346e762a6.json | 40 ---- ...9cce0549c50166fb34fc91f4039f62cde6f13.json | 16 +- ...1a212ef5f16390f85cdba3a334390486adebc.json | 52 ------ ...aaa678a334810d03fe9e05cef730134bcaae4.json | 16 +- ...a55f369f23b6e139e801f5b949e2b0d6a22c7.json | 17 -- ...78d8ef1897aa84c8dc0a7a3ffca5a8747ef33.json | 173 ----------------- ...4f587005e6d6e864dbe6c656bf5df5cdcb112.json | 16 +- ...6bd036fd7ed3a5c3712df228933b6bb3ffa4c.json | 16 +- ...cbfbbacb1dc31d40f907a046e44a0a89dd285.json | 35 ++++ ...601a7d4a77756182a45647d381181eb0eafbd.json | 16 +- ...0250218000000_simplify_calendar_events.sql | 18 ++ .../src/repos/event/calendar_event/mod.rs | 6 +- .../repos/event/calendar_event/postgres.rs | 135 +++----------- .../infra/src/repos/event/event_group/mod.rs | 119 ------------ .../src/repos/event/event_group/postgres.rs | 168 ----------------- crates/infra/src/repos/event/mod.rs | 2 - crates/infra/src/repos/mod.rs | 4 - .../infra/src/repos/shared/query_structs.rs | 1 + 75 files changed, 287 insertions(+), 2474 deletions(-) delete mode 100644 clients/javascript/lib/eventGroupClient.ts delete mode 100644 clients/javascript/lib/gen_types/CreateEventGroupRequestBody.ts delete mode 100644 clients/javascript/lib/gen_types/EventGroupDTO.ts delete mode 100644 clients/javascript/lib/gen_types/EventGroupResponse.ts delete mode 100644 clients/javascript/lib/gen_types/GetEventsByExternalIdQueryParams.ts delete mode 100644 clients/javascript/lib/gen_types/UpdateEventGroupRequestBody.ts delete mode 100644 clients/javascript/tests/eventGroup.spec.ts delete mode 100644 crates/api/src/event_group/create_event_group.rs delete mode 100644 crates/api/src/event_group/delete_event_group.rs delete mode 100644 crates/api/src/event_group/get_event_group.rs delete mode 100644 crates/api/src/event_group/get_event_group_by_external_id.rs delete mode 100644 crates/api/src/event_group/mod.rs delete mode 100644 crates/api/src/event_group/update_event_group.rs delete mode 100644 crates/api_structs/src/event_group/api.rs delete mode 100644 crates/api_structs/src/event_group/dtos.rs delete mode 100644 crates/api_structs/src/event_group/mod.rs delete mode 100644 crates/infra/.sqlx/query-04752eb8015b9333981bc966d56eead8f4690d55c3c1d1dc03616f88731e63ee.json delete mode 100644 crates/infra/.sqlx/query-09e9d9301a69be6bfe1e558fe7e9473c40af70dc79441291c72ec2922a2cbf95.json create mode 100644 crates/infra/.sqlx/query-1a18eb7670301b5335cbf19e02802ba307b2cd707444a2713b9c18014018358e.json delete mode 100644 crates/infra/.sqlx/query-246d53166723bcce5485835454c12b6ccb688c76e357fc81828e20e58ca917e3.json delete mode 100644 crates/infra/.sqlx/query-43604faa9bb10d9030db0a050b521d81e95b0e816df63beaf8a2e9b486068eb7.json delete mode 100644 crates/infra/.sqlx/query-7ca1e21500b0ee13496086f3258b98d9993127ede389814e6800822b0a7b7b57.json delete mode 100644 crates/infra/.sqlx/query-a3c5484db7b583f04582494294cac26d8a6269be7d3c01fcd576000346e762a6.json delete mode 100644 crates/infra/.sqlx/query-c8d36057bc491a1940386c101401a212ef5f16390f85cdba3a334390486adebc.json delete mode 100644 crates/infra/.sqlx/query-db24e838156e66fdff8694e040ca55f369f23b6e139e801f5b949e2b0d6a22c7.json delete mode 100644 crates/infra/.sqlx/query-dff6107515f942d02e2ca40164678d8ef1897aa84c8dc0a7a3ffca5a8747ef33.json create mode 100644 crates/infra/.sqlx/query-fa9c5b0aad3b49a8303f3fdc1d6cbfbbacb1dc31d40f907a046e44a0a89dd285.json create mode 100644 crates/infra/migrations/20250218000000_simplify_calendar_events.sql delete mode 100644 crates/infra/src/repos/event/event_group/mod.rs delete mode 100644 crates/infra/src/repos/event/event_group/postgres.rs diff --git a/bins/nittei/tests/api.rs b/bins/nittei/tests/api.rs index 6736a741..9515866b 100644 --- a/bins/nittei/tests/api.rs +++ b/bins/nittei/tests/api.rs @@ -482,9 +482,8 @@ async fn test_crud_events() { let event = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -533,12 +532,11 @@ async fn test_crud_events() { event_id: event.id.clone(), title: None, description: None, - group_id: None, event_type: None, location: None, status: None, all_day: None, - parent_id: None, + external_parent_id: None, external_id: None, busy: None, duration: None, @@ -765,9 +763,8 @@ async fn test_freebusy_multiple() { let _event1 = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -793,9 +790,8 @@ async fn test_freebusy_multiple() { let _event2 = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, diff --git a/bins/nittei/tests/api_loadtests.rs b/bins/nittei/tests/api_loadtests.rs index b4c2269e..3618734c 100644 --- a/bins/nittei/tests/api_loadtests.rs +++ b/bins/nittei/tests/api_loadtests.rs @@ -95,9 +95,8 @@ async fn create_300_events_1_month( .create(CreateEventInput { user_id: user_id.clone(), calendar_id: calendar_id.clone(), - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, diff --git a/bins/nittei/tests/api_recurring_events.rs b/bins/nittei/tests/api_recurring_events.rs index 517225e2..6f116a8a 100644 --- a/bins/nittei/tests/api_recurring_events.rs +++ b/bins/nittei/tests/api_recurring_events.rs @@ -52,9 +52,8 @@ async fn test_create_event_validation() { let event = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -117,9 +116,8 @@ async fn test_expand_daily_recurring_event() { let event = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -214,9 +212,8 @@ async fn test_expand_weekly_recurring_event() { let event = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -307,9 +304,8 @@ async fn test_expand_monthly_recurring_event() { let event = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -395,9 +391,8 @@ async fn test_expand_recurring_event_and_remove_exceptions() { let event = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -432,9 +427,8 @@ async fn test_expand_recurring_event_and_remove_exceptions() { let exception_changed = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -462,9 +456,8 @@ async fn test_expand_recurring_event_and_remove_exceptions() { let exception_removed = admin_client .event .create(CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, diff --git a/bins/nittei/tests/collective_team_scheduling.rs b/bins/nittei/tests/collective_team_scheduling.rs index 7621542d..ed2e62aa 100644 --- a/bins/nittei/tests/collective_team_scheduling.rs +++ b/bins/nittei/tests/collective_team_scheduling.rs @@ -168,9 +168,8 @@ async fn test_collective_team_scheduling() { for (host, calendar) in hosts_with_calendar { let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, diff --git a/bins/nittei/tests/group_team_scheduling.rs b/bins/nittei/tests/group_team_scheduling.rs index b33b4111..45db775f 100644 --- a/bins/nittei/tests/group_team_scheduling.rs +++ b/bins/nittei/tests/group_team_scheduling.rs @@ -186,9 +186,8 @@ async fn test_group_team_scheduling() { assert!(booking_intend.create_event_for_hosts); for (host, calendar) in hosts_with_calendar { let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -524,9 +523,8 @@ async fn test_group_team_scheduling_increase_max_count() { ); assert!(booking_intend.create_event_for_hosts); let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -959,9 +957,8 @@ async fn test_group_team_scheduling_decrease_max_count() { ); assert!(booking_intend.create_event_for_hosts); let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -1176,9 +1173,8 @@ async fn test_combination_of_services() { // And then create service event which is not busy let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, diff --git a/bins/nittei/tests/round_robin_scheduling.rs b/bins/nittei/tests/round_robin_scheduling.rs index ba5867c8..3bdf8f79 100644 --- a/bins/nittei/tests/round_robin_scheduling.rs +++ b/bins/nittei/tests/round_robin_scheduling.rs @@ -191,9 +191,8 @@ async fn test_round_robin_scheduling_simple_test() { // Create service event let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -315,9 +314,8 @@ async fn test_round_robin_equal_distribution_scheduling() { for _ in 0..*upcoming_service_events { // Create service event let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -380,9 +378,8 @@ async fn test_round_robin_equal_distribution_scheduling() { .find(|(h, _)| h.id == booking_intend.selected_hosts[0].id) .expect("To find selected host"); let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -514,9 +511,8 @@ async fn test_round_robin_availability_scheduling() { { // Create service event let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, @@ -598,9 +594,8 @@ async fn test_round_robin_availability_scheduling() { .expect("To find selected host"); let service_event = CreateEventInput { - parent_id: None, + external_parent_id: None, external_id: None, - group_id: None, title: None, description: None, event_type: None, diff --git a/clients/javascript/lib/eventClient.ts b/clients/javascript/lib/eventClient.ts index 2e25eade..a8f5c8fe 100644 --- a/clients/javascript/lib/eventClient.ts +++ b/clients/javascript/lib/eventClient.ts @@ -1,7 +1,6 @@ import { NitteiBaseClient } from './baseClient' import type { GetEventsByExternalIdAPIResponse, - GetEventsByExternalIdQueryParams, SearchEventsAPIResponse, SearchEventsRequestBody, } from './gen_types' @@ -78,19 +77,16 @@ export class NitteiEventClient extends NitteiBaseClient { /** * Get events by external id - * This returns an array of events - * It can be empty if no events are found - * @param externalId - external id of the event - * @param queryParams - query params (optional) - allow to specify that the events from groups should be included + * + * This returns an array of events (it can match zero, one or more events) + * @param externalId - external id of the event(s) to search * @returns - the events found */ public async getByExternalId( - externalId: string, - queryParams?: GetEventsByExternalIdQueryParams + externalId: string ): Promise { const res = await this.get( - `/user/events/external_id/${externalId}`, - queryParams + `/user/events/external_id/${externalId}` ) return { diff --git a/clients/javascript/lib/eventGroupClient.ts b/clients/javascript/lib/eventGroupClient.ts deleted file mode 100644 index 01f3e2b3..00000000 --- a/clients/javascript/lib/eventGroupClient.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { NitteiBaseClient } from './baseClient' -import type { - CreateEventGroupRequestBody, - EventGroupResponse, - UpdateEventGroupRequestBody, -} from './gen_types' -import type { ID } from './gen_types/ID' - -/** - * Client for the events groups' endpoints - * This is an admin client (usually backend) - */ -export class NitteiEventGroupClient extends NitteiBaseClient { - /** - * Create an event group - * @param userId - the user ID - * @param data - the event group data - * @returns - the created event group - */ - public async create( - userId: ID, - data: CreateEventGroupRequestBody - ): Promise { - return await this.post( - `/user/${userId}/event_groups`, - data - ) - } - - /** - * Update an event group - * @param eventGroupId - the event group ID - * @param data - the event group data - * @throws NotFoundError - if the event group is not found - * @returns - the updated event group - */ - public async update( - eventGroupId: ID, - data: UpdateEventGroupRequestBody - ): Promise { - return await this.put( - `/user/event_groups/${eventGroupId}`, - data - ) - } - - /** - * Get an event group by ID - * @param eventGroupId - the event group ID - * @throws NotFoundError - if the event group is not found - * @returns - the event group - */ - public async getById(eventGroupId: ID): Promise { - return await this.get( - `/user/event_groups/${eventGroupId}` - ) - } - - /** - * Get an event group by external ID - * @param externalId - the external ID - * @throws NotFoundError - if the event group is not found - * @returns - the event group - */ - public async getByExternalId( - externalId: string - ): Promise { - return await this.get( - `/user/event_groups/external_id/${externalId}` - ) - } - - /** - * Delete an event group - * @param eventGroupId - the event group ID - * @throws NotFoundError - if the event group is not found - * @returns - the deleted event group - */ - public async remove(eventGroupId: ID): Promise { - return await this.delete( - `/user/event_groups/${eventGroupId}` - ) - } -} diff --git a/clients/javascript/lib/gen_types/CalendarEventDTO.ts b/clients/javascript/lib/gen_types/CalendarEventDTO.ts index df30590e..288bc3ad 100644 --- a/clients/javascript/lib/gen_types/CalendarEventDTO.ts +++ b/clients/javascript/lib/gen_types/CalendarEventDTO.ts @@ -40,10 +40,17 @@ export type CalendarEventDTO = { status: CalendarEventStatus /** * Optional parent event ID + * This is useful for external applications that need to link Nittei's events to a wider data model (e.g. a project, an order, etc.) + * Example: If the event is a meeting, the parent ID could be the project ID (ObjectId, UUID or any other string) */ - parentId: string | null + externalParentId: string | null /** * Optional external ID + * This is useful for external applications that need to link Nittei's events to their own data models + * Example: If the event is a meeting, the external ID could be the meeting ID in the external system + * + * Note that nothing prevents multiple events from having the same external ID + * This can also be a way to link events together */ externalId: string | null /** @@ -98,10 +105,6 @@ export type CalendarEventDTO = { * UUID of the user */ userId: ID - /** - * Optional group ID - */ - groupId: ID | null /** * List of reminders */ diff --git a/clients/javascript/lib/gen_types/CreateEventGroupRequestBody.ts b/clients/javascript/lib/gen_types/CreateEventGroupRequestBody.ts deleted file mode 100644 index c1271e12..00000000 --- a/clients/javascript/lib/gen_types/CreateEventGroupRequestBody.ts +++ /dev/null @@ -1,22 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { ID } from './ID' - -/** - * Request body for creating an event - */ -export type CreateEventGroupRequestBody = { - /** - * UUID of the calendar where the event group will be created - */ - calendarId: ID - /** - * Optional parent event ID - * This is useful for external applications that need to link Nittei's events to a wider data model (e.g. a project, an order, etc.) - */ - parentId?: string - /** - * Optional external event ID - * This is useful for external applications that need to link Nittei's events to their own data models - */ - externalId?: string -} diff --git a/clients/javascript/lib/gen_types/CreateEventRequestBody.ts b/clients/javascript/lib/gen_types/CreateEventRequestBody.ts index 0772cd67..1b5c62ef 100644 --- a/clients/javascript/lib/gen_types/CreateEventRequestBody.ts +++ b/clients/javascript/lib/gen_types/CreateEventRequestBody.ts @@ -30,11 +30,16 @@ export type CreateEventRequestBody = { /** * Optional parent event ID * This is useful for external applications that need to link Nittei's events to a wider data model (e.g. a project, an order, etc.) + * Example: If the event is a meeting, the parent ID could be the project ID (ObjectId, UUID or any other string) */ - parentId?: string + externalParentId?: string /** * Optional external event ID * This is useful for external applications that need to link Nittei's events to their own data models + * Example: If the event is a meeting, the external ID could be the meeting ID in the external system + * + * Note that nothing prevents multiple events from having the same external ID + * This can also be a way to link events together */ externalId?: string /** @@ -93,12 +98,6 @@ export type CreateEventRequestBody = { * This is automatically set when the event is created from a service */ serviceId?: ID - /** - * Optional group UUID - * Allows to group events together (e.g. a project, a team, etc.) - * Default is None - */ - groupId?: ID /** * Optional metadata (e.g. {"key": "value"}) */ diff --git a/clients/javascript/lib/gen_types/EventGroupDTO.ts b/clients/javascript/lib/gen_types/EventGroupDTO.ts deleted file mode 100644 index b836c4d5..00000000 --- a/clients/javascript/lib/gen_types/EventGroupDTO.ts +++ /dev/null @@ -1,28 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { ID } from './ID' - -/** - * Calendar event object - */ -export type EventGroupDTO = { - /** - * UUID of the event - */ - id: ID - /** - * Optional parent event ID - */ - parentId: string | null - /** - * Optional external ID - */ - externalId: string | null - /** - * UUID of the calendar - */ - calendarId: ID - /** - * UUID of the user - */ - userId: ID -} diff --git a/clients/javascript/lib/gen_types/EventGroupResponse.ts b/clients/javascript/lib/gen_types/EventGroupResponse.ts deleted file mode 100644 index 0f466f7f..00000000 --- a/clients/javascript/lib/gen_types/EventGroupResponse.ts +++ /dev/null @@ -1,12 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { EventGroupDTO } from './EventGroupDTO' - -/** - * Calendar event response object - */ -export type EventGroupResponse = { - /** - * Calendar event retrieved - */ - eventGroup: EventGroupDTO -} diff --git a/clients/javascript/lib/gen_types/GetEventsByExternalIdQueryParams.ts b/clients/javascript/lib/gen_types/GetEventsByExternalIdQueryParams.ts deleted file mode 100644 index 92f8a087..00000000 --- a/clients/javascript/lib/gen_types/GetEventsByExternalIdQueryParams.ts +++ /dev/null @@ -1,11 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -/** - * Query parameters that can be used when getting an event by external ID - */ -export type GetEventsByExternalIdQueryParams = { - /** - * Optional flag to include the events that are from a group with the same external ID - */ - includeGroups?: boolean -} diff --git a/clients/javascript/lib/gen_types/SearchEventsRequestBody.ts b/clients/javascript/lib/gen_types/SearchEventsRequestBody.ts index 14083b57..51717126 100644 --- a/clients/javascript/lib/gen_types/SearchEventsRequestBody.ts +++ b/clients/javascript/lib/gen_types/SearchEventsRequestBody.ts @@ -1,7 +1,6 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { DateTimeQuery } from './DateTimeQuery' import type { ID } from './ID' -import type { IDQuery } from './IDQuery' import type { StringQuery } from './StringQuery' import type { JsonValue } from './serde_json/JsonValue' @@ -21,11 +20,7 @@ export type SearchEventsRequestBody = { /** * Optional query on parent ID (which is a string as it's an ID from an external system) */ - parentId?: StringQuery - /** - * Optional query on group ID - */ - groupId?: IDQuery + externalParentId?: StringQuery /** * Optional query on start time - "lower than or equal", or "great than or equal" (UTC) */ diff --git a/clients/javascript/lib/gen_types/UpdateEventGroupRequestBody.ts b/clients/javascript/lib/gen_types/UpdateEventGroupRequestBody.ts deleted file mode 100644 index 45d9b472..00000000 --- a/clients/javascript/lib/gen_types/UpdateEventGroupRequestBody.ts +++ /dev/null @@ -1,18 +0,0 @@ -// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. - -/** - * Request body for updating an event - */ -export type UpdateEventGroupRequestBody = { - /** - * Optional parent event ID - * This is useful for external applications that need to link Nittei's events to a wider data model (e.g. a project, an order, etc.) - */ - parentId?: string - /** - * Optional external event ID - * This is useful for external applications that need to link Nittei's events to their own data models - * Default is None - */ - externalId?: string -} diff --git a/clients/javascript/lib/gen_types/UpdateEventRequestBody.ts b/clients/javascript/lib/gen_types/UpdateEventRequestBody.ts index bc050bbc..df65e1f5 100644 --- a/clients/javascript/lib/gen_types/UpdateEventRequestBody.ts +++ b/clients/javascript/lib/gen_types/UpdateEventRequestBody.ts @@ -68,12 +68,6 @@ export type UpdateEventRequestBody = { * Optional service UUID */ serviceId?: ID - /** - * Optional group UUID - * Allows to group events together (e.g. a project, a team, etc.) - * Default is None - */ - groupId?: ID /** * Optional list of exclusion dates for the recurrence rule */ diff --git a/clients/javascript/lib/gen_types/index.ts b/clients/javascript/lib/gen_types/index.ts index 856efa9f..57faeaee 100644 --- a/clients/javascript/lib/gen_types/index.ts +++ b/clients/javascript/lib/gen_types/index.ts @@ -23,7 +23,6 @@ export * from './CalendarSettingsDTO' export * from './CreateAccountRequestBody' export * from './CreateAccountResponseBody' export * from './CreateCalendarRequestBody' -export * from './CreateEventGroupRequestBody' export * from './CreateEventRequestBody' export * from './CreateServiceEventIntendRequestBody' export * from './CreateServiceRequestBody' @@ -31,8 +30,6 @@ export * from './CreateUserRequestBody' export * from './DateTimeQuery' export * from './DateTimeQueryRange' export * from './EventGroup' -export * from './EventGroupDTO' -export * from './EventGroupResponse' export * from './EventInstance' export * from './EventWithInstancesDTO' export * from './GetCalendarEventsAPIResponse' @@ -42,7 +39,6 @@ export * from './GetEventInstancesAPIResponse' export * from './GetEventsByCalendarsAPIResponse' export * from './GetEventsByCalendarsQueryParams' export * from './GetEventsByExternalIdAPIResponse' -export * from './GetEventsByExternalIdQueryParams' export * from './GetEventsByMetaAPIResponse' export * from './GetGoogleCalendarsAPIResponse' export * from './GetOutlookCalendarsAPIResponse' @@ -96,7 +92,6 @@ export * from './TimePlan' export * from './TimeSpan' export * from './UpdateCalendarRequestBody' export * from './UpdateCalendarSettings' -export * from './UpdateEventGroupRequestBody' export * from './UpdateEventRequestBody' export * from './UpdateServiceRequestBody' export * from './UpdateServiceUserRequestBody' diff --git a/clients/javascript/lib/index.ts b/clients/javascript/lib/index.ts index e1432f4e..7c06ab2b 100644 --- a/clients/javascript/lib/index.ts +++ b/clients/javascript/lib/index.ts @@ -8,7 +8,6 @@ import { NitteiCalendarUserClient, } from './calendarClient' import { NitteiEventClient, NitteiEventUserClient } from './eventClient' -import { NitteiEventGroupClient } from './eventGroupClient' import { NitteiHealthClient } from './healthClient' import { type PartialCredentials, createCreds } from './helpers/credentials' import { @@ -33,7 +32,6 @@ export interface INitteiClient { account: NitteiAccountClient calendar: NitteiCalendarClient events: NitteiEventClient - eventGroups: NitteiEventGroupClient health: NitteiHealthClient service: NitteiServiceClient schedule: NitteiScheduleClient @@ -111,7 +109,6 @@ export const NitteiClient = async ( return Object.freeze({ account: new NitteiAccountClient(axiosClient), events: new NitteiEventClient(axiosClient), - eventGroups: new NitteiEventGroupClient(axiosClient), calendar: new NitteiCalendarClient(axiosClient), user: new _NitteiUserClient(axiosClient), service: new NitteiServiceClient(axiosClient), diff --git a/clients/javascript/tests/account.spec.ts b/clients/javascript/tests/account.spec.ts index 0c5726ae..76b62477 100644 --- a/clients/javascript/tests/account.spec.ts +++ b/clients/javascript/tests/account.spec.ts @@ -139,7 +139,7 @@ describe('Account API', () => { duration: 1000, startTime: new Date(1000), status: 'confirmed', - parentId: 'parentId', + externalParentId: 'parentId', }) eventId2 = eventRes2.event.id diff --git a/clients/javascript/tests/calendarEvent.spec.ts b/clients/javascript/tests/calendarEvent.spec.ts index 09692015..8af4d78b 100644 --- a/clients/javascript/tests/calendarEvent.spec.ts +++ b/clients/javascript/tests/calendarEvent.spec.ts @@ -320,81 +320,26 @@ describe('CalendarEvent API', () => { }) it('should be able to query on external ID', async () => { - const externalId = crypto.randomUUID() + const commonExternalId = crypto.randomUUID() const resEvent1 = await adminClient.events.create(userId, { calendarId, duration: 1000, startTime: new Date(1000), - externalId: externalId, - }) - - const resGroup1 = await adminClient.eventGroups.create(userId, { - calendarId, - externalId: externalId, + externalId: commonExternalId, }) const resEvent2 = await adminClient.events.create(userId, { calendarId, duration: 1000, startTime: new Date(1000), - groupId: resGroup1.eventGroup.id, + externalId: commonExternalId, }) const eventId1 = resEvent1.event.id const eventId2 = resEvent2.event.id - const resExternalId = await adminClient.events.getByExternalId(externalId) - - expect(resExternalId.events).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: eventId1, - }), - ]) - ) - - expect(resExternalId.events).not.toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: eventId2, - }), - ]) - ) - }) - - it('should be able to query on external ID (include groups)', async () => { - const resUnrelatedEvent = await adminClient.events.create(userId, { - calendarId, - duration: 1000, - startTime: new Date(1000), - }) - - const externalId = crypto.randomUUID() - const resEvent1 = await adminClient.events.create(userId, { - calendarId, - duration: 1000, - startTime: new Date(1000), - externalId: externalId, - }) + const resExternalId = + await adminClient.events.getByExternalId(commonExternalId) - const resGroup = await adminClient.eventGroups.create(userId, { - calendarId, - externalId: externalId, - }) - - const resEvent2 = await adminClient.events.create(userId, { - calendarId, - duration: 1000, - startTime: new Date(1000), - groupId: resGroup.eventGroup.id, - }) - const eventId1 = resEvent1.event.id - const eventId2 = resEvent2.event.id - const resExternalId = await adminClient.events.getByExternalId( - externalId, - { - includeGroups: true, - } - ) expect(resExternalId.events).toEqual( expect.arrayContaining([ expect.objectContaining({ @@ -405,72 +350,64 @@ describe('CalendarEvent API', () => { }), ]) ) - - expect(resExternalId.events).not.toEqual( - expect.arrayContaining([ - expect.objectContaining({ - id: resUnrelatedEvent.event.id, - }), - ]) - ) }) - it('should update event (externalId and parentId)', async () => { + it('should update event (externalId and externalParentId)', async () => { const externalId = crypto.randomUUID() - const parentId = crypto.randomUUID() + const externalParentId = crypto.randomUUID() const res = await adminClient.events.create(userId, { calendarId, duration: 1000, startTime: new Date(1000), eventType: 'job', externalId: externalId, - parentId: parentId, + externalParentId: externalParentId, }) const eventId = res.event.id expect(res.event.externalId).toBe(externalId) - expect(res.event.parentId).toBe(parentId) + expect(res.event.externalParentId).toBe(externalParentId) const getRes = await adminClient.events.getByExternalId(externalId) expect(getRes.events[0].externalId).toBe(externalId) - expect(getRes.events[0].parentId).toBe(parentId) + expect(getRes.events[0].externalParentId).toBe(externalParentId) expect(getRes.events[0].eventType).toBe('job') const externalId2 = crypto.randomUUID() - const parentId2 = crypto.randomUUID() + const externalParentId2 = crypto.randomUUID() const res2 = await adminClient.events.update(eventId, { eventType: 'block', - parentId: parentId2, + parentId: externalParentId2, externalId: externalId2, }) expect(res2.event.externalId).toBe(externalId2) - expect(res2.event.parentId).toBe(parentId2) + expect(res2.event.externalParentId).toBe(externalParentId2) const getRes2 = await adminClient.events.getByExternalId(externalId2) expect(getRes2.events[0].externalId).toBe(externalId2) - expect(getRes2.events[0].parentId).toBe(parentId2) + expect(getRes2.events[0].externalParentId).toBe(externalParentId2) expect(getRes2.events[0].eventType).toBe('block') }) it('should not overwrite externalId and parentId when updating event', async () => { const externalId = crypto.randomUUID() - const parentId = crypto.randomUUID() + const externalParentId = crypto.randomUUID() const res = await adminClient.events.create(userId, { calendarId, duration: 1000, startTime: new Date(1000), externalId: externalId, - parentId: parentId, + externalParentId: externalParentId, }) const eventId = res.event.id expect(res.event.externalId).toBe(externalId) - expect(res.event.parentId).toBe(parentId) + expect(res.event.externalParentId).toBe(externalParentId) const res2 = await adminClient.events.update(eventId, { title: 'new title', }) expect(res2.event.externalId).toBe(externalId) - expect(res2.event.parentId).toBe(parentId) + expect(res2.event.externalParentId).toBe(externalParentId) }) let metadataEventId: string @@ -577,7 +514,7 @@ describe('CalendarEvent API', () => { duration: 1000, startTime: new Date(1000), status: 'confirmed', - parentId: 'parentId', + externalParentId: 'parentId', }) eventId2 = eventRes2.event.id @@ -684,7 +621,7 @@ describe('CalendarEvent API', () => { it('should be able to search by parentId (equality)', async () => { const res = await adminClient.events.searchEvents({ userId: userId, - parentId: { + externalParentId: { eq: 'parentId', }, }) @@ -695,7 +632,7 @@ describe('CalendarEvent API', () => { it('should be able to search by parentId (existence)', async () => { const res = await adminClient.events.searchEvents({ userId: userId, - parentId: { + externalParentId: { exists: true, }, }) @@ -706,7 +643,7 @@ describe('CalendarEvent API', () => { it('should be able to search by parentId and startTime', async () => { const res = await adminClient.events.searchEvents({ userId: userId, - parentId: { + externalParentId: { eq: 'parentId', }, startTime: { @@ -722,7 +659,7 @@ describe('CalendarEvent API', () => { it('should fail to find something when searching by parentId and wrong startTime', async () => { const res = await adminClient.events.searchEvents({ userId: userId, - parentId: { + externalParentId: { eq: 'parentId', }, startTime: { @@ -781,32 +718,6 @@ describe('CalendarEvent API', () => { expect(res.events.length).toBe(1) expect(res.events[0].id).toBe(metadataEventId1) }) - - it('should be search events on event group id', async () => { - const group = await adminClient.eventGroups.create(userId, { - calendarId, - }) - - const resCreate = await adminClient.events.create(userId, { - calendarId, - duration: 1000, - startTime: new Date(1000), - groupId: group.eventGroup.id, - }) - expect(resCreate.event).toBeDefined() - expect(resCreate.event.calendarId).toBe(calendarId) - - const resSearch = await adminClient.events.searchEvents({ - userId, - groupId: { - eq: group.eventGroup.id, - }, - }) - - expect(resSearch.events.length).toBe(1) - expect(resSearch.events[0].id).toBe(resCreate.event.id) - expect(resSearch.events[0].groupId).toBe(group.eventGroup.id) - }) }) afterAll(async () => { diff --git a/clients/javascript/tests/eventGroup.spec.ts b/clients/javascript/tests/eventGroup.spec.ts deleted file mode 100644 index 6a654887..00000000 --- a/clients/javascript/tests/eventGroup.spec.ts +++ /dev/null @@ -1,88 +0,0 @@ -import type { INitteiClient } from '../lib' -import { setupAccount } from './helpers/fixtures' - -describe('EventGroup API', () => { - describe('Admin API', () => { - let calendarId: string - let userId: string - let adminClient: INitteiClient - beforeAll(async () => { - const data = await setupAccount() - adminClient = data.client - const userRes = await adminClient.user.create() - userId = userRes.user.id - const calendarRes = await adminClient.calendar.create(userId, { - timezone: 'UTC', - }) - calendarId = calendarRes.calendar.id - }) - - it('should be able to create an event group', async () => { - const res = await adminClient.eventGroups.create(userId, { - calendarId, - }) - expect(res.eventGroup).toBeDefined() - expect(res.eventGroup.calendarId).toBe(calendarId) - }) - - it('should be able to update an event group', async () => { - const externalId = crypto.randomUUID() - const res = await adminClient.eventGroups.create(userId, { - calendarId, - }) - const eventGroupId = res.eventGroup.id - - expect(res.eventGroup.calendarId).toEqual(calendarId) - - const res2 = await adminClient.eventGroups.update(eventGroupId, { - externalId, - }) - expect(res2.eventGroup.externalId).toEqual(externalId) - }) - - it('should be able to query on external ID', async () => { - const externalId = crypto.randomUUID() - const res = await adminClient.eventGroups.create(userId, { - calendarId, - externalId: externalId, - }) - const eventGroupId = res.eventGroup.id - const res2 = await adminClient.eventGroups.getByExternalId(externalId) - expect(res2.eventGroup.id).toBe(eventGroupId) - }) - - it('should update an event group (externalId and parentId)', async () => { - const externalId = crypto.randomUUID() - const parentId = crypto.randomUUID() - const res = await adminClient.eventGroups.create(userId, { - calendarId, - externalId: externalId, - parentId: parentId, - }) - const eventId = res.eventGroup.id - expect(res.eventGroup.externalId).toBe(externalId) - expect(res.eventGroup.parentId).toBe(parentId) - - const getRes = await adminClient.eventGroups.getByExternalId(externalId) - expect(getRes.eventGroup.externalId).toBe(externalId) - expect(getRes.eventGroup.parentId).toBe(parentId) - - const externalId2 = crypto.randomUUID() - const parentId2 = crypto.randomUUID() - const res2 = await adminClient.eventGroups.update(eventId, { - parentId: parentId2, - externalId: externalId2, - }) - expect(res2.eventGroup.externalId).toBe(externalId2) - expect(res2.eventGroup.parentId).toBe(parentId2) - - const getRes2 = await adminClient.eventGroups.getByExternalId(externalId2) - expect(getRes2.eventGroup.externalId).toBe(externalId2) - expect(getRes2.eventGroup.parentId).toBe(parentId2) - }) - - afterAll(async () => { - await adminClient.user.remove(userId) - }) - }) -}) diff --git a/clients/rust/src/event.rs b/clients/rust/src/event.rs index a39ebcb9..a73f88c7 100644 --- a/clients/rust/src/event.rs +++ b/clients/rust/src/event.rs @@ -32,12 +32,10 @@ pub struct CreateEventInput { #[serde(default)] pub event_type: Option, #[serde(default)] - pub parent_id: Option, + pub external_parent_id: Option, #[serde(default)] pub external_id: Option, #[serde(default)] - pub group_id: Option, - #[serde(default)] pub location: Option, #[serde(default)] pub status: CalendarEventStatus, @@ -78,9 +76,8 @@ pub struct UpdateEventInput { pub title: Option, pub description: Option, pub event_type: Option, - pub parent_id: Option, + pub external_parent_id: Option, pub external_id: Option, - pub group_id: Option, pub location: Option, pub status: Option, pub all_day: Option, @@ -132,7 +129,7 @@ impl CalendarEventClient { pub async fn create(&self, input: CreateEventInput) -> APIResponse { let user_id = input.user_id.clone(); let body = create_event::RequestBody { - parent_id: input.parent_id, + external_parent_id: input.external_parent_id, external_id: input.external_id, title: input.title, description: input.description, @@ -150,7 +147,6 @@ impl CalendarEventClient { original_start_time: input.original_start_time, reminders: input.reminders, service_id: input.service_id, - group_id: input.group_id, metadata: input.metadata, created: None, updated: None, @@ -187,7 +183,7 @@ impl CalendarEventClient { location: input.location, all_day: input.all_day, status: input.status, - parent_id: input.parent_id, + parent_id: input.external_parent_id, external_id: input.external_id, busy: input.busy, start_time: input.start_time, @@ -198,7 +194,6 @@ impl CalendarEventClient { original_start_time: input.original_start_time, reminders: input.reminders, service_id: input.service_id, - group_id: input.group_id, metadata: input.metadata, created: None, updated: None, diff --git a/crates/api/src/account/account_search_events.rs b/crates/api/src/account/account_search_events.rs index 78d2350e..a788c555 100644 --- a/crates/api/src/account/account_search_events.rs +++ b/crates/api/src/account/account_search_events.rs @@ -1,6 +1,6 @@ use actix_web::{web, HttpRequest, HttpResponse}; use nittei_api_structs::{account_search_events::*, dtos::CalendarEventDTO}; -use nittei_domain::{DateTimeQuery, IDQuery, StringQuery, ID}; +use nittei_domain::{DateTimeQuery, StringQuery, ID}; use nittei_infra::{NitteiContext, SearchEventsForAccountParams, SearchEventsParams}; use crate::{ @@ -21,8 +21,7 @@ pub async fn account_search_events_controller( let body = body.0; let usecase = AccountSearchEventsUseCase { account_id: account.id, - parent_id: body.parent_id, - group_id: body.group_id, + external_parent_id: body.parent_id, start_time: body.start_time, end_time: body.end_time, status: body.status, @@ -43,10 +42,7 @@ pub struct AccountSearchEventsUseCase { pub account_id: ID, /// Optional query on parent ID (which is a string as it's an ID from an external system) - pub parent_id: Option, - - /// Optional query on the group ID - pub group_id: Option, + pub external_parent_id: Option, /// Optional query on start time - "lower than or equal", or "great than or equal" (UTC) pub start_time: Option, @@ -100,8 +96,7 @@ impl UseCase for AccountSearchEventsUseCase { .search_events_for_account(SearchEventsForAccountParams { account_id: self.account_id.clone(), search_events_params: SearchEventsParams { - parent_id: self.parent_id.take(), - group_id: self.group_id.take(), + external_parent_id: self.external_parent_id.take(), start_time: self.start_time.take(), end_time: self.end_time.take(), status: self.status.take(), diff --git a/crates/api/src/event/create_event.rs b/crates/api/src/event/create_event.rs index 045112cd..b7bbc455 100644 --- a/crates/api/src/event/create_event.rs +++ b/crates/api/src/event/create_event.rs @@ -32,7 +32,7 @@ pub async fn create_event_admin_controller( let body = body.0; let usecase = CreateEventUseCase { - parent_id: body.parent_id, + external_parent_id: body.external_parent_id, external_id: body.external_id, title: body.title, description: body.description, @@ -51,7 +51,6 @@ pub async fn create_event_admin_controller( original_start_time: body.original_start_time, reminders: body.reminders, service_id: body.service_id, - group_id: body.group_id, metadata: body.metadata, created: body.created, updated: body.updated, @@ -72,7 +71,7 @@ pub async fn create_event_controller( let body = body.0; let usecase = CreateEventUseCase { - parent_id: body.parent_id, + external_parent_id: body.external_parent_id, external_id: body.external_id, title: body.title, description: body.description, @@ -91,7 +90,6 @@ pub async fn create_event_controller( user, reminders: body.reminders, service_id: body.service_id, - group_id: body.group_id, metadata: body.metadata, created: body.created, updated: body.updated, @@ -110,7 +108,7 @@ pub struct CreateEventUseCase { pub title: Option, pub description: Option, pub event_type: Option, - pub parent_id: Option, + pub external_parent_id: Option, pub external_id: Option, pub location: Option, pub status: CalendarEventStatus, @@ -124,7 +122,6 @@ pub struct CreateEventUseCase { pub original_start_time: Option>, pub reminders: Vec, pub service_id: Option, - pub group_id: Option, pub metadata: Option, pub created: Option>, pub updated: Option>, @@ -185,7 +182,7 @@ impl UseCase for CreateEventUseCase { let mut e = CalendarEvent { id: Default::default(), - parent_id: self.parent_id.clone(), + external_parent_id: self.external_parent_id.clone(), external_id: self.external_id.clone(), title: self.title.clone(), description: self.description.clone(), @@ -206,7 +203,6 @@ impl UseCase for CreateEventUseCase { account_id: self.user.account_id.clone(), reminders: self.reminders.clone(), service_id: self.service_id.take(), - group_id: self.group_id.take(), metadata: self.metadata.take(), created: self.created.unwrap_or_else(Utc::now), updated: self.updated.unwrap_or_else(Utc::now), diff --git a/crates/api/src/event/get_event_by_external_id.rs b/crates/api/src/event/get_event_by_external_id.rs index 51b81242..c534390a 100644 --- a/crates/api/src/event/get_event_by_external_id.rs +++ b/crates/api/src/event/get_event_by_external_id.rs @@ -14,7 +14,6 @@ use crate::{ pub async fn get_event_by_external_id_admin_controller( http_req: HttpRequest, path_params: web::Path, - query_params: web::Query, ctx: web::Data, ) -> Result { let account = protect_account_route(&http_req, &ctx).await?; @@ -22,7 +21,6 @@ pub async fn get_event_by_external_id_admin_controller( let usecase = GetEventByExternalIdUseCase { account_id: account.id, external_id: path_params.external_id.clone(), - include_groups: query_params.include_groups, }; execute(usecase, &ctx) @@ -35,7 +33,6 @@ pub async fn get_event_by_external_id_admin_controller( pub struct GetEventByExternalIdUseCase { pub external_id: String, pub account_id: ID, - pub include_groups: Option, } #[derive(Debug)] @@ -63,11 +60,7 @@ impl UseCase for GetEventByExternalIdUseCase { let events = ctx .repos .events - .get_by_external_id( - &self.account_id, - &self.external_id, - self.include_groups.unwrap_or(false), - ) + .get_by_external_id(&self.account_id, &self.external_id) .await .map_err(|_| UseCaseError::InternalError)?; diff --git a/crates/api/src/event/search_events.rs b/crates/api/src/event/search_events.rs index d3225efb..15bb63f6 100644 --- a/crates/api/src/event/search_events.rs +++ b/crates/api/src/event/search_events.rs @@ -1,6 +1,6 @@ use actix_web::{web, HttpRequest, HttpResponse}; use nittei_api_structs::{dtos::CalendarEventDTO, search_events::*}; -use nittei_domain::{DateTimeQuery, IDQuery, StringQuery, ID}; +use nittei_domain::{DateTimeQuery, StringQuery, ID}; use nittei_infra::{NitteiContext, SearchEventsForUserParams, SearchEventsParams}; use crate::{ @@ -23,8 +23,7 @@ pub async fn search_events_controller( account_id: account.id, user_id: body.user_id, calendar_ids: body.calendar_ids, - parent_id: body.parent_id, - group_id: body.group_id, + external_parent_id: body.external_parent_id, start_time: body.start_time, end_time: body.end_time, event_type: body.event_type, @@ -52,10 +51,7 @@ pub struct SearchEventsUseCase { pub calendar_ids: Option>, /// Optional query on parent ID (which is a string as it's an ID from an external system) - pub parent_id: Option, - - /// Optional query on the group ID - pub group_id: Option, + pub external_parent_id: Option, /// Optional query on start time - "lower than or equal", or "great than or equal" (UTC) pub start_time: Option, @@ -149,8 +145,7 @@ impl UseCase for SearchEventsUseCase { user_id: self.user_id.clone(), calendar_ids: self.calendar_ids.take(), search_events_params: SearchEventsParams { - parent_id: self.parent_id.take(), - group_id: self.group_id.take(), + external_parent_id: self.external_parent_id.take(), start_time: self.start_time.take(), end_time: self.end_time.take(), event_type: self.event_type.take(), diff --git a/crates/api/src/event/update_event.rs b/crates/api/src/event/update_event.rs index 421743d5..55e744cf 100644 --- a/crates/api/src/event/update_event.rs +++ b/crates/api/src/event/update_event.rs @@ -44,7 +44,7 @@ pub async fn update_event_admin_controller( title: body.title, description: body.description, event_type: body.event_type, - parent_id: body.parent_id, + external_parent_id: body.parent_id, external_id: body.external_id, location: body.location, status: body.status, @@ -54,7 +54,6 @@ pub async fn update_event_admin_controller( reminders: body.reminders, busy: body.busy, service_id: body.service_id, - group_id: body.group_id, recurrence: body.recurrence, exdates: body.exdates, recurring_event_id: body.recurring_event_id, @@ -85,7 +84,7 @@ pub async fn update_event_controller( title: body.title, description: body.description, event_type: body.event_type, - parent_id: body.parent_id, + external_parent_id: body.parent_id, external_id: body.external_id, location: body.location, status: body.status, @@ -95,7 +94,6 @@ pub async fn update_event_controller( reminders: body.reminders, busy: body.busy, service_id: body.service_id, - group_id: body.group_id, recurrence: body.recurrence, exdates: body.exdates, recurring_event_id: body.recurring_event_id, @@ -119,7 +117,7 @@ pub struct UpdateEventUseCase { pub title: Option, pub description: Option, pub event_type: Option, - pub parent_id: Option, + pub external_parent_id: Option, pub external_id: Option, pub location: Option, pub status: Option, @@ -129,7 +127,6 @@ pub struct UpdateEventUseCase { pub duration: Option, pub reminders: Option>, pub service_id: Option, - pub group_id: Option, pub recurrence: Option, pub exdates: Option>>, pub recurring_event_id: Option, @@ -180,7 +177,7 @@ impl UseCase for UpdateEventUseCase { title, description, event_type, - parent_id, + external_parent_id, external_id, location, status, @@ -194,7 +191,6 @@ impl UseCase for UpdateEventUseCase { original_start_time, reminders, service_id, - group_id, metadata, created, updated, @@ -316,18 +312,14 @@ impl UseCase for UpdateEventUseCase { e.event_type.clone_from(event_type); } - if parent_id.is_some() { - e.parent_id.clone_from(parent_id); + if external_parent_id.is_some() { + e.external_parent_id.clone_from(external_parent_id); } if external_id.is_some() { e.external_id.clone_from(external_id); } - if group_id.is_some() { - e.group_id.clone_from(group_id); - } - if location.is_some() { e.location.clone_from(location); } diff --git a/crates/api/src/event_group/create_event_group.rs b/crates/api/src/event_group/create_event_group.rs deleted file mode 100644 index 9455b53e..00000000 --- a/crates/api/src/event_group/create_event_group.rs +++ /dev/null @@ -1,174 +0,0 @@ -use actix_web::{web, HttpRequest, HttpResponse}; -use nittei_api_structs::create_event_group::*; -use nittei_domain::{event_group::EventGroup, User, ID}; -use nittei_infra::NitteiContext; - -use crate::{ - error::NitteiError, - shared::{ - auth::{account_can_modify_user, protect_account_route}, - usecase::{execute, UseCase}, - }, -}; - -pub async fn create_event_group_admin_controller( - http_req: HttpRequest, - path_params: web::Path, - body: actix_web_validator::Json, - ctx: web::Data, -) -> Result { - let account = protect_account_route(&http_req, &ctx).await?; - let user = account_can_modify_user(&account, &path_params.user_id, &ctx).await?; - - let body = body.0; - let usecase = CreateEventGroupUseCase { - parent_id: body.parent_id, - external_id: body.external_id, - user, - calendar_id: body.calendar_id, - }; - - execute(usecase, &ctx) - .await - .map(|group| HttpResponse::Created().json(APIResponse::new(group))) - .map_err(NitteiError::from) -} - -#[derive(Debug, Default)] -pub struct CreateEventGroupUseCase { - pub calendar_id: ID, - pub user: User, - pub parent_id: Option, - pub external_id: Option, -} - -#[derive(Debug, PartialEq)] -pub enum UseCaseError { - NotFound(ID), - StorageError, -} - -impl From for NitteiError { - fn from(e: UseCaseError) -> Self { - match e { - UseCaseError::NotFound(calendar_id) => Self::NotFound(format!( - "The calendar with id: {}, was not found.", - calendar_id - )), - UseCaseError::StorageError => Self::InternalError, - } - } -} - -impl From for UseCaseError { - fn from(_: anyhow::Error) -> Self { - UseCaseError::StorageError - } -} - -#[async_trait::async_trait(?Send)] -impl UseCase for CreateEventGroupUseCase { - type Response = EventGroup; - - type Error = UseCaseError; - - const NAME: &'static str = "CreateEvent"; - - async fn execute(&mut self, ctx: &NitteiContext) -> Result { - let calendar = ctx - .repos - .calendars - .find(&self.calendar_id) - .await - .map_err(|_| UseCaseError::StorageError)?; - let calendar = match calendar { - Some(calendar) if calendar.user_id == self.user.id => calendar, - _ => return Err(UseCaseError::NotFound(self.calendar_id.clone())), - }; - - let g = EventGroup { - id: Default::default(), - parent_id: self.parent_id.clone(), - external_id: self.external_id.clone(), - calendar_id: calendar.id.clone(), - user_id: self.user.id.clone(), - account_id: self.user.account_id.clone(), - }; - - ctx.repos.event_groups.insert(&g).await?; - - Ok(g) - } -} - -#[cfg(test)] -mod test { - use nittei_domain::{Account, Calendar, User}; - use nittei_infra::setup_context; - - use super::*; - - struct TestContext { - ctx: NitteiContext, - calendar: Calendar, - user: User, - } - - async fn setup() -> TestContext { - let ctx = setup_context().await.unwrap(); - let account = Account::default(); - ctx.repos.accounts.insert(&account).await.unwrap(); - let user = User::new(account.id.clone(), None); - ctx.repos.users.insert(&user).await.unwrap(); - let calendar = Calendar::new(&user.id, &account.id, None, None); - ctx.repos.calendars.insert(&calendar).await.unwrap(); - - TestContext { - user, - calendar, - ctx, - } - } - - #[actix_web::main] - #[test] - async fn creates_event_group() { - let TestContext { - ctx, - calendar, - user, - } = setup().await; - - let mut usecase = CreateEventGroupUseCase { - calendar_id: calendar.id.clone(), - user, - ..Default::default() - }; - - let res = usecase.execute(&ctx).await; - - assert!(res.is_ok()); - } - - #[actix_web::main] - #[test] - async fn rejects_invalid_calendar_id() { - let TestContext { - ctx, - calendar: _, - user, - } = setup().await; - - let mut usecase = CreateEventGroupUseCase { - user, - ..Default::default() - }; - - let res = usecase.execute(&ctx).await; - assert!(res.is_err()); - assert_eq!( - res.unwrap_err(), - UseCaseError::NotFound(usecase.calendar_id) - ); - } -} diff --git a/crates/api/src/event_group/delete_event_group.rs b/crates/api/src/event_group/delete_event_group.rs deleted file mode 100644 index 4dd4c7e8..00000000 --- a/crates/api/src/event_group/delete_event_group.rs +++ /dev/null @@ -1,87 +0,0 @@ -use actix_web::{web, HttpRequest, HttpResponse}; -use nittei_api_structs::delete_event_group::*; -use nittei_domain::{event_group::EventGroup, User, ID}; -use nittei_infra::NitteiContext; - -use crate::{ - error::NitteiError, - shared::{ - auth::{account_can_modify_event_group, account_can_modify_user, protect_account_route}, - usecase::{execute, UseCase}, - }, -}; - -pub async fn delete_event_group_admin_controller( - http_req: HttpRequest, - path_params: web::Path, - ctx: web::Data, -) -> Result { - let account = protect_account_route(&http_req, &ctx).await?; - let e = account_can_modify_event_group(&account, &path_params.event_group_id, &ctx).await?; - let user = account_can_modify_user(&account, &e.user_id, &ctx).await?; - - let usecase = DeleteEventGroupUseCase { - user, - event_group_id: e.id, - }; - - execute(usecase, &ctx) - .await - .map(|event| HttpResponse::Ok().json(APIResponse::new(event))) - .map_err(NitteiError::from) -} - -#[derive(Debug)] -pub struct DeleteEventGroupUseCase { - pub user: User, - pub event_group_id: ID, -} - -#[derive(Debug)] -pub enum UseCaseError { - NotFound(ID), - StorageError, -} - -impl From for NitteiError { - fn from(e: UseCaseError) -> Self { - match e { - UseCaseError::StorageError => Self::InternalError, - UseCaseError::NotFound(event_group_id) => Self::NotFound(format!( - "The event group with id: {}, was not found.", - event_group_id - )), - } - } -} - -#[async_trait::async_trait(?Send)] -impl UseCase for DeleteEventGroupUseCase { - type Response = EventGroup; - - type Error = UseCaseError; - - const NAME: &'static str = "DeleteEvent"; - - // TODO: use only one db call - async fn execute(&mut self, ctx: &NitteiContext) -> Result { - let event_group = ctx - .repos - .event_groups - .find(&self.event_group_id) - .await - .map_err(|_| UseCaseError::StorageError)?; - let g = match event_group { - Some(g) if g.user_id == self.user.id => g, - _ => return Err(UseCaseError::NotFound(self.event_group_id.clone())), - }; - - ctx.repos - .event_groups - .delete(&g.id) - .await - .map_err(|_| UseCaseError::StorageError)?; - - Ok(g) - } -} diff --git a/crates/api/src/event_group/get_event_group.rs b/crates/api/src/event_group/get_event_group.rs deleted file mode 100644 index 2e23459d..00000000 --- a/crates/api/src/event_group/get_event_group.rs +++ /dev/null @@ -1,77 +0,0 @@ -use actix_web::{web, HttpRequest, HttpResponse}; -use nittei_api_structs::get_event_group::*; -use nittei_domain::{event_group::EventGroup, ID}; -use nittei_infra::NitteiContext; - -use crate::{ - error::NitteiError, - shared::{ - auth::{account_can_modify_event_group, protect_account_route}, - usecase::{execute, UseCase}, - }, -}; - -pub async fn get_event_group_admin_controller( - http_req: HttpRequest, - path_params: web::Path, - ctx: web::Data, -) -> Result { - let account = protect_account_route(&http_req, &ctx).await?; - let e = account_can_modify_event_group(&account, &path_params.event_group_id, &ctx).await?; - - let usecase = GetEventGroupUseCase { - user_id: e.user_id, - event_group_id: e.id, - }; - - execute(usecase, &ctx) - .await - .map(|event_group| HttpResponse::Ok().json(APIResponse::new(event_group))) - .map_err(NitteiError::from) -} - -#[derive(Debug)] -pub struct GetEventGroupUseCase { - pub event_group_id: ID, - pub user_id: ID, -} - -#[derive(Debug)] -pub enum UseCaseError { - InternalError, - NotFound(ID), -} - -impl From for NitteiError { - fn from(e: UseCaseError) -> Self { - match e { - UseCaseError::InternalError => Self::InternalError, - UseCaseError::NotFound(event_id) => Self::NotFound(format!( - "The event group with id: {}, was not found.", - event_id - )), - } - } -} - -#[async_trait::async_trait(?Send)] -impl UseCase for GetEventGroupUseCase { - type Response = EventGroup; - - type Error = UseCaseError; - - const NAME: &'static str = "GetEvent"; - - async fn execute(&mut self, ctx: &NitteiContext) -> Result { - let e = ctx - .repos - .event_groups - .find(&self.event_group_id) - .await - .map_err(|_| UseCaseError::InternalError)?; - match e { - Some(event_group) if event_group.user_id == self.user_id => Ok(event_group), - _ => Err(UseCaseError::NotFound(self.event_group_id.clone())), - } - } -} diff --git a/crates/api/src/event_group/get_event_group_by_external_id.rs b/crates/api/src/event_group/get_event_group_by_external_id.rs deleted file mode 100644 index 3b901f16..00000000 --- a/crates/api/src/event_group/get_event_group_by_external_id.rs +++ /dev/null @@ -1,76 +0,0 @@ -use actix_web::{web, HttpRequest, HttpResponse}; -use nittei_api_structs::get_event_group_by_external_id::*; -use nittei_domain::{event_group::EventGroup, ID}; -use nittei_infra::NitteiContext; - -use crate::{ - error::NitteiError, - shared::{ - auth::protect_account_route, - usecase::{execute, UseCase}, - }, -}; - -pub async fn get_event_group_by_external_id_admin_controller( - http_req: HttpRequest, - path_params: web::Path, - ctx: web::Data, -) -> Result { - let account = protect_account_route(&http_req, &ctx).await?; - - let usecase = GetEventGroupByExternalIdUseCase { - account_id: account.id, - external_id: path_params.external_id.clone(), - }; - - execute(usecase, &ctx) - .await - .map(|event| HttpResponse::Ok().json(APIResponse::new(event))) - .map_err(NitteiError::from) -} - -#[derive(Debug)] -pub struct GetEventGroupByExternalIdUseCase { - pub external_id: String, - pub account_id: ID, -} - -#[derive(Debug)] -pub enum UseCaseError { - InternalError, - NotFound(String), -} - -impl From for NitteiError { - fn from(e: UseCaseError) -> Self { - match e { - UseCaseError::InternalError => Self::InternalError, - UseCaseError::NotFound(external_id) => Self::NotFound(format!( - "The event group with external_id: {}, was not found.", - external_id - )), - } - } -} - -#[async_trait::async_trait(?Send)] -impl UseCase for GetEventGroupByExternalIdUseCase { - type Response = EventGroup; - - type Error = UseCaseError; - - const NAME: &'static str = "GetEvent"; - - async fn execute(&mut self, ctx: &NitteiContext) -> Result { - let g = ctx - .repos - .event_groups - .get_by_external_id(&self.external_id) - .await - .map_err(|_| UseCaseError::InternalError)?; - match g { - Some(event_group) if event_group.account_id == self.account_id => Ok(event_group), - _ => Err(UseCaseError::NotFound(self.external_id.clone())), - } - } -} diff --git a/crates/api/src/event_group/mod.rs b/crates/api/src/event_group/mod.rs deleted file mode 100644 index a92110cb..00000000 --- a/crates/api/src/event_group/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -mod create_event_group; -mod delete_event_group; -mod get_event_group; -mod get_event_group_by_external_id; -mod update_event_group; - -use actix_web::web; -use create_event_group::create_event_group_admin_controller; -use delete_event_group::delete_event_group_admin_controller; -use get_event_group::get_event_group_admin_controller; -use get_event_group_by_external_id::get_event_group_by_external_id_admin_controller; -use update_event_group::update_event_group_admin_controller; - -// Configure the routes for the event_group module -pub fn configure_routes(cfg: &mut web::ServiceConfig) { - // Create an event group for a user (admin route) - cfg.route( - "/user/{user_id}/event_groups", - web::post().to(create_event_group_admin_controller), - ); - - // Get a specific event group by external id - cfg.route( - "/user/event_groups/external_id/{external_id}", - web::get().to(get_event_group_by_external_id_admin_controller), - ); - - // Get a specific event group by uid (admin route) - cfg.route( - "/user/event_groups/{event_group_id}", - web::get().to(get_event_group_admin_controller), - ); - - // Update an event group by uid (admin route) - cfg.route( - "/user/event_groups/{event_group_id}", - web::put().to(update_event_group_admin_controller), - ); - - // Delete an event group by uid (admin route) - cfg.route( - "/user/event_groups/{event_group_id}", - web::delete().to(delete_event_group_admin_controller), - ); -} diff --git a/crates/api/src/event_group/update_event_group.rs b/crates/api/src/event_group/update_event_group.rs deleted file mode 100644 index c3e1da06..00000000 --- a/crates/api/src/event_group/update_event_group.rs +++ /dev/null @@ -1,133 +0,0 @@ -use actix_web::{web, HttpRequest, HttpResponse}; -use nittei_api_structs::update_event_group::*; -use nittei_domain::{event_group::EventGroup, User, ID}; -use nittei_infra::NitteiContext; - -use crate::{ - error::NitteiError, - shared::{ - auth::{account_can_modify_event_group, account_can_modify_user, protect_account_route}, - usecase::{execute, UseCase}, - }, -}; - -pub async fn update_event_group_admin_controller( - http_req: HttpRequest, - body: web::Json, - path_params: web::Path, - ctx: web::Data, -) -> Result { - let account = protect_account_route(&http_req, &ctx).await?; - let e = account_can_modify_event_group(&account, &path_params.event_group_id, &ctx).await?; - let user = account_can_modify_user(&account, &e.user_id, &ctx).await?; - - let body = body.0; - let usecase = UpdateEventGroupUseCase { - user, - event_group_id: e.id, - parent_id: body.parent_id, - external_id: body.external_id, - }; - - execute(usecase, &ctx) - .await - .map(|event| HttpResponse::Ok().json(APIResponse::new(event))) - .map_err(NitteiError::from) -} - -#[derive(Debug, Default)] -pub struct UpdateEventGroupUseCase { - pub user: User, - pub event_group_id: ID, - - pub parent_id: Option, - pub external_id: Option, -} - -#[derive(Debug)] -pub enum UseCaseError { - NotFound(String, ID), - StorageError, -} - -impl From for NitteiError { - fn from(e: UseCaseError) -> Self { - match e { - UseCaseError::NotFound(entity, event_id) => Self::NotFound(format!( - "The {} with id: {}, was not found.", - entity, event_id - )), - UseCaseError::StorageError => Self::InternalError, - } - } -} - -#[async_trait::async_trait(?Send)] -impl UseCase for UpdateEventGroupUseCase { - type Response = EventGroup; - - type Error = UseCaseError; - - const NAME: &'static str = "UpdateGroupEvent"; - - async fn execute(&mut self, ctx: &NitteiContext) -> Result { - let UpdateEventGroupUseCase { - user, - event_group_id, - parent_id, - external_id, - } = self; - - let mut g = match ctx.repos.event_groups.find(event_group_id).await { - Ok(Some(event_group)) if event_group.user_id == user.id => event_group, - Ok(_) => { - return Err(UseCaseError::NotFound( - "Calendar Event".into(), - event_group_id.clone(), - )) - } - Err(e) => { - tracing::error!("Failed to get one event {:?}", e); - return Err(UseCaseError::StorageError); - } - }; - - if parent_id.is_some() { - g.parent_id.clone_from(parent_id); - } - - if external_id.is_some() { - g.external_id.clone_from(external_id); - } - - // e.updated = ctx.sys.get_timestamp_millis(); - - ctx.repos - .event_groups - .save(&g) - .await - .map(|_| g.clone()) - .map_err(|_| UseCaseError::StorageError) - } -} - -// #[cfg(test)] -// mod test { -// use nittei_infra::setup_context; - -// use super::*; - -// #[actix_web::main] -// #[test] -// async fn update_nonexisting_event() { -// let mut usecase = UpdateEventGroupUseCase { -// start_time: Some(DateTime::from_timestamp_millis(500).unwrap()), -// duration: Some(800), -// busy: Some(false), -// ..Default::default() -// }; -// let ctx = setup_context().await.unwrap(); -// let res = usecase.execute(&ctx).await; -// assert!(res.is_err()); -// } -// } diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 99384cd6..d452c480 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -2,7 +2,6 @@ mod account; mod calendar; mod error; mod event; -mod event_group; mod http_logger; mod job_schedulers; mod schedule; @@ -42,7 +41,6 @@ pub fn configure_server_api(cfg: &mut web::ServiceConfig) { account::configure_routes(cfg); calendar::configure_routes(cfg); event::configure_routes(cfg); - event_group::configure_routes(cfg); schedule::configure_routes(cfg); service::configure_routes(cfg); status::configure_routes(cfg); diff --git a/crates/api/src/shared/auth/mod.rs b/crates/api/src/shared/auth/mod.rs index dd5aa586..7fcd3557 100644 --- a/crates/api/src/shared/auth/mod.rs +++ b/crates/api/src/shared/auth/mod.rs @@ -5,7 +5,6 @@ pub use policy::{Permission, Policy}; pub use route_guards::{ account_can_modify_calendar, account_can_modify_event, - account_can_modify_event_group, account_can_modify_schedule, account_can_modify_user, protect_account_route, diff --git a/crates/api/src/shared/auth/route_guards.rs b/crates/api/src/shared/auth/route_guards.rs index fda9332d..86647774 100644 --- a/crates/api/src/shared/auth/route_guards.rs +++ b/crates/api/src/shared/auth/route_guards.rs @@ -1,14 +1,6 @@ use actix_web::HttpRequest; use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; -use nittei_domain::{ - event_group::EventGroup, - Account, - Calendar, - CalendarEvent, - Schedule, - User, - ID, -}; +use nittei_domain::{Account, Calendar, CalendarEvent, Schedule, User, ID}; use nittei_infra::NitteiContext; use serde::{Deserialize, Serialize}; use tracing::log::warn; @@ -263,23 +255,6 @@ pub async fn account_can_modify_event( } } -/// Used for account admin routes by checking that account -/// is not modifying an event group in another account -pub async fn account_can_modify_event_group( - account: &Account, - event_group_id: &ID, - ctx: &NitteiContext, -) -> Result { - match ctx.repos.event_groups.find(event_group_id).await { - Ok(Some(event_group)) if event_group.account_id == account.id => Ok(event_group), - Ok(_) => Err(NitteiError::NotFound(format!( - "Event group with id: {} was not found", - event_group_id - ))), - Err(_) => Err(NitteiError::InternalError), - } -} - /// Used for account admin routes by checking that account /// is not modifying a schedule in another account pub async fn account_can_modify_schedule( diff --git a/crates/api_structs/src/event/api.rs b/crates/api_structs/src/event/api.rs index 60af25c8..0c405e14 100644 --- a/crates/api_structs/src/event/api.rs +++ b/crates/api_structs/src/event/api.rs @@ -78,13 +78,18 @@ pub mod create_event { /// Optional parent event ID /// This is useful for external applications that need to link Nittei's events to a wider data model (e.g. a project, an order, etc.) + /// Example: If the event is a meeting, the parent ID could be the project ID (ObjectId, UUID or any other string) #[serde(default)] #[ts(optional)] #[validate(length(min = 1))] - pub parent_id: Option, + pub external_parent_id: Option, /// Optional external event ID /// This is useful for external applications that need to link Nittei's events to their own data models + /// Example: If the event is a meeting, the external ID could be the meeting ID in the external system + /// + /// Note that nothing prevents multiple events from having the same external ID + /// This can also be a way to link events together #[serde(default)] #[ts(optional)] #[validate(length(min = 1))] @@ -157,13 +162,6 @@ pub mod create_event { #[ts(optional)] pub service_id: Option, - /// Optional group UUID - /// Allows to group events together (e.g. a project, a team, etc.) - /// Default is None - #[serde(default)] - #[ts(optional)] - pub group_id: Option, - /// Optional metadata (e.g. {"key": "value"}) #[serde(default)] #[ts(optional)] @@ -253,17 +251,6 @@ pub mod get_event_by_external_id { pub external_id: String, } - /// Query parameters that can be used when getting an event by external ID - #[derive(Deserialize, Serialize, TS)] - #[serde(rename_all = "camelCase")] - #[ts(export, rename = "GetEventsByExternalIdQueryParams")] - pub struct QueryParams { - /// Optional flag to include the events that are from a group with the same external ID - #[serde(default)] - #[ts(optional)] - pub include_groups: Option, - } - #[derive(Serialize, TS)] #[serde(rename_all = "camelCase")] #[ts(export, rename = "GetEventsByExternalIdAPIResponse")] @@ -331,7 +318,7 @@ pub mod get_events_by_calendars { } pub mod search_events { - use nittei_domain::{DateTimeQuery, IDQuery, StringQuery}; + use nittei_domain::{DateTimeQuery, StringQuery}; use super::*; @@ -351,11 +338,7 @@ pub mod search_events { /// Optional query on parent ID (which is a string as it's an ID from an external system) #[ts(optional)] - pub parent_id: Option, - - /// Optional query on group ID - #[ts(optional)] - pub group_id: Option, + pub external_parent_id: Option, /// Optional query on start time - "lower than or equal", or "great than or equal" (UTC) #[ts(optional)] @@ -533,13 +516,6 @@ pub mod update_event { #[ts(optional)] pub service_id: Option, - /// Optional group UUID - /// Allows to group events together (e.g. a project, a team, etc.) - /// Default is None - #[serde(default)] - #[ts(optional)] - pub group_id: Option, - /// Optional list of exclusion dates for the recurrence rule #[serde(default)] #[ts(optional, type = "Array")] diff --git a/crates/api_structs/src/event/dtos.rs b/crates/api_structs/src/event/dtos.rs index 45ba3cef..2cbd00da 100644 --- a/crates/api_structs/src/event/dtos.rs +++ b/crates/api_structs/src/event/dtos.rs @@ -38,9 +38,16 @@ pub struct CalendarEventDTO { pub status: CalendarEventStatus, /// Optional parent event ID - pub parent_id: Option, + /// This is useful for external applications that need to link Nittei's events to a wider data model (e.g. a project, an order, etc.) + /// Example: If the event is a meeting, the parent ID could be the project ID (ObjectId, UUID or any other string) + pub external_parent_id: Option, /// Optional external ID + /// This is useful for external applications that need to link Nittei's events to their own data models + /// Example: If the event is a meeting, the external ID could be the meeting ID in the external system + /// + /// Note that nothing prevents multiple events from having the same external ID + /// This can also be a way to link events together pub external_id: Option, /// Start time of the event (UTC) @@ -91,9 +98,6 @@ pub struct CalendarEventDTO { /// UUID of the user pub user_id: ID, - /// Optional group ID - pub group_id: Option, - /// List of reminders pub reminders: Vec, @@ -112,7 +116,7 @@ impl CalendarEventDTO { location: event.location, all_day: event.all_day, status: event.status, - parent_id: event.parent_id, + external_parent_id: event.external_parent_id, external_id: event.external_id, start_time: event.start_time, end_time: event.end_time, @@ -126,7 +130,6 @@ impl CalendarEventDTO { original_start_time: event.original_start_time, calendar_id: event.calendar_id, user_id: event.user_id, - group_id: event.group_id, reminders: event.reminders, metadata: event.metadata, } diff --git a/crates/api_structs/src/event_group/api.rs b/crates/api_structs/src/event_group/api.rs deleted file mode 100644 index f33a1116..00000000 --- a/crates/api_structs/src/event_group/api.rs +++ /dev/null @@ -1,124 +0,0 @@ -use nittei_domain::{event_group::EventGroup, ID}; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; -use validator::Validate; - -use super::dtos::EventGroupDTO; - -/// Calendar event response object -#[derive(Deserialize, Serialize, TS)] -#[serde(rename_all = "camelCase")] -#[ts(export)] -pub struct EventGroupResponse { - /// Calendar event retrieved - pub event_group: EventGroupDTO, -} - -impl EventGroupResponse { - pub fn new(event_group: EventGroup) -> Self { - Self { - event_group: EventGroupDTO::new(event_group), - } - } -} - -pub mod create_event_group { - - use super::*; - - #[derive(Serialize, Deserialize)] - pub struct PathParams { - pub user_id: ID, - } - - /// Request body for creating an event - #[derive(Serialize, Deserialize, Validate, TS)] - #[serde(rename_all = "camelCase")] - #[ts(export, rename = "CreateEventGroupRequestBody")] - pub struct RequestBody { - /// UUID of the calendar where the event group will be created - pub calendar_id: ID, - - /// Optional parent event ID - /// This is useful for external applications that need to link Nittei's events to a wider data model (e.g. a project, an order, etc.) - #[serde(default)] - #[ts(optional)] - #[validate(length(min = 1))] - pub parent_id: Option, - - /// Optional external event ID - /// This is useful for external applications that need to link Nittei's events to their own data models - #[serde(default)] - #[ts(optional)] - #[validate(length(min = 1))] - pub external_id: Option, - } - - pub type APIResponse = EventGroupResponse; -} - -pub mod delete_event_group { - use super::*; - - #[derive(Deserialize)] - pub struct PathParams { - pub event_group_id: ID, - } - - pub type APIResponse = EventGroupResponse; -} - -pub mod get_event_group { - use super::*; - - #[derive(Deserialize)] - pub struct PathParams { - pub event_group_id: ID, - } - - pub type APIResponse = EventGroupResponse; -} - -pub mod get_event_group_by_external_id { - use super::*; - - #[derive(Deserialize)] - pub struct PathParams { - pub external_id: String, - } - - pub type APIResponse = EventGroupResponse; -} - -pub mod update_event_group { - - use super::*; - - /// Request body for updating an event - #[derive(Deserialize, Serialize, Validate, TS)] - #[serde(rename_all = "camelCase")] - #[ts(export, rename = "UpdateEventGroupRequestBody")] - pub struct RequestBody { - /// Optional parent event ID - /// This is useful for external applications that need to link Nittei's events to a wider data model (e.g. a project, an order, etc.) - #[serde(default)] - #[ts(optional)] - #[validate(length(min = 1))] - pub parent_id: Option, - - /// Optional external event ID - /// This is useful for external applications that need to link Nittei's events to their own data models - /// Default is None - #[serde(default)] - #[ts(optional)] - #[validate(length(min = 1))] - pub external_id: Option, - } - - #[derive(Deserialize)] - pub struct PathParams { - pub event_group_id: ID, - } - - pub type APIResponse = EventGroupResponse; -} diff --git a/crates/api_structs/src/event_group/dtos.rs b/crates/api_structs/src/event_group/dtos.rs deleted file mode 100644 index 84d224a6..00000000 --- a/crates/api_structs/src/event_group/dtos.rs +++ /dev/null @@ -1,37 +0,0 @@ -use nittei_domain::{event_group::EventGroup, ID}; -use serde::{Deserialize, Serialize}; -use ts_rs::TS; - -/// Calendar event object -#[derive(Debug, Deserialize, Serialize, Clone, TS)] -#[serde(rename_all = "camelCase")] -#[ts(export)] -pub struct EventGroupDTO { - /// UUID of the event - pub id: ID, - - /// Optional parent event ID - pub parent_id: Option, - - /// Optional external ID - pub external_id: Option, - - /// UUID of the calendar - pub calendar_id: ID, - - /// UUID of the user - pub user_id: ID, -} - -impl EventGroupDTO { - /// Create a new EventGroupDTO from an EventGroup - pub fn new(event_group: EventGroup) -> Self { - Self { - id: event_group.id, - parent_id: event_group.parent_id, - external_id: event_group.external_id, - calendar_id: event_group.calendar_id, - user_id: event_group.user_id, - } - } -} diff --git a/crates/api_structs/src/event_group/mod.rs b/crates/api_structs/src/event_group/mod.rs deleted file mode 100644 index 1b658d6d..00000000 --- a/crates/api_structs/src/event_group/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub(crate) mod api; -pub(crate) mod dtos; diff --git a/crates/api_structs/src/lib.rs b/crates/api_structs/src/lib.rs index bd7b2549..6bd60b59 100644 --- a/crates/api_structs/src/lib.rs +++ b/crates/api_structs/src/lib.rs @@ -1,7 +1,6 @@ mod account; mod calendar; mod event; -mod event_group; mod helpers; mod schedule; mod service; @@ -13,7 +12,6 @@ pub mod dtos { account::dtos::*, calendar::dtos::*, event::dtos::*, - event_group::dtos::*, schedule::dtos::*, service::dtos::*, user::dtos::*, @@ -23,7 +21,6 @@ pub use crate::{ account::api::*, calendar::api::*, event::api::*, - event_group::api::*, schedule::api::*, service::api::*, status::api::*, diff --git a/crates/domain/src/event.rs b/crates/domain/src/event.rs index 43c6cbe8..1487b518 100644 --- a/crates/domain/src/event.rs +++ b/crates/domain/src/event.rs @@ -56,7 +56,7 @@ impl TryFrom for CalendarEventStatus { #[serde(rename_all = "camelCase")] pub struct CalendarEvent { pub id: ID, - pub parent_id: Option, + pub external_parent_id: Option, pub external_id: Option, pub title: Option, pub description: Option, @@ -79,7 +79,6 @@ pub struct CalendarEvent { pub account_id: ID, pub reminders: Vec, pub service_id: Option, - pub group_id: Option, pub metadata: Option, } diff --git a/crates/infra/.sqlx/query-0088c2b930980add3076ab20ad0013fbc1f2a5c828edb319edab1b2d291db878.json b/crates/infra/.sqlx/query-0088c2b930980add3076ab20ad0013fbc1f2a5c828edb319edab1b2d291db878.json index 9aa1ecb2..4b89b35f 100644 --- a/crates/infra/.sqlx/query-0088c2b930980add3076ab20ad0013fbc1f2a5c828edb319edab1b2d291db878.json +++ b/crates/infra/.sqlx/query-0088c2b930980add3076ab20ad0013fbc1f2a5c828edb319edab1b2d291db878.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -166,7 +161,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-04752eb8015b9333981bc966d56eead8f4690d55c3c1d1dc03616f88731e63ee.json b/crates/infra/.sqlx/query-04752eb8015b9333981bc966d56eead8f4690d55c3c1d1dc03616f88731e63ee.json deleted file mode 100644 index 46aaa288..00000000 --- a/crates/infra/.sqlx/query-04752eb8015b9333981bc966d56eead8f4690d55c3c1d1dc03616f88731e63ee.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO calendar_events(\n event_uid,\n calendar_uid,\n parent_id,\n external_id,\n title,\n description,\n event_type,\n location,\n status,\n all_day,\n start_time,\n duration,\n end_time,\n busy,\n created,\n updated,\n recurrence,\n exdates,\n recurring_event_uid,\n original_start_time,\n reminders,\n service_uid,\n group_uid,\n metadata\n )\n VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24)\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid", - "Uuid", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Bool", - "Timestamptz", - "Int8", - "Timestamptz", - "Bool", - "Int8", - "Int8", - "Json", - "TimestamptzArray", - "Uuid", - "Timestamptz", - "Json", - "Uuid", - "Uuid", - "Jsonb" - ] - }, - "nullable": [] - }, - "hash": "04752eb8015b9333981bc966d56eead8f4690d55c3c1d1dc03616f88731e63ee" -} diff --git a/crates/infra/.sqlx/query-06df3ceb9d4cb19181312733eff427005768ac1df02c3c219242996daff2d6fe.json b/crates/infra/.sqlx/query-06df3ceb9d4cb19181312733eff427005768ac1df02c3c219242996daff2d6fe.json index 9c8028ca..41ff0226 100644 --- a/crates/infra/.sqlx/query-06df3ceb9d4cb19181312733eff427005768ac1df02c3c219242996daff2d6fe.json +++ b/crates/infra/.sqlx/query-06df3ceb9d4cb19181312733eff427005768ac1df02c3c219242996daff2d6fe.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -166,7 +161,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-09e9d9301a69be6bfe1e558fe7e9473c40af70dc79441291c72ec2922a2cbf95.json b/crates/infra/.sqlx/query-09e9d9301a69be6bfe1e558fe7e9473c40af70dc79441291c72ec2922a2cbf95.json deleted file mode 100644 index d45ffd1e..00000000 --- a/crates/infra/.sqlx/query-09e9d9301a69be6bfe1e558fe7e9473c40af70dc79441291c72ec2922a2cbf95.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT g.*, u.user_uid, account_uid FROM events_groups AS g\n INNER JOIN calendars AS c\n ON c.calendar_uid = g.calendar_uid\n INNER JOIN users AS u\n ON u.user_uid = c.user_uid\n WHERE g.group_uid = $1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "calendar_uid", - "type_info": "Uuid" - }, - { - "ordinal": 2, - "name": "parent_id", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "external_id", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "user_uid", - "type_info": "Uuid" - }, - { - "ordinal": 5, - "name": "account_uid", - "type_info": "Uuid" - } - ], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [ - false, - false, - true, - true, - false, - false - ] - }, - "hash": "09e9d9301a69be6bfe1e558fe7e9473c40af70dc79441291c72ec2922a2cbf95" -} diff --git a/crates/infra/.sqlx/query-1a18eb7670301b5335cbf19e02802ba307b2cd707444a2713b9c18014018358e.json b/crates/infra/.sqlx/query-1a18eb7670301b5335cbf19e02802ba307b2cd707444a2713b9c18014018358e.json new file mode 100644 index 00000000..15e01d1a --- /dev/null +++ b/crates/infra/.sqlx/query-1a18eb7670301b5335cbf19e02802ba307b2cd707444a2713b9c18014018358e.json @@ -0,0 +1,36 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO calendar_events(\n event_uid,\n calendar_uid,\n external_parent_id,\n external_id,\n title,\n description,\n event_type,\n location,\n status,\n all_day,\n start_time,\n duration,\n end_time,\n busy,\n created,\n updated,\n recurrence,\n exdates,\n recurring_event_uid,\n original_start_time,\n reminders,\n service_uid,\n metadata\n )\n VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23)\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Uuid", + "Text", + "Text", + "Text", + "Text", + "Text", + "Text", + "Text", + "Bool", + "Timestamptz", + "Int8", + "Timestamptz", + "Bool", + "Int8", + "Int8", + "Json", + "TimestamptzArray", + "Uuid", + "Timestamptz", + "Json", + "Uuid", + "Jsonb" + ] + }, + "nullable": [] + }, + "hash": "1a18eb7670301b5335cbf19e02802ba307b2cd707444a2713b9c18014018358e" +} diff --git a/crates/infra/.sqlx/query-246d53166723bcce5485835454c12b6ccb688c76e357fc81828e20e58ca917e3.json b/crates/infra/.sqlx/query-246d53166723bcce5485835454c12b6ccb688c76e357fc81828e20e58ca917e3.json deleted file mode 100644 index aea1c48b..00000000 --- a/crates/infra/.sqlx/query-246d53166723bcce5485835454c12b6ccb688c76e357fc81828e20e58ca917e3.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE calendar_events SET\n parent_id = $2,\n external_id = $3,\n title = $4,\n description = $5,\n event_type = $6,\n location = $7,\n status = $8,\n all_day = $9,\n start_time = $10,\n duration = $11,\n end_time = $12,\n busy = $13,\n created = $14,\n updated = $15,\n recurrence = $16,\n exdates = $17,\n recurring_event_uid = $18,\n original_start_time = $19,\n reminders = $20,\n service_uid = $21,\n group_uid = $22,\n metadata = $23\n WHERE event_uid = $1\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Text", - "Bool", - "Timestamptz", - "Int8", - "Timestamptz", - "Bool", - "Int8", - "Int8", - "Json", - "TimestamptzArray", - "Uuid", - "Timestamptz", - "Json", - "Uuid", - "Uuid", - "Jsonb" - ] - }, - "nullable": [] - }, - "hash": "246d53166723bcce5485835454c12b6ccb688c76e357fc81828e20e58ca917e3" -} diff --git a/crates/infra/.sqlx/query-3f602e58d6e5ee486a478708c57857ecda868db3abd1001a642c30549cb487b5.json b/crates/infra/.sqlx/query-3f602e58d6e5ee486a478708c57857ecda868db3abd1001a642c30549cb487b5.json index 5cb3d659..d379bc46 100644 --- a/crates/infra/.sqlx/query-3f602e58d6e5ee486a478708c57857ecda868db3abd1001a642c30549cb487b5.json +++ b/crates/infra/.sqlx/query-3f602e58d6e5ee486a478708c57857ecda868db3abd1001a642c30549cb487b5.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -163,7 +158,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-43604faa9bb10d9030db0a050b521d81e95b0e816df63beaf8a2e9b486068eb7.json b/crates/infra/.sqlx/query-43604faa9bb10d9030db0a050b521d81e95b0e816df63beaf8a2e9b486068eb7.json deleted file mode 100644 index b8a9c3c2..00000000 --- a/crates/infra/.sqlx/query-43604faa9bb10d9030db0a050b521d81e95b0e816df63beaf8a2e9b486068eb7.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n UPDATE events_groups SET\n parent_id = $2,\n external_id = $3\n WHERE group_uid = $1\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid", - "Text", - "Text" - ] - }, - "nullable": [] - }, - "hash": "43604faa9bb10d9030db0a050b521d81e95b0e816df63beaf8a2e9b486068eb7" -} diff --git a/crates/infra/.sqlx/query-501ef13a11ba2faacadd9a0dc484abdef01b81c9bba68250ed6ca2766be91adf.json b/crates/infra/.sqlx/query-501ef13a11ba2faacadd9a0dc484abdef01b81c9bba68250ed6ca2766be91adf.json index 0d565c1f..09bdd120 100644 --- a/crates/infra/.sqlx/query-501ef13a11ba2faacadd9a0dc484abdef01b81c9bba68250ed6ca2766be91adf.json +++ b/crates/infra/.sqlx/query-501ef13a11ba2faacadd9a0dc484abdef01b81c9bba68250ed6ca2766be91adf.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,21 +105,16 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" } @@ -152,7 +147,6 @@ true, true, true, - true, true ] }, diff --git a/crates/infra/.sqlx/query-6d8b17be58e55bd6c51aef757655973d637db2af2519cf59aa8a3b1ad9278308.json b/crates/infra/.sqlx/query-6d8b17be58e55bd6c51aef757655973d637db2af2519cf59aa8a3b1ad9278308.json index 228d5fc5..44c6dba3 100644 --- a/crates/infra/.sqlx/query-6d8b17be58e55bd6c51aef757655973d637db2af2519cf59aa8a3b1ad9278308.json +++ b/crates/infra/.sqlx/query-6d8b17be58e55bd6c51aef757655973d637db2af2519cf59aa8a3b1ad9278308.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -166,7 +161,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-7ca1e21500b0ee13496086f3258b98d9993127ede389814e6800822b0a7b7b57.json b/crates/infra/.sqlx/query-7ca1e21500b0ee13496086f3258b98d9993127ede389814e6800822b0a7b7b57.json deleted file mode 100644 index 3e1c400f..00000000 --- a/crates/infra/.sqlx/query-7ca1e21500b0ee13496086f3258b98d9993127ede389814e6800822b0a7b7b57.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT e.*, u.user_uid, account_uid \n FROM calendar_events AS e\n INNER JOIN calendars AS c\n ON c.calendar_uid = e.calendar_uid\n INNER JOIN users AS u\n ON u.user_uid = c.user_uid\n LEFT JOIN events_groups AS g\n ON g.group_uid = e.group_uid AND g.calendar_uid = e.calendar_uid\n WHERE u.account_uid = $1 AND g.external_id = $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "event_uid", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "calendar_uid", - "type_info": "Uuid" - }, - { - "ordinal": 2, - "name": "parent_id", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "title", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "location", - "type_info": "Text" - }, - { - "ordinal": 6, - "name": "all_day", - "type_info": "Bool" - }, - { - "ordinal": 7, - "name": "status", - "type_info": "Text" - }, - { - "ordinal": 8, - "name": "start_time", - "type_info": "Timestamptz" - }, - { - "ordinal": 9, - "name": "duration", - "type_info": "Int8" - }, - { - "ordinal": 10, - "name": "end_time", - "type_info": "Timestamptz" - }, - { - "ordinal": 11, - "name": "busy", - "type_info": "Bool" - }, - { - "ordinal": 12, - "name": "created", - "type_info": "Int8" - }, - { - "ordinal": 13, - "name": "updated", - "type_info": "Int8" - }, - { - "ordinal": 14, - "name": "recurrence", - "type_info": "Json" - }, - { - "ordinal": 15, - "name": "exdates", - "type_info": "TimestamptzArray" - }, - { - "ordinal": 16, - "name": "reminders", - "type_info": "Json" - }, - { - "ordinal": 17, - "name": "service_uid", - "type_info": "Uuid" - }, - { - "ordinal": 18, - "name": "metadata", - "type_info": "Jsonb" - }, - { - "ordinal": 19, - "name": "external_id", - "type_info": "Text" - }, - { - "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, - "name": "event_type", - "type_info": "Text" - }, - { - "ordinal": 22, - "name": "recurring_event_uid", - "type_info": "Uuid" - }, - { - "ordinal": 23, - "name": "original_start_time", - "type_info": "Timestamptz" - }, - { - "ordinal": 24, - "name": "user_uid", - "type_info": "Uuid" - }, - { - "ordinal": 25, - "name": "account_uid", - "type_info": "Uuid" - } - ], - "parameters": { - "Left": [ - "Uuid", - "Text" - ] - }, - "nullable": [ - false, - false, - true, - true, - true, - true, - false, - false, - false, - false, - false, - false, - false, - false, - true, - false, - true, - true, - false, - true, - true, - true, - true, - true, - false, - false - ] - }, - "hash": "7ca1e21500b0ee13496086f3258b98d9993127ede389814e6800822b0a7b7b57" -} diff --git a/crates/infra/.sqlx/query-933b6b34fb671b4ed95d4ce20d1cfffcd3014c10f352a53393ba321d0df83e2d.json b/crates/infra/.sqlx/query-933b6b34fb671b4ed95d4ce20d1cfffcd3014c10f352a53393ba321d0df83e2d.json index 8cf50389..c3859afb 100644 --- a/crates/infra/.sqlx/query-933b6b34fb671b4ed95d4ce20d1cfffcd3014c10f352a53393ba321d0df83e2d.json +++ b/crates/infra/.sqlx/query-933b6b34fb671b4ed95d4ce20d1cfffcd3014c10f352a53393ba321d0df83e2d.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -164,7 +159,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-a01aa726a30e658bca61f0ad0a12997c23f74627d2e5b3e13a1cd582bded7ea8.json b/crates/infra/.sqlx/query-a01aa726a30e658bca61f0ad0a12997c23f74627d2e5b3e13a1cd582bded7ea8.json index 679713e7..da2ba167 100644 --- a/crates/infra/.sqlx/query-a01aa726a30e658bca61f0ad0a12997c23f74627d2e5b3e13a1cd582bded7ea8.json +++ b/crates/infra/.sqlx/query-a01aa726a30e658bca61f0ad0a12997c23f74627d2e5b3e13a1cd582bded7ea8.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -165,7 +160,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-a3c5484db7b583f04582494294cac26d8a6269be7d3c01fcd576000346e762a6.json b/crates/infra/.sqlx/query-a3c5484db7b583f04582494294cac26d8a6269be7d3c01fcd576000346e762a6.json deleted file mode 100644 index 4b7c9ca1..00000000 --- a/crates/infra/.sqlx/query-a3c5484db7b583f04582494294cac26d8a6269be7d3c01fcd576000346e762a6.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n DELETE FROM events_groups AS g\n WHERE g.group_uid = $1\n RETURNING *\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "calendar_uid", - "type_info": "Uuid" - }, - { - "ordinal": 2, - "name": "parent_id", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "external_id", - "type_info": "Text" - } - ], - "parameters": { - "Left": [ - "Uuid" - ] - }, - "nullable": [ - false, - false, - true, - true - ] - }, - "hash": "a3c5484db7b583f04582494294cac26d8a6269be7d3c01fcd576000346e762a6" -} diff --git a/crates/infra/.sqlx/query-bff47dd65830b0b586feb4fba049cce0549c50166fb34fc91f4039f62cde6f13.json b/crates/infra/.sqlx/query-bff47dd65830b0b586feb4fba049cce0549c50166fb34fc91f4039f62cde6f13.json index b3cf708f..7e1ce3c3 100644 --- a/crates/infra/.sqlx/query-bff47dd65830b0b586feb4fba049cce0549c50166fb34fc91f4039f62cde6f13.json +++ b/crates/infra/.sqlx/query-bff47dd65830b0b586feb4fba049cce0549c50166fb34fc91f4039f62cde6f13.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -166,7 +161,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-c8d36057bc491a1940386c101401a212ef5f16390f85cdba3a334390486adebc.json b/crates/infra/.sqlx/query-c8d36057bc491a1940386c101401a212ef5f16390f85cdba3a334390486adebc.json deleted file mode 100644 index 0ef5af55..00000000 --- a/crates/infra/.sqlx/query-c8d36057bc491a1940386c101401a212ef5f16390f85cdba3a334390486adebc.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT g.*, u.user_uid, account_uid FROM events_groups AS g\n INNER JOIN calendars AS c\n ON c.calendar_uid = g.calendar_uid\n INNER JOIN users AS u\n ON u.user_uid = c.user_uid\n WHERE g.external_id = $1\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "calendar_uid", - "type_info": "Uuid" - }, - { - "ordinal": 2, - "name": "parent_id", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "external_id", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "user_uid", - "type_info": "Uuid" - }, - { - "ordinal": 5, - "name": "account_uid", - "type_info": "Uuid" - } - ], - "parameters": { - "Left": [ - "Text" - ] - }, - "nullable": [ - false, - false, - true, - true, - false, - false - ] - }, - "hash": "c8d36057bc491a1940386c101401a212ef5f16390f85cdba3a334390486adebc" -} diff --git a/crates/infra/.sqlx/query-d5a94d74eb91eb11f7a1fa61173aaa678a334810d03fe9e05cef730134bcaae4.json b/crates/infra/.sqlx/query-d5a94d74eb91eb11f7a1fa61173aaa678a334810d03fe9e05cef730134bcaae4.json index 17061851..3398f315 100644 --- a/crates/infra/.sqlx/query-d5a94d74eb91eb11f7a1fa61173aaa678a334810d03fe9e05cef730134bcaae4.json +++ b/crates/infra/.sqlx/query-d5a94d74eb91eb11f7a1fa61173aaa678a334810d03fe9e05cef730134bcaae4.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -165,7 +160,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-db24e838156e66fdff8694e040ca55f369f23b6e139e801f5b949e2b0d6a22c7.json b/crates/infra/.sqlx/query-db24e838156e66fdff8694e040ca55f369f23b6e139e801f5b949e2b0d6a22c7.json deleted file mode 100644 index 40e2c9d0..00000000 --- a/crates/infra/.sqlx/query-db24e838156e66fdff8694e040ca55f369f23b6e139e801f5b949e2b0d6a22c7.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO events_groups(\n group_uid,\n calendar_uid,\n parent_id,\n external_id\n )\n VALUES($1, $2, $3, $4)\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Uuid", - "Uuid", - "Text", - "Text" - ] - }, - "nullable": [] - }, - "hash": "db24e838156e66fdff8694e040ca55f369f23b6e139e801f5b949e2b0d6a22c7" -} diff --git a/crates/infra/.sqlx/query-dff6107515f942d02e2ca40164678d8ef1897aa84c8dc0a7a3ffca5a8747ef33.json b/crates/infra/.sqlx/query-dff6107515f942d02e2ca40164678d8ef1897aa84c8dc0a7a3ffca5a8747ef33.json deleted file mode 100644 index 3d7afcc9..00000000 --- a/crates/infra/.sqlx/query-dff6107515f942d02e2ca40164678d8ef1897aa84c8dc0a7a3ffca5a8747ef33.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n SELECT e.*, u.user_uid, account_uid \n FROM calendar_events AS e\n INNER JOIN calendars AS c\n ON c.calendar_uid = e.calendar_uid\n INNER JOIN users AS u\n ON u.user_uid = c.user_uid\n WHERE u.account_uid = $1 AND e.external_id = $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "event_uid", - "type_info": "Uuid" - }, - { - "ordinal": 1, - "name": "calendar_uid", - "type_info": "Uuid" - }, - { - "ordinal": 2, - "name": "parent_id", - "type_info": "Text" - }, - { - "ordinal": 3, - "name": "title", - "type_info": "Text" - }, - { - "ordinal": 4, - "name": "description", - "type_info": "Text" - }, - { - "ordinal": 5, - "name": "location", - "type_info": "Text" - }, - { - "ordinal": 6, - "name": "all_day", - "type_info": "Bool" - }, - { - "ordinal": 7, - "name": "status", - "type_info": "Text" - }, - { - "ordinal": 8, - "name": "start_time", - "type_info": "Timestamptz" - }, - { - "ordinal": 9, - "name": "duration", - "type_info": "Int8" - }, - { - "ordinal": 10, - "name": "end_time", - "type_info": "Timestamptz" - }, - { - "ordinal": 11, - "name": "busy", - "type_info": "Bool" - }, - { - "ordinal": 12, - "name": "created", - "type_info": "Int8" - }, - { - "ordinal": 13, - "name": "updated", - "type_info": "Int8" - }, - { - "ordinal": 14, - "name": "recurrence", - "type_info": "Json" - }, - { - "ordinal": 15, - "name": "exdates", - "type_info": "TimestamptzArray" - }, - { - "ordinal": 16, - "name": "reminders", - "type_info": "Json" - }, - { - "ordinal": 17, - "name": "service_uid", - "type_info": "Uuid" - }, - { - "ordinal": 18, - "name": "metadata", - "type_info": "Jsonb" - }, - { - "ordinal": 19, - "name": "external_id", - "type_info": "Text" - }, - { - "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, - "name": "event_type", - "type_info": "Text" - }, - { - "ordinal": 22, - "name": "recurring_event_uid", - "type_info": "Uuid" - }, - { - "ordinal": 23, - "name": "original_start_time", - "type_info": "Timestamptz" - }, - { - "ordinal": 24, - "name": "user_uid", - "type_info": "Uuid" - }, - { - "ordinal": 25, - "name": "account_uid", - "type_info": "Uuid" - } - ], - "parameters": { - "Left": [ - "Uuid", - "Text" - ] - }, - "nullable": [ - false, - false, - true, - true, - true, - true, - false, - false, - false, - false, - false, - false, - false, - false, - true, - false, - true, - true, - false, - true, - true, - true, - true, - true, - false, - false - ] - }, - "hash": "dff6107515f942d02e2ca40164678d8ef1897aa84c8dc0a7a3ffca5a8747ef33" -} diff --git a/crates/infra/.sqlx/query-e2942b19e8dd8c5de308e64bd6e4f587005e6d6e864dbe6c656bf5df5cdcb112.json b/crates/infra/.sqlx/query-e2942b19e8dd8c5de308e64bd6e4f587005e6d6e864dbe6c656bf5df5cdcb112.json index 148029dd..b545c703 100644 --- a/crates/infra/.sqlx/query-e2942b19e8dd8c5de308e64bd6e4f587005e6d6e864dbe6c656bf5df5cdcb112.json +++ b/crates/infra/.sqlx/query-e2942b19e8dd8c5de308e64bd6e4f587005e6d6e864dbe6c656bf5df5cdcb112.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -163,7 +158,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-e7da03c1fc42c828dee243bb04f6bd036fd7ed3a5c3712df228933b6bb3ffa4c.json b/crates/infra/.sqlx/query-e7da03c1fc42c828dee243bb04f6bd036fd7ed3a5c3712df228933b6bb3ffa4c.json index bdeb91f1..81d7bff3 100644 --- a/crates/infra/.sqlx/query-e7da03c1fc42c828dee243bb04f6bd036fd7ed3a5c3712df228933b6bb3ffa4c.json +++ b/crates/infra/.sqlx/query-e7da03c1fc42c828dee243bb04f6bd036fd7ed3a5c3712df228933b6bb3ffa4c.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -163,7 +158,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/.sqlx/query-fa9c5b0aad3b49a8303f3fdc1d6cbfbbacb1dc31d40f907a046e44a0a89dd285.json b/crates/infra/.sqlx/query-fa9c5b0aad3b49a8303f3fdc1d6cbfbbacb1dc31d40f907a046e44a0a89dd285.json new file mode 100644 index 00000000..5fd6cde7 --- /dev/null +++ b/crates/infra/.sqlx/query-fa9c5b0aad3b49a8303f3fdc1d6cbfbbacb1dc31d40f907a046e44a0a89dd285.json @@ -0,0 +1,35 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE calendar_events SET\n external_parent_id = $2,\n external_id = $3,\n title = $4,\n description = $5,\n event_type = $6,\n location = $7,\n status = $8,\n all_day = $9,\n start_time = $10,\n duration = $11,\n end_time = $12,\n busy = $13,\n created = $14,\n updated = $15,\n recurrence = $16,\n exdates = $17,\n recurring_event_uid = $18,\n original_start_time = $19,\n reminders = $20,\n service_uid = $21,\n metadata = $22\n WHERE event_uid = $1\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text", + "Text", + "Text", + "Text", + "Text", + "Text", + "Text", + "Bool", + "Timestamptz", + "Int8", + "Timestamptz", + "Bool", + "Int8", + "Int8", + "Json", + "TimestamptzArray", + "Uuid", + "Timestamptz", + "Json", + "Uuid", + "Jsonb" + ] + }, + "nullable": [] + }, + "hash": "fa9c5b0aad3b49a8303f3fdc1d6cbfbbacb1dc31d40f907a046e44a0a89dd285" +} diff --git a/crates/infra/.sqlx/query-fa9c71d7c78ea93dd35d0019993601a7d4a77756182a45647d381181eb0eafbd.json b/crates/infra/.sqlx/query-fa9c71d7c78ea93dd35d0019993601a7d4a77756182a45647d381181eb0eafbd.json index ca2998a8..f85f5896 100644 --- a/crates/infra/.sqlx/query-fa9c71d7c78ea93dd35d0019993601a7d4a77756182a45647d381181eb0eafbd.json +++ b/crates/infra/.sqlx/query-fa9c71d7c78ea93dd35d0019993601a7d4a77756182a45647d381181eb0eafbd.json @@ -15,7 +15,7 @@ }, { "ordinal": 2, - "name": "parent_id", + "name": "external_parent_id", "type_info": "Text" }, { @@ -105,31 +105,26 @@ }, { "ordinal": 20, - "name": "group_uid", - "type_info": "Uuid" - }, - { - "ordinal": 21, "name": "event_type", "type_info": "Text" }, { - "ordinal": 22, + "ordinal": 21, "name": "recurring_event_uid", "type_info": "Uuid" }, { - "ordinal": 23, + "ordinal": 22, "name": "original_start_time", "type_info": "Timestamptz" }, { - "ordinal": 24, + "ordinal": 23, "name": "user_uid", "type_info": "Uuid" }, { - "ordinal": 25, + "ordinal": 24, "name": "account_uid", "type_info": "Uuid" } @@ -163,7 +158,6 @@ true, true, true, - true, false, false ] diff --git a/crates/infra/migrations/20250218000000_simplify_calendar_events.sql b/crates/infra/migrations/20250218000000_simplify_calendar_events.sql new file mode 100644 index 00000000..ee69ba3b --- /dev/null +++ b/crates/infra/migrations/20250218000000_simplify_calendar_events.sql @@ -0,0 +1,18 @@ +-- Remove unique constraint on `external_id` column +-- We now allow multiple events to reference the same external object +ALTER TABLE + calendar_events DROP CONSTRAINT IF EXISTS calendar_events__external_id__unique; + +-- Create a normal index +CREATE INDEX IF NOT EXISTS idx_calendar_events_external_id ON calendar_events(external_id); + +-- Remove events groups +-- We will use the implicit grouping by external_id +ALTER TABLE + calendar_events DROP COLUMN IF EXISTS group_uid; + +DROP TABLE IF EXISTS events_groups; + +-- Rename `parent_id` to something more "external" +ALTER TABLE + calendar_events RENAME COLUMN parent_id TO external_parent_id; \ No newline at end of file diff --git a/crates/infra/src/repos/event/calendar_event/mod.rs b/crates/infra/src/repos/event/calendar_event/mod.rs index 082c25d3..794ad90a 100644 --- a/crates/infra/src/repos/event/calendar_event/mod.rs +++ b/crates/infra/src/repos/event/calendar_event/mod.rs @@ -1,7 +1,7 @@ mod postgres; use chrono::{DateTime, Utc}; -use nittei_domain::{CalendarEvent, DateTimeQuery, IDQuery, StringQuery, TimeSpan, ID}; +use nittei_domain::{CalendarEvent, DateTimeQuery, StringQuery, TimeSpan, ID}; pub use postgres::PostgresEventRepo; use crate::repos::shared::query_structs::MetadataFindQuery; @@ -27,8 +27,7 @@ pub struct SearchEventsForAccountParams { #[derive(Debug, Clone)] pub struct SearchEventsParams { - pub parent_id: Option, - pub group_id: Option, + pub external_parent_id: Option, pub start_time: Option, pub end_time: Option, pub status: Option, @@ -50,7 +49,6 @@ pub trait IEventRepo: Send + Sync { &self, account_uid: &ID, external_id: &str, - include_groups: bool, ) -> anyhow::Result>; async fn find_many(&self, event_ids: &[ID]) -> anyhow::Result>; async fn find_by_calendar( diff --git a/crates/infra/src/repos/event/calendar_event/postgres.rs b/crates/infra/src/repos/event/calendar_event/postgres.rs index 597f43de..72f52c13 100644 --- a/crates/infra/src/repos/event/calendar_event/postgres.rs +++ b/crates/infra/src/repos/event/calendar_event/postgres.rs @@ -1,7 +1,6 @@ use std::convert::{TryFrom, TryInto}; use chrono::{DateTime, Utc}; -use futures::future; use nittei_domain::{CalendarEvent, CalendarEventReminder, CalendarEventStatus, RRuleOptions, ID}; use serde_json::Value; use sqlx::{ @@ -20,7 +19,6 @@ use super::{ }; use crate::repos::{ apply_datetime_query, - apply_id_query, apply_string_query, shared::query_structs::MetadataFindQuery, }; @@ -68,7 +66,7 @@ struct EventRaw { calendar_uid: Uuid, user_uid: Uuid, account_uid: Uuid, - parent_id: Option, + external_parent_id: Option, external_id: Option, title: Option, description: Option, @@ -88,7 +86,6 @@ struct EventRaw { original_start_time: Option>, reminders: Option, service_uid: Option, - group_uid: Option, metadata: Value, } @@ -110,7 +107,7 @@ impl TryFrom for CalendarEvent { user_id: e.user_uid.into(), account_id: e.account_uid.into(), calendar_id: e.calendar_uid.into(), - parent_id: e.parent_id, + external_parent_id: e.external_parent_id, external_id: e.external_id, title: e.title, description: e.description, @@ -134,7 +131,6 @@ impl TryFrom for CalendarEvent { original_start_time: e.original_start_time, reminders, service_id: e.service_uid.map(|id| id.into()), - group_id: e.group_uid.map(|id| id.into()), metadata: serde_json::from_value(e.metadata)?, }) } @@ -150,7 +146,7 @@ impl IEventRepo for PostgresEventRepo { INSERT INTO calendar_events( event_uid, calendar_uid, - parent_id, + external_parent_id, external_id, title, description, @@ -170,14 +166,13 @@ impl IEventRepo for PostgresEventRepo { original_start_time, reminders, service_uid, - group_uid, metadata ) - VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24) + VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23) "#, e.id.as_ref(), e.calendar_id.as_ref(), - e.parent_id, + e.external_parent_id, e.external_id, e.title, e.description, @@ -197,7 +192,6 @@ impl IEventRepo for PostgresEventRepo { e.original_start_time, Json(&e.reminders) as _, e.service_id.as_ref().map(|id| id.as_ref()), - e.group_id.as_ref().map(|id| id.as_ref()), Json(&e.metadata) as _, ) .execute(&self.pool) @@ -218,7 +212,7 @@ impl IEventRepo for PostgresEventRepo { sqlx::query!( r#" UPDATE calendar_events SET - parent_id = $2, + external_parent_id = $2, external_id = $3, title = $4, description = $5, @@ -238,12 +232,11 @@ impl IEventRepo for PostgresEventRepo { original_start_time = $19, reminders = $20, service_uid = $21, - group_uid = $22, - metadata = $23 + metadata = $22 WHERE event_uid = $1 "#, e.id.as_ref(), - e.parent_id, + e.external_parent_id, e.external_id, e.title, e.description, @@ -263,7 +256,6 @@ impl IEventRepo for PostgresEventRepo { e.original_start_time, Json(&e.reminders) as _, e.service_id.as_ref().map(|id| id.as_ref()), - e.group_id.as_ref().map(|id| id.as_ref()), Json(&e.metadata) as _, ) .execute(&self.pool) @@ -343,66 +335,10 @@ impl IEventRepo for PostgresEventRepo { &self, account_uid: &ID, external_id: &str, - include_groups: bool, ) -> anyhow::Result> { - if include_groups { - // Define two queries and merge the results - let query_calendar_event = sqlx::query_as!( - EventRaw, - r#" - SELECT e.*, u.user_uid, account_uid - FROM calendar_events AS e - INNER JOIN calendars AS c - ON c.calendar_uid = e.calendar_uid - INNER JOIN users AS u - ON u.user_uid = c.user_uid - WHERE u.account_uid = $1 AND e.external_id = $2 - "#, - account_uid.as_ref(), - external_id - ); - - let query_calendar_events_from_group = sqlx::query_as!( - EventRaw, - r#" - SELECT e.*, u.user_uid, account_uid - FROM calendar_events AS e - INNER JOIN calendars AS c - ON c.calendar_uid = e.calendar_uid - INNER JOIN users AS u - ON u.user_uid = c.user_uid - LEFT JOIN events_groups AS g - ON g.group_uid = e.group_uid AND g.calendar_uid = e.calendar_uid - WHERE u.account_uid = $1 AND g.external_id = $2 - "#, - account_uid.as_ref(), - external_id - ); - - // Execute both queries in parallel - let (result1, result2) = future::try_join( - query_calendar_event.fetch_all(&self.pool), - query_calendar_events_from_group.fetch_all(&self.pool), - ) - .await - .inspect_err(|err| { - error!( - "Find calendar event (with group) with external_id: {:?} failed. DB returned error: {:?}", - external_id, err - ); - })?; - - // Merge the results - let mut all_events = Vec::with_capacity(result1.len() + result2.len()); - all_events.extend(result1); - all_events.extend(result2); - - // Convert the results to CalendarEvent - all_events.into_iter().map(|e| e.try_into()).collect() - } else { - sqlx::query_as!( - EventRaw, - r#" + sqlx::query_as!( + EventRaw, + r#" SELECT e.*, u.user_uid, account_uid FROM calendar_events AS e INNER JOIN calendars AS c ON c.calendar_uid = e.calendar_uid @@ -410,21 +346,20 @@ impl IEventRepo for PostgresEventRepo { ON u.user_uid = c.user_uid WHERE u.account_uid = $1 AND e.external_id = $2 "#, - account_uid.as_ref(), - external_id, - ) - .fetch_all(&self.pool) - .await - .inspect_err(|err| { - error!( - "Find calendar event with external_id: {:?} failed. DB returned error: {:?}", - external_id, err - ); - })? - .into_iter() - .map(|e| e.try_into()) - .collect() - } + account_uid.as_ref(), + external_id, + ) + .fetch_all(&self.pool) + .await + .inspect_err(|err| { + error!( + "Find calendar event with external_id: {:?} failed. DB returned error: {:?}", + external_id, err + ); + })? + .into_iter() + .map(|e| e.try_into()) + .collect() } #[instrument] @@ -652,14 +587,8 @@ impl IEventRepo for PostgresEventRepo { apply_string_query( &mut query, - "parent_id", - ¶ms.search_events_params.parent_id, - ); - - apply_id_query( - &mut query, - "group_uid", - ¶ms.search_events_params.group_id, + "external_parent_id", + ¶ms.search_events_params.external_parent_id, ); apply_datetime_query( @@ -734,14 +663,8 @@ impl IEventRepo for PostgresEventRepo { apply_string_query( &mut query, - "parent_id", - ¶ms.search_events_params.parent_id, - ); - - apply_id_query( - &mut query, - "group_uid", - ¶ms.search_events_params.group_id, + "external_parent_id", + ¶ms.search_events_params.external_parent_id, ); apply_datetime_query( diff --git a/crates/infra/src/repos/event/event_group/mod.rs b/crates/infra/src/repos/event/event_group/mod.rs deleted file mode 100644 index 45bb74b0..00000000 --- a/crates/infra/src/repos/event/event_group/mod.rs +++ /dev/null @@ -1,119 +0,0 @@ -mod postgres; - -use nittei_domain::{event_group::EventGroup, ID}; -pub use postgres::PostgresEventGroupRepo; - -#[async_trait::async_trait] -pub trait IEventGroupRepo: Send + Sync { - async fn insert(&self, e: &EventGroup) -> anyhow::Result<()>; - async fn save(&self, e: &EventGroup) -> anyhow::Result<()>; - async fn find(&self, group_id: &ID) -> anyhow::Result>; - async fn get_by_external_id(&self, external_id: &str) -> anyhow::Result>; - async fn delete(&self, group_id: &ID) -> anyhow::Result<()>; -} - -#[cfg(test)] -mod tests { - use nittei_domain::{event_group::EventGroup, Account, Calendar, User, ID}; - - use crate::{setup_context, NitteiContext}; - - fn generate_default_event_group(account_id: &ID, calendar_id: &ID, user_id: &ID) -> EventGroup { - EventGroup { - account_id: account_id.clone(), - calendar_id: calendar_id.clone(), - user_id: user_id.clone(), - ..Default::default() - } - } - - struct TestContext { - ctx: NitteiContext, - account: Account, - calendar: Calendar, - user: User, - } - - async fn setup() -> TestContext { - let ctx = setup_context().await.unwrap(); - let account = Account::default(); - ctx.repos.accounts.insert(&account).await.unwrap(); - let user = User::new(account.id.clone(), None); - ctx.repos.users.insert(&user).await.unwrap(); - let calendar = Calendar::new(&user.id, &account.id, None, None); - ctx.repos.calendars.insert(&calendar).await.unwrap(); - - TestContext { - account, - calendar, - user, - ctx, - } - } - - #[tokio::test] - async fn create_and_delete() { - let TestContext { - ctx, - account, - calendar, - user, - } = setup().await; - let event_group = generate_default_event_group(&account.id, &calendar.id, &user.id); - - // Insert - assert!(ctx.repos.event_groups.insert(&event_group).await.is_ok()); - - // Get - let get_event_group_res = ctx - .repos - .event_groups - .find(&event_group.id) - .await - .unwrap() - .unwrap(); - assert!(get_event_group_res.eq(&event_group)); - - // Delete - let delete_res = ctx.repos.event_groups.delete(&event_group.id).await; - assert!(delete_res.is_ok()); - - // Find - assert!(ctx - .repos - .event_groups - .find(&event_group.id) - .await - .unwrap() - .is_none()); - } - - #[tokio::test] - async fn update() { - let TestContext { - ctx, - account, - calendar, - user, - } = setup().await; - let mut event_group = generate_default_event_group(&account.id, &calendar.id, &user.id); - - // Insert - assert!(ctx.repos.event_groups.insert(&event_group).await.is_ok()); - - event_group.external_id = Some("test".to_string()); - - // Save - assert!(ctx.repos.event_groups.save(&event_group).await.is_ok()); - - // Find - assert!(ctx - .repos - .event_groups - .find(&event_group.id) - .await - .unwrap() - .expect("To be event_group") - .eq(&event_group)); - } -} diff --git a/crates/infra/src/repos/event/event_group/postgres.rs b/crates/infra/src/repos/event/event_group/postgres.rs deleted file mode 100644 index 60522953..00000000 --- a/crates/infra/src/repos/event/event_group/postgres.rs +++ /dev/null @@ -1,168 +0,0 @@ -use nittei_domain::{event_group::EventGroup, ID}; -use sqlx::{FromRow, PgPool}; -use tracing::{error, instrument}; - -use super::IEventGroupRepo; - -#[derive(Debug)] -pub struct PostgresEventGroupRepo { - pool: PgPool, -} - -impl PostgresEventGroupRepo { - pub fn new(pool: PgPool) -> Self { - Self { pool } - } -} - -#[derive(Debug, FromRow)] -struct EventGroupRaw { - pub group_uid: ID, - pub calendar_uid: ID, - pub user_uid: ID, - pub account_uid: ID, - pub parent_id: Option, - pub external_id: Option, -} - -impl From for EventGroup { - fn from(e: EventGroupRaw) -> Self { - Self { - id: e.group_uid, - calendar_id: e.calendar_uid, - user_id: e.user_uid, - account_id: e.account_uid, - parent_id: e.parent_id, - external_id: e.external_id, - } - } -} - -#[async_trait::async_trait] -impl IEventGroupRepo for PostgresEventGroupRepo { - #[instrument] - async fn insert(&self, e: &EventGroup) -> anyhow::Result<()> { - sqlx::query!( - r#" - INSERT INTO events_groups( - group_uid, - calendar_uid, - parent_id, - external_id - ) - VALUES($1, $2, $3, $4) - "#, - e.id.as_ref(), - e.calendar_id.as_ref(), - e.parent_id, - e.external_id, - ) - .execute(&self.pool) - .await - .inspect_err(|err| { - error!( - "Unable to insert event_group: {:?}. DB returned error: {:?}", - e, err - ); - })?; - - Ok(()) - } - - #[instrument] - async fn save(&self, e: &EventGroup) -> anyhow::Result<()> { - sqlx::query!( - r#" - UPDATE events_groups SET - parent_id = $2, - external_id = $3 - WHERE group_uid = $1 - "#, - e.id.as_ref(), - e.parent_id, - e.external_id, - ) - .execute(&self.pool) - .await - .inspect_err(|err| { - error!( - "Unable to save event_group: {:?}. DB returned error: {:?}", - e, err - ); - })?; - - Ok(()) - } - - #[instrument] - async fn find(&self, group_id: &ID) -> anyhow::Result> { - Ok(sqlx::query_as!( - EventGroupRaw, - r#" - SELECT g.*, u.user_uid, account_uid FROM events_groups AS g - INNER JOIN calendars AS c - ON c.calendar_uid = g.calendar_uid - INNER JOIN users AS u - ON u.user_uid = c.user_uid - WHERE g.group_uid = $1 - "#, - group_id.as_ref(), - ) - .fetch_optional(&self.pool) - .await - .inspect_err(|err| { - error!( - "Find event_group with id: {:?} failed. DB returned error: {:?}", - group_id, err - ); - })? - .map(|e| e.into())) - } - - #[instrument] - async fn get_by_external_id(&self, external_id: &str) -> anyhow::Result> { - Ok(sqlx::query_as!( - EventGroupRaw, - r#" - SELECT g.*, u.user_uid, account_uid FROM events_groups AS g - INNER JOIN calendars AS c - ON c.calendar_uid = g.calendar_uid - INNER JOIN users AS u - ON u.user_uid = c.user_uid - WHERE g.external_id = $1 - "#, - external_id, - ) - .fetch_optional(&self.pool) - .await - .inspect_err(|err| { - error!( - "Find events_groups with external_id: {:?} failed. DB returned error: {:?}", - external_id, err - ); - })? - .map(|e| e.into())) - } - - #[instrument] - async fn delete(&self, group_id: &ID) -> anyhow::Result<()> { - sqlx::query!( - r#" - DELETE FROM events_groups AS g - WHERE g.group_uid = $1 - RETURNING * - "#, - group_id.as_ref(), - ) - .fetch_optional(&self.pool) - .await - .inspect_err(|e| { - error!( - "Delete events_groups with id: {:?} failed. DB returned error: {:?}", - group_id, e - ); - })? - .ok_or_else(|| anyhow::Error::msg("Unable to delete event_group")) - .map(|_| ()) - } -} diff --git a/crates/infra/src/repos/event/mod.rs b/crates/infra/src/repos/event/mod.rs index e0a88f31..664ef374 100644 --- a/crates/infra/src/repos/event/mod.rs +++ b/crates/infra/src/repos/event/mod.rs @@ -1,5 +1,4 @@ mod calendar_event; -mod event_group; mod event_reminders_expansion_jobs; mod event_synced; mod reminder; @@ -11,7 +10,6 @@ pub use calendar_event::{ SearchEventsForUserParams, SearchEventsParams, }; -pub use event_group::{IEventGroupRepo, PostgresEventGroupRepo}; pub use event_reminders_expansion_jobs::{ IEventRemindersGenerationJobsRepo, PostgresEventReminderGenerationJobsRepo, diff --git a/crates/infra/src/repos/mod.rs b/crates/infra/src/repos/mod.rs index 56ea114f..3c67c41c 100644 --- a/crates/infra/src/repos/mod.rs +++ b/crates/infra/src/repos/mod.rs @@ -21,12 +21,10 @@ use anyhow::Context; use calendar::{ICalendarRepo, PostgresCalendarRepo}; use calendar_synced::{ICalendarSyncedRepo, PostgresCalendarSyncedRepo}; use event::{ - IEventGroupRepo, IEventRemindersGenerationJobsRepo, IEventRepo, IEventSyncedRepo, IReminderRepo, - PostgresEventGroupRepo, PostgresEventReminderGenerationJobsRepo, PostgresEventRepo, PostgresEventSyncedRepo, @@ -58,7 +56,6 @@ pub struct Repos { pub events: Arc, pub event_reminders_generation_jobs: Arc, pub event_synced: Arc, - pub event_groups: Arc, pub schedules: Arc, pub reminders: Arc, pub reservations: Arc, @@ -114,7 +111,6 @@ impl Repos { calendar_synced: Arc::new(PostgresCalendarSyncedRepo::new(pool.clone())), events: Arc::new(PostgresEventRepo::new(pool.clone())), event_synced: Arc::new(PostgresEventSyncedRepo::new(pool.clone())), - event_groups: Arc::new(PostgresEventGroupRepo::new(pool.clone())), users: Arc::new(PostgresUserRepo::new(pool.clone())), user_integrations: Arc::new(PostgresUserIntegrationRepo::new(pool.clone())), services: Arc::new(PostgresServiceRepo::new(pool.clone())), diff --git a/crates/infra/src/repos/shared/query_structs.rs b/crates/infra/src/repos/shared/query_structs.rs index 63ba4e6b..deb0a41a 100644 --- a/crates/infra/src/repos/shared/query_structs.rs +++ b/crates/infra/src/repos/shared/query_structs.rs @@ -21,6 +21,7 @@ pub struct MetadataFindQuery { /// This can only be used for fields that are UUIDs /// /// This effectively mutates the query_builder ! +#[allow(dead_code)] pub fn apply_id_query( query_builder: &mut sqlx::QueryBuilder<'_, Postgres>, field_name: &str,