@dv4resi/dvss-backend-module-calendar-im 0.0.4 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -976,8 +976,16 @@ var GET_PAYMENTS_SORTING_ENUM = /* @__PURE__ */ (function(GET_PAYMENTS_SORTING_E
976
976
  GET_PAYMENTS_SORTING_ENUM2["AMOUNT"] = "AMOUNT";
977
977
  GET_PAYMENTS_SORTING_ENUM2["NOTES"] = "NOTES";
978
978
  GET_PAYMENTS_SORTING_ENUM2["PAYMENT_MODE"] = "PAYMENT_MODE";
979
+ GET_PAYMENTS_SORTING_ENUM2["CREATED_TIME"] = "CREATED_TIME";
979
980
  return GET_PAYMENTS_SORTING_ENUM2;
980
981
  })({});
982
+ var EVENT_INSTANCE_KIND = /* @__PURE__ */ (function(EVENT_INSTANCE_KIND2) {
983
+ EVENT_INSTANCE_KIND2["SINGLE"] = "SINGLE";
984
+ EVENT_INSTANCE_KIND2["SERIES_MASTER"] = "SERIES_MASTER";
985
+ EVENT_INSTANCE_KIND2["OCCURRENCE"] = "OCCURRENCE";
986
+ EVENT_INSTANCE_KIND2["EXCEPTION"] = "EXCEPTION";
987
+ return EVENT_INSTANCE_KIND2;
988
+ })({});
981
989
 
982
990
  // ../../packages/dvss-integration-libs/src/integration-operation-skeletons/capabilities/wellness/wellness-management.base.ts
983
991
  var BaseWellnessManagement = class {
@@ -3834,184 +3842,215 @@ exports.MicrosoftApiClientService = _ts_decorate27([
3834
3842
  typeof exports.TrafficGatewayService === "undefined" ? Object : exports.TrafficGatewayService
3835
3843
  ])
3836
3844
  ], exports.MicrosoftApiClientService);
3837
-
3838
- // ../../packages/dvss-integration-microsoft/src/capabilities/booking-management/booking-management.mapper.ts
3839
- var GRAPH_EVENT_KNOWN_KEYS = /* @__PURE__ */ new Set([
3840
- "id",
3841
- "subject",
3842
- "body",
3843
- "start",
3844
- "end",
3845
- "location",
3846
- "showAs",
3847
- "isCancelled",
3848
- "recurrence",
3849
- "attendees",
3850
- "organizer"
3851
- ]);
3852
3845
  var GRAPH_RESOURCE_ATTENDEE_TYPE = "resource";
3846
+ var GRAPH_WEEKDAY = {
3847
+ [models.DAY_OF_WEEK.SUN]: "sunday",
3848
+ [models.DAY_OF_WEEK.MON]: "monday",
3849
+ [models.DAY_OF_WEEK.TUE]: "tuesday",
3850
+ [models.DAY_OF_WEEK.WED]: "wednesday",
3851
+ [models.DAY_OF_WEEK.THU]: "thursday",
3852
+ [models.DAY_OF_WEEK.FRI]: "friday",
3853
+ [models.DAY_OF_WEEK.SAT]: "saturday"
3854
+ };
3855
+ var GRAPH_MONTHLY_INDEX = {
3856
+ [models.SCHEDULE_MONTHLY_UNIT.FIRST]: "first",
3857
+ [models.SCHEDULE_MONTHLY_UNIT.SECOND]: "second",
3858
+ [models.SCHEDULE_MONTHLY_UNIT.THIRD]: "third",
3859
+ [models.SCHEDULE_MONTHLY_UNIT.FOURTH]: "fourth",
3860
+ [models.SCHEDULE_MONTHLY_UNIT.LAST]: "last"
3861
+ };
3862
+ var GRAPH_TYPE_TO_INSTANCE_KIND = {
3863
+ singleInstance: EVENT_INSTANCE_KIND.SINGLE,
3864
+ seriesMaster: EVENT_INSTANCE_KIND.SERIES_MASTER,
3865
+ occurrence: EVENT_INSTANCE_KIND.OCCURRENCE,
3866
+ exception: EVENT_INSTANCE_KIND.EXCEPTION
3867
+ };
3853
3868
  function toGraphEvent(event, options) {
3854
3869
  const graph = {};
3855
- if (event.subject !== void 0) {
3856
- graph.subject = event.subject;
3870
+ if (event.name !== void 0) {
3871
+ graph.subject = event.name;
3857
3872
  }
3858
- if (event.body !== void 0) {
3873
+ const body = event.description ?? event.notes ?? void 0;
3874
+ if (body !== void 0) {
3859
3875
  graph.body = {
3860
3876
  contentType: "text",
3861
- content: event.body
3877
+ content: body
3862
3878
  };
3863
3879
  }
3864
- if (event.start !== void 0) {
3880
+ if (event.bookingStartDateLabel !== void 0) {
3865
3881
  graph.start = {
3866
- dateTime: event.start.dateTime,
3867
- timeZone: event.start.timeZone
3882
+ dateTime: toGraphDateTime(event.bookingStartDateLabel, event.bookingStartTimeLabel, event.isFullDay),
3883
+ timeZone: event.timeZone ?? ""
3868
3884
  };
3869
3885
  }
3870
- if (event.end !== void 0) {
3886
+ if (event.bookingEndDateLabel !== void 0) {
3871
3887
  graph.end = {
3872
- dateTime: event.end.dateTime,
3873
- timeZone: event.end.timeZone
3888
+ dateTime: toGraphDateTime(event.bookingEndDateLabel, event.bookingEndTimeLabel, event.isFullDay),
3889
+ timeZone: event.timeZone ?? ""
3874
3890
  };
3875
3891
  }
3876
- if (event.location !== void 0) {
3877
- graph.location = {
3878
- displayName: event.location
3879
- };
3892
+ if (event.isFullDay !== void 0) {
3893
+ graph.isAllDay = event.isFullDay;
3880
3894
  }
3881
- if (event.showAs !== void 0) {
3882
- graph.showAs = event.showAs;
3895
+ if (event.isRecurring && event.schedule) {
3896
+ const recurrence = scheduleToGraphRecurrence(event.schedule, {
3897
+ startDate: event.bookingStartDateLabel,
3898
+ endDate: event.seriesEndDateLabel ?? event.bookingEndDateLabel
3899
+ });
3900
+ if (recurrence) {
3901
+ graph.recurrence = recurrence;
3902
+ }
3883
3903
  }
3884
- if (event.isCancelled !== void 0) {
3885
- graph.isCancelled = event.isCancelled;
3904
+ const attendees = buildGraphAttendees(event, options?.targetMailbox);
3905
+ if (attendees.length > 0) {
3906
+ graph.attendees = attendees;
3886
3907
  }
3887
- if (event.recurrence !== void 0) {
3888
- graph.recurrence = toGraphRecurrence(event.recurrence);
3908
+ return graph;
3909
+ }
3910
+ __name(toGraphEvent, "toGraphEvent");
3911
+ function spaceMailboxesFromItems(items) {
3912
+ const out = [];
3913
+ const seen = /* @__PURE__ */ new Set();
3914
+ for (const item of items ?? []) {
3915
+ const isSpace = item.resources?.some((resource) => resource.resourceType === models.OFFERING_RESOURCE_TYPE.SPACE);
3916
+ const email = item.externalId?.trim();
3917
+ const key = email?.toLowerCase();
3918
+ if (isSpace && email && key && !seen.has(key)) {
3919
+ seen.add(key);
3920
+ out.push(email);
3921
+ }
3889
3922
  }
3890
- if (event.attendees !== void 0) {
3891
- graph.attendees = event.attendees.map((attendee) => {
3892
- const mapped = {
3893
- emailAddress: omitUndefined({
3894
- address: attendee.email,
3895
- name: attendee.name
3896
- })
3897
- };
3898
- if (attendee.type !== void 0) {
3899
- mapped.type = attendee.type;
3900
- }
3901
- return mapped;
3923
+ return out;
3924
+ }
3925
+ __name(spaceMailboxesFromItems, "spaceMailboxesFromItems");
3926
+ function buildGraphAttendees(event, targetMailbox) {
3927
+ const target = targetMailbox?.trim().toLowerCase();
3928
+ const seen = new Set(target ? [
3929
+ target
3930
+ ] : []);
3931
+ const attendees = [];
3932
+ const add = /* @__PURE__ */ __name((email, type) => {
3933
+ const key = email?.trim().toLowerCase();
3934
+ if (!key || seen.has(key)) {
3935
+ return;
3936
+ }
3937
+ seen.add(key);
3938
+ attendees.push({
3939
+ emailAddress: {
3940
+ address: email.trim()
3941
+ },
3942
+ type
3902
3943
  });
3944
+ }, "add");
3945
+ for (const email of [
3946
+ ...event.requestedForIds ?? [],
3947
+ ...event.recipientIds ?? []
3948
+ ]) {
3949
+ add(email, "required");
3903
3950
  }
3904
- const resourceId = options?.resourceId?.trim();
3905
- if (resourceId) {
3906
- const isAlreadyInvited = graph.attendees?.some((attendee) => attendee.emailAddress?.address?.toLowerCase() === resourceId.toLowerCase());
3907
- if (isAlreadyInvited !== true) {
3908
- graph.attendees = [
3909
- ...graph.attendees ?? [],
3910
- {
3911
- emailAddress: {
3912
- address: resourceId
3913
- },
3914
- type: GRAPH_RESOURCE_ATTENDEE_TYPE
3915
- }
3916
- ];
3917
- }
3951
+ for (const email of spaceMailboxesFromItems(event.items)) {
3952
+ add(email, GRAPH_RESOURCE_ATTENDEE_TYPE);
3918
3953
  }
3919
- return graph;
3954
+ return attendees;
3920
3955
  }
3921
- __name(toGraphEvent, "toGraphEvent");
3922
- function toGraphRecurrence(recurrence) {
3923
- return {
3924
- pattern: omitUndefined({
3925
- type: recurrence.pattern.type,
3926
- interval: recurrence.pattern.interval,
3927
- daysOfWeek: recurrence.pattern.daysOfWeek,
3928
- firstDayOfWeek: recurrence.pattern.firstDayOfWeek,
3929
- dayOfMonth: recurrence.pattern.dayOfMonth,
3930
- month: recurrence.pattern.month,
3931
- index: recurrence.pattern.index
3932
- }),
3933
- range: omitUndefined({
3934
- type: recurrence.range.type,
3935
- startDate: recurrence.range.startDate,
3936
- endDate: recurrence.range.endDate,
3937
- numberOfOccurrences: recurrence.range.numberOfOccurrences,
3938
- recurrenceTimeZone: recurrence.range.recurrenceTimeZone
3939
- })
3956
+ __name(buildGraphAttendees, "buildGraphAttendees");
3957
+ function scheduleToGraphRecurrence(schedule, window) {
3958
+ if (!window.startDate || !window.endDate) {
3959
+ return void 0;
3960
+ }
3961
+ const range = {
3962
+ type: "endDate",
3963
+ startDate: window.startDate,
3964
+ endDate: window.endDate
3940
3965
  };
3966
+ switch (schedule.repeat) {
3967
+ case models.SCHEDULE_REPEAT_TYPE.EVERY_DAY:
3968
+ return {
3969
+ pattern: {
3970
+ type: "daily",
3971
+ interval: 1
3972
+ },
3973
+ range
3974
+ };
3975
+ case models.SCHEDULE_REPEAT_TYPE.EVERY_WEEK:
3976
+ if (!schedule.daysOfWeek?.length) {
3977
+ return void 0;
3978
+ }
3979
+ return {
3980
+ pattern: {
3981
+ type: "weekly",
3982
+ interval: 1,
3983
+ daysOfWeek: schedule.daysOfWeek.map((day) => GRAPH_WEEKDAY[day])
3984
+ },
3985
+ range
3986
+ };
3987
+ case models.SCHEDULE_REPEAT_TYPE.EVERY_MONTH:
3988
+ if (schedule.datesOfMonth?.length === 1) {
3989
+ return {
3990
+ pattern: {
3991
+ type: "absoluteMonthly",
3992
+ interval: 1,
3993
+ dayOfMonth: schedule.datesOfMonth[0]
3994
+ },
3995
+ range
3996
+ };
3997
+ }
3998
+ if (schedule.monthlyUnit && schedule.daysOfWeek?.length) {
3999
+ return {
4000
+ pattern: {
4001
+ type: "relativeMonthly",
4002
+ interval: 1,
4003
+ daysOfWeek: schedule.daysOfWeek.map((day) => GRAPH_WEEKDAY[day]),
4004
+ index: GRAPH_MONTHLY_INDEX[schedule.monthlyUnit]
4005
+ },
4006
+ range
4007
+ };
4008
+ }
4009
+ return void 0;
4010
+ case models.SCHEDULE_REPEAT_TYPE.CUSTOM:
4011
+ default:
4012
+ return void 0;
4013
+ }
3941
4014
  }
3942
- __name(toGraphRecurrence, "toGraphRecurrence");
3943
- function fromGraphEvent(graph, options) {
3944
- const providerPayload = collectUnknownGraphFields(graph);
4015
+ __name(scheduleToGraphRecurrence, "scheduleToGraphRecurrence");
4016
+ function graphEventToRef(graph, options) {
3945
4017
  return {
3946
4018
  id: graph.id,
3947
- subject: graph.subject ?? "",
3948
- body: graph.body?.content,
3949
- start: graph.start ?? {
3950
- dateTime: "",
3951
- timeZone: ""
3952
- },
3953
- end: graph.end ?? {
3954
- dateTime: "",
3955
- timeZone: ""
3956
- },
3957
- location: graph.location?.displayName,
3958
- resourceId: options?.resourceId,
3959
- recurrence: graph.recurrence ? fromGraphRecurrence(graph.recurrence) : void 0,
3960
- attendees: graph.attendees?.filter((attendee) => Boolean(attendee.emailAddress?.address)).map((attendee) => ({
3961
- email: attendee.emailAddress?.address ?? "",
3962
- name: attendee.emailAddress?.name,
3963
- type: attendee.type
3964
- })),
3965
- organizerEmail: graph.organizer?.emailAddress?.address,
3966
- showAs: graph.showAs,
3967
- isCancelled: graph.isCancelled,
4019
+ seriesId: graph.seriesMasterId,
4020
+ instanceKind: graph.type ? GRAPH_TYPE_TO_INSTANCE_KIND[graph.type] : void 0,
3968
4021
  syncMetadata: omitUndefined({
3969
4022
  ...options?.syncMetadata,
3970
4023
  externalEventId: graph.id ?? options?.syncMetadata?.externalEventId,
3971
- // Event ids are mailbox-scoped — remember which mailbox can address this id.
3972
- // Left undefined when the room organizes; `resourceId` addresses the event then.
3973
4024
  organizerUserEmail: options?.organizerUserEmail ?? options?.syncMetadata?.organizerUserEmail,
3974
- resourceId: options?.resourceId ?? options?.syncMetadata?.resourceId
3975
- }),
3976
- providerPayload
3977
- };
3978
- }
3979
- __name(fromGraphEvent, "fromGraphEvent");
3980
- function fromGraphRecurrence(recurrence) {
3981
- return {
3982
- pattern: omitUndefined({
3983
- type: recurrence.pattern?.type ?? "",
3984
- interval: recurrence.pattern?.interval ?? 1,
3985
- daysOfWeek: recurrence.pattern?.daysOfWeek,
3986
- firstDayOfWeek: recurrence.pattern?.firstDayOfWeek,
3987
- dayOfMonth: recurrence.pattern?.dayOfMonth,
3988
- month: recurrence.pattern?.month,
3989
- index: recurrence.pattern?.index
3990
- }),
3991
- range: omitUndefined({
3992
- type: recurrence.range?.type ?? "",
3993
- startDate: recurrence.range?.startDate ?? "",
3994
- endDate: recurrence.range?.endDate,
3995
- numberOfOccurrences: recurrence.range?.numberOfOccurrences,
3996
- recurrenceTimeZone: recurrence.range?.recurrenceTimeZone
4025
+ resourceId: options?.resourceId ?? options?.syncMetadata?.resourceId,
4026
+ excludedDateResults: options?.excludedDateResults ?? options?.syncMetadata?.excludedDateResults
3997
4027
  })
3998
4028
  };
3999
4029
  }
4000
- __name(fromGraphRecurrence, "fromGraphRecurrence");
4030
+ __name(graphEventToRef, "graphEventToRef");
4031
+ function graphEventsToInstances(response) {
4032
+ return (response.value ?? []).filter((graph) => Boolean(graph.id && graph.start?.dateTime)).map((graph) => omitUndefined({
4033
+ id: graph.id,
4034
+ startDateLabel: graph.start.dateTime.slice(0, 10),
4035
+ seriesId: graph.seriesMasterId
4036
+ }));
4037
+ }
4038
+ __name(graphEventsToInstances, "graphEventsToInstances");
4039
+ function toGraphDateTime(dateLabel, timeLabel, isFullDay) {
4040
+ if (isFullDay || !timeLabel) {
4041
+ return `${dateLabel}T00:00:00`;
4042
+ }
4043
+ const parts = timeLabel.split(":");
4044
+ const hh = parts[0] ?? "00";
4045
+ const mm = parts[1] ?? "00";
4046
+ const ss = parts[2] ?? "00";
4047
+ return `${dateLabel}T${hh}:${mm}:${ss}`;
4048
+ }
4049
+ __name(toGraphDateTime, "toGraphDateTime");
4001
4050
  function omitUndefined(value) {
4002
4051
  return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0));
4003
4052
  }
4004
4053
  __name(omitUndefined, "omitUndefined");
4005
- function collectUnknownGraphFields(graph) {
4006
- const extras = {};
4007
- for (const [key, value] of Object.entries(graph)) {
4008
- if (!GRAPH_EVENT_KNOWN_KEYS.has(key) && value !== void 0) {
4009
- extras[key] = value;
4010
- }
4011
- }
4012
- return Object.keys(extras).length > 0 ? extras : void 0;
4013
- }
4014
- __name(collectUnknownGraphFields, "collectUnknownGraphFields");
4015
4054
 
4016
4055
  // ../../packages/dvss-integration-microsoft/src/capabilities/booking-management/booking-management.service.ts
4017
4056
  function _ts_decorate28(decorators, target, key, desc2) {
@@ -4037,32 +4076,34 @@ exports.MicrosoftCalendarBookingService = class MicrosoftCalendarBookingService
4037
4076
  }
4038
4077
  async createEvent(request, integration, loggedInUserId) {
4039
4078
  try {
4040
- const mailboxEmail = this.resolveMailboxEmail(request);
4079
+ const organizerEmail = request.event.requestedForIds?.[0];
4080
+ const roomEmail = spaceMailboxesFromItems(request.event.items)[0];
4081
+ const mailboxEmail = this.pickMailbox(organizerEmail, roomEmail);
4082
+ this.assertMailbox(mailboxEmail);
4041
4083
  this.logger.info(loggedInUserId, this.createEvent.name, this.fileName, "Create Microsoft Graph calendar event", {
4042
4084
  mailboxEmail,
4043
- resourceId: request.resourceId,
4044
- subject: request.event.subject,
4085
+ subject: request.event.name,
4045
4086
  path: MICROSOFT_GRAPH_PATHS.userCalendarEvents(mailboxEmail)
4046
4087
  });
4047
- this.assertResourceId(request.resourceId);
4048
4088
  const graphEvent = await this.microsoftApiClient.apiCall({
4049
4089
  apiMethod: HTTP_METHOD.POST,
4050
4090
  url: MICROSOFT_GRAPH_PATHS.userCalendarEvents(mailboxEmail),
4051
4091
  body: toGraphEvent(request.event, {
4052
- resourceId: this.resourceAsAttendee(mailboxEmail, request.resourceId)
4092
+ targetMailbox: mailboxEmail
4053
4093
  })
4054
4094
  }, integration, loggedInUserId);
4055
- const mapped = fromGraphEvent(graphEvent, {
4056
- resourceId: request.resourceId,
4057
- organizerUserEmail: this.organizerUserMailbox(request),
4058
- syncMetadata: request.event.syncMetadata
4095
+ const excludedDateResults = await this.resolveSkipDatesIfAny(graphEvent.id, request.event.schedule?.skipDates, mailboxEmail, this.organizerUserMailbox(organizerEmail), integration, loggedInUserId);
4096
+ const ref = graphEventToRef(graphEvent, {
4097
+ organizerUserEmail: this.organizerUserMailbox(organizerEmail),
4098
+ resourceId: roomEmail,
4099
+ syncMetadata: request.event.syncMetadata,
4100
+ excludedDateResults
4059
4101
  });
4060
4102
  this.logger.info(loggedInUserId, this.createEvent.name, this.fileName, "Created Microsoft Graph calendar event", {
4061
- eventId: mapped.id,
4062
- mailboxEmail,
4063
- resourceId: request.resourceId
4103
+ eventId: ref.id,
4104
+ mailboxEmail
4064
4105
  });
4065
- return mapped;
4106
+ return ref;
4066
4107
  } catch (error) {
4067
4108
  this.logger.error(loggedInUserId, this.createEvent.name, this.fileName, "Error creating Microsoft Graph calendar event", error);
4068
4109
  throw error;
@@ -4070,31 +4111,33 @@ exports.MicrosoftCalendarBookingService = class MicrosoftCalendarBookingService
4070
4111
  }
4071
4112
  async updateEvent(request, integration, loggedInUserId) {
4072
4113
  try {
4073
- const mailboxEmail = this.resolveMailboxEmail(request);
4114
+ const mailboxEmail = this.pickMailbox(request.organizerUserEmail, request.resourceEmail);
4115
+ this.assertMailbox(mailboxEmail);
4116
+ this.assertEventId(request.eventId);
4074
4117
  this.logger.info(loggedInUserId, this.updateEvent.name, this.fileName, "Update Microsoft Graph calendar event", {
4075
4118
  mailboxEmail,
4076
- resourceId: request.resourceId,
4077
4119
  eventId: request.eventId,
4078
4120
  path: MICROSOFT_GRAPH_PATHS.userCalendarEvent(mailboxEmail, request.eventId)
4079
4121
  });
4080
- this.assertResourceId(request.resourceId);
4081
- this.assertEventId(request.eventId);
4082
4122
  const graphEvent = await this.microsoftApiClient.apiCall({
4083
4123
  apiMethod: HTTP_METHOD.PATCH,
4084
4124
  url: MICROSOFT_GRAPH_PATHS.userCalendarEvent(mailboxEmail, request.eventId),
4085
- body: toGraphEvent(request.event)
4125
+ body: toGraphEvent(request.event, {
4126
+ targetMailbox: mailboxEmail
4127
+ })
4086
4128
  }, integration, loggedInUserId);
4087
- const mapped = fromGraphEvent(graphEvent, {
4088
- resourceId: request.resourceId,
4089
- organizerUserEmail: this.organizerUserMailbox(request),
4090
- syncMetadata: request.event.syncMetadata
4129
+ const excludedDateResults = await this.resolveSkipDatesIfAny(graphEvent.id ?? request.eventId, request.event.schedule?.skipDates, mailboxEmail, this.organizerUserMailbox(request.organizerUserEmail), integration, loggedInUserId);
4130
+ const ref = graphEventToRef(graphEvent, {
4131
+ organizerUserEmail: this.organizerUserMailbox(request.organizerUserEmail),
4132
+ resourceId: request.resourceEmail,
4133
+ syncMetadata: request.event.syncMetadata,
4134
+ excludedDateResults
4091
4135
  });
4092
4136
  this.logger.info(loggedInUserId, this.updateEvent.name, this.fileName, "Updated Microsoft Graph calendar event", {
4093
- eventId: mapped.id,
4094
- mailboxEmail,
4095
- resourceId: request.resourceId
4137
+ eventId: ref.id,
4138
+ mailboxEmail
4096
4139
  });
4097
- return mapped;
4140
+ return ref;
4098
4141
  } catch (error) {
4099
4142
  this.logger.error(loggedInUserId, this.updateEvent.name, this.fileName, "Error updating Microsoft Graph calendar event", error);
4100
4143
  throw error;
@@ -4102,19 +4145,12 @@ exports.MicrosoftCalendarBookingService = class MicrosoftCalendarBookingService
4102
4145
  }
4103
4146
  async cancelEvent(request, integration, loggedInUserId) {
4104
4147
  try {
4105
- const mailboxEmail = this.resolveMailboxEmail(request);
4148
+ const mailboxEmail = this.pickMailbox(request.organizerUserEmail, request.resourceEmail);
4106
4149
  this.logger.info(loggedInUserId, this.cancelEvent.name, this.fileName, "Cancel Microsoft Graph calendar event", {
4107
4150
  mailboxEmail,
4108
- resourceId: request.resourceId,
4109
- eventId: request.eventId,
4110
- path: MICROSOFT_GRAPH_PATHS.userCalendarEvent(mailboxEmail, request.eventId)
4111
- });
4112
- await this.deleteGraphEvent(mailboxEmail, request.resourceId, request.eventId, integration, loggedInUserId);
4113
- this.logger.info(loggedInUserId, this.cancelEvent.name, this.fileName, "Cancelled Microsoft Graph calendar event", {
4114
- eventId: request.eventId,
4115
- mailboxEmail,
4116
- resourceId: request.resourceId
4151
+ eventId: request.eventId
4117
4152
  });
4153
+ await this.deleteGraphEvent(mailboxEmail, request.eventId, integration, loggedInUserId);
4118
4154
  } catch (error) {
4119
4155
  this.logger.error(loggedInUserId, this.cancelEvent.name, this.fileName, "Error cancelling Microsoft Graph calendar event", error);
4120
4156
  throw error;
@@ -4122,76 +4158,35 @@ exports.MicrosoftCalendarBookingService = class MicrosoftCalendarBookingService
4122
4158
  }
4123
4159
  async deleteEvent(request, integration, loggedInUserId) {
4124
4160
  try {
4125
- const mailboxEmail = this.resolveMailboxEmail(request);
4161
+ const mailboxEmail = this.pickMailbox(request.organizerUserEmail, request.resourceEmail);
4126
4162
  this.logger.info(loggedInUserId, this.deleteEvent.name, this.fileName, "Delete Microsoft Graph calendar event", {
4127
4163
  mailboxEmail,
4128
- resourceId: request.resourceId,
4129
- eventId: request.eventId,
4130
- path: MICROSOFT_GRAPH_PATHS.userCalendarEvent(mailboxEmail, request.eventId)
4131
- });
4132
- await this.deleteGraphEvent(mailboxEmail, request.resourceId, request.eventId, integration, loggedInUserId);
4133
- this.logger.info(loggedInUserId, this.deleteEvent.name, this.fileName, "Deleted Microsoft Graph calendar event", {
4134
- eventId: request.eventId,
4135
- mailboxEmail,
4136
- resourceId: request.resourceId
4164
+ eventId: request.eventId
4137
4165
  });
4166
+ await this.deleteGraphEvent(mailboxEmail, request.eventId, integration, loggedInUserId);
4138
4167
  } catch (error) {
4139
4168
  this.logger.error(loggedInUserId, this.deleteEvent.name, this.fileName, "Error deleting Microsoft Graph calendar event", error);
4140
4169
  throw error;
4141
4170
  }
4142
4171
  }
4143
- async getEvent(request, integration, loggedInUserId) {
4144
- try {
4145
- const mailboxEmail = this.resolveMailboxEmail(request);
4146
- this.logger.info(loggedInUserId, this.getEvent.name, this.fileName, "Get Microsoft Graph calendar event", {
4147
- mailboxEmail,
4148
- resourceId: request.resourceId,
4149
- eventId: request.eventId,
4150
- path: MICROSOFT_GRAPH_PATHS.userCalendarEvent(mailboxEmail, request.eventId)
4151
- });
4152
- this.assertResourceId(request.resourceId);
4153
- this.assertEventId(request.eventId);
4154
- const graphEvent = await this.microsoftApiClient.apiCall({
4155
- apiMethod: HTTP_METHOD.GET,
4156
- url: MICROSOFT_GRAPH_PATHS.userCalendarEvent(mailboxEmail, request.eventId)
4157
- }, integration, loggedInUserId);
4158
- const mapped = fromGraphEvent(graphEvent, {
4159
- resourceId: request.resourceId,
4160
- organizerUserEmail: this.organizerUserMailbox(request)
4161
- });
4162
- this.logger.info(loggedInUserId, this.getEvent.name, this.fileName, "Fetched Microsoft Graph calendar event", {
4163
- eventId: mapped.id,
4164
- mailboxEmail,
4165
- resourceId: request.resourceId
4166
- });
4167
- return mapped;
4168
- } catch (error) {
4169
- this.logger.error(loggedInUserId, this.getEvent.name, this.fileName, "Error fetching Microsoft Graph calendar event", error);
4170
- throw error;
4171
- }
4172
- }
4173
4172
  async getEvents(request, integration, loggedInUserId) {
4174
4173
  try {
4175
- this.assertResourceId(request.resourceId);
4176
- const mailboxEmail = this.resolveMailboxEmail(request);
4177
- const url = request.start && request.end ? MICROSOFT_GRAPH_PATHS.userCalendarView(mailboxEmail, request.start.dateTime, request.end.dateTime) : MICROSOFT_GRAPH_PATHS.userCalendarEvents(mailboxEmail);
4174
+ const mailboxEmail = this.pickMailbox(request.organizerUserEmail, request.resourceEmail);
4175
+ this.assertMailbox(mailboxEmail);
4176
+ const hasWindow = Boolean(request.startDateLabel && request.endDateLabel);
4177
+ const url = hasWindow ? MICROSOFT_GRAPH_PATHS.userCalendarView(mailboxEmail, `${request.startDateLabel}T00:00:00`, `${request.endDateLabel}T23:59:59`) : MICROSOFT_GRAPH_PATHS.userCalendarEvents(mailboxEmail);
4178
4178
  this.logger.info(loggedInUserId, this.getEvents.name, this.fileName, "List Microsoft Graph calendar events", {
4179
4179
  mailboxEmail,
4180
- resourceId: request.resourceId,
4181
4180
  path: url,
4182
- hasTimeWindow: Boolean(request.start && request.end)
4181
+ hasTimeWindow: hasWindow
4183
4182
  });
4184
4183
  const response = await this.microsoftApiClient.apiCall({
4185
4184
  apiMethod: HTTP_METHOD.GET,
4186
4185
  url
4187
4186
  }, integration, loggedInUserId);
4188
- const events = (response.value ?? []).map((graphEvent) => fromGraphEvent(graphEvent, {
4189
- resourceId: request.resourceId,
4190
- organizerUserEmail: this.organizerUserMailbox(request)
4191
- }));
4187
+ const events = graphEventsToInstances(response);
4192
4188
  this.logger.info(loggedInUserId, this.getEvents.name, this.fileName, "Listed Microsoft Graph calendar events", {
4193
4189
  mailboxEmail,
4194
- resourceId: request.resourceId,
4195
4190
  count: events.length
4196
4191
  });
4197
4192
  return {
@@ -4202,16 +4197,8 @@ exports.MicrosoftCalendarBookingService = class MicrosoftCalendarBookingService
4202
4197
  throw error;
4203
4198
  }
4204
4199
  }
4205
- syncEvents(request, integration, loggedInUserId) {
4206
- this.logger.info(loggedInUserId, this.syncEvents.name, this.fileName, "Sync Microsoft Graph calendar events (delta)", {
4207
- resourceId: request.resourceId,
4208
- hasSyncToken: Boolean(request.syncToken)
4209
- });
4210
- void this.microsoftApiClient;
4211
- return Promise.reject(new common.NotImplementedException("MicrosoftCalendarBookingService.syncEvents is not implemented yet"));
4212
- }
4213
- async deleteGraphEvent(mailboxEmail, resourceId, eventId, integration, loggedInUserId) {
4214
- this.assertResourceId(resourceId);
4200
+ async deleteGraphEvent(mailboxEmail, eventId, integration, loggedInUserId) {
4201
+ this.assertMailbox(mailboxEmail);
4215
4202
  this.assertEventId(eventId);
4216
4203
  await this.microsoftApiClient.apiCall({
4217
4204
  apiMethod: HTTP_METHOD.DELETE,
@@ -4219,30 +4206,74 @@ exports.MicrosoftCalendarBookingService = class MicrosoftCalendarBookingService
4219
4206
  }, integration, loggedInUserId);
4220
4207
  }
4221
4208
  /**
4222
- * Mailbox the Graph call targets: the organizing user when one is known, otherwise the
4223
- * resource mailbox, which keeps the room-organizes behaviour for callers that cannot
4224
- * resolve a user. The return value is therefore a user *or* a resource mailbox — never
4225
- * store it as `organizerUserEmail`; use `organizerUserMailbox` for that.
4209
+ * Graph always creates/updates a recurring series whole. For each date in
4210
+ * `schedule.skipDates` this finds the occurrence instance in the series just
4211
+ * created/updated and cancels it via the existing DELETE path. Best-effort per date — a
4212
+ * date that can't be resolved is reported `excluded: false`, not thrown.
4226
4213
  */
4227
- resolveMailboxEmail(request) {
4228
- return this.organizerUserMailbox(request) ?? request.resourceId;
4214
+ async resolveSkipDatesIfAny(seriesId, dates, mailboxEmail, organizerUserEmail, integration, loggedInUserId) {
4215
+ if (!dates?.length) {
4216
+ return void 0;
4217
+ }
4218
+ const results = [];
4219
+ for (const date of dates) {
4220
+ try {
4221
+ const instanceId = await this.findOccurrenceInstanceId(seriesId, date, mailboxEmail, integration, loggedInUserId);
4222
+ if (!instanceId) {
4223
+ this.logger.warn(loggedInUserId, this.resolveSkipDatesIfAny.name, this.fileName, "Could not resolve skip-date occurrence", {
4224
+ seriesId,
4225
+ date,
4226
+ mailboxEmail
4227
+ });
4228
+ results.push({
4229
+ date,
4230
+ excluded: false
4231
+ });
4232
+ continue;
4233
+ }
4234
+ await this.cancelEvent({
4235
+ eventId: instanceId,
4236
+ resourceEmail: mailboxEmail,
4237
+ organizerUserEmail
4238
+ }, integration, loggedInUserId);
4239
+ results.push({
4240
+ date,
4241
+ eventId: instanceId,
4242
+ excluded: true
4243
+ });
4244
+ } catch (error) {
4245
+ this.logger.warn(loggedInUserId, this.resolveSkipDatesIfAny.name, this.fileName, "Failed to cancel skip-date occurrence", {
4246
+ seriesId,
4247
+ date,
4248
+ mailboxEmail,
4249
+ error: error instanceof Error ? error.message : String(error)
4250
+ });
4251
+ results.push({
4252
+ date,
4253
+ excluded: false
4254
+ });
4255
+ }
4256
+ }
4257
+ return results;
4229
4258
  }
4230
- /**
4231
- * The organizing user's mailbox, or undefined when the room ends up organizing.
4232
- */
4233
- organizerUserMailbox(request) {
4234
- return request.organizerUserEmail?.trim() || void 0;
4259
+ async findOccurrenceInstanceId(seriesId, date, mailboxEmail, integration, loggedInUserId) {
4260
+ const response = await this.microsoftApiClient.apiCall({
4261
+ apiMethod: HTTP_METHOD.GET,
4262
+ url: MICROSOFT_GRAPH_PATHS.userCalendarView(mailboxEmail, `${date}T00:00:00`, `${date}T23:59:59`)
4263
+ }, integration, loggedInUserId);
4264
+ return (response.value ?? []).find((occurrence) => occurrence.seriesMasterId === seriesId)?.id;
4235
4265
  }
4236
- /**
4237
- * The room only needs to be invited as an attendee when the event lives in someone
4238
- * else's mailbox. Posting into the room's own calendar already books it.
4239
- */
4240
- resourceAsAttendee(mailboxEmail, resourceId) {
4241
- return mailboxEmail.trim().toLowerCase() === resourceId.trim().toLowerCase() ? void 0 : resourceId;
4266
+ /** Mailbox the Graph call targets: the organizing user if known, else the room. */
4267
+ pickMailbox(organizerEmail, roomEmail) {
4268
+ return this.organizerUserMailbox(organizerEmail) ?? roomEmail?.trim() ?? "";
4242
4269
  }
4243
- assertResourceId(resourceId) {
4244
- if (!resourceId?.trim()) {
4245
- throw new dvssBackendModuleUtility.CustomException("BAD_REQUEST", "resourceId is required");
4270
+ /** The organizing user's mailbox, or undefined when the room ends up organizing. */
4271
+ organizerUserMailbox(organizerEmail) {
4272
+ return organizerEmail?.trim() || void 0;
4273
+ }
4274
+ assertMailbox(mailboxEmail) {
4275
+ if (!mailboxEmail?.trim()) {
4276
+ throw new dvssBackendModuleUtility.CustomException("BAD_REQUEST", "a requested-for or resource mailbox is required");
4246
4277
  }
4247
4278
  }
4248
4279
  assertEventId(eventId) {
@@ -4788,15 +4819,9 @@ exports.MicrosoftCalendarBookingHandler = class MicrosoftCalendarBookingHandler
4788
4819
  async deleteCalendarBooking(request, integration, loggedInUserId) {
4789
4820
  return this.microsoftCalendarBookingService.deleteEvent(request, integration, loggedInUserId);
4790
4821
  }
4791
- async getCalendarBooking(request, integration, loggedInUserId) {
4792
- return this.microsoftCalendarBookingService.getEvent(request, integration, loggedInUserId);
4793
- }
4794
4822
  async getCalendarBookings(request, integration, loggedInUserId) {
4795
4823
  return this.microsoftCalendarBookingService.getEvents(request, integration, loggedInUserId);
4796
4824
  }
4797
- async syncCalendarBookings(request, integration, loggedInUserId) {
4798
- return this.microsoftCalendarBookingService.syncEvents(request, integration, loggedInUserId);
4799
- }
4800
4825
  };
4801
4826
  exports.MicrosoftCalendarBookingHandler = _ts_decorate36([
4802
4827
  common.Injectable(),
@@ -5112,6 +5137,30 @@ exports.CalendarIntegrationManager = _ts_decorate44([
5112
5137
  })
5113
5138
  ], exports.CalendarIntegrationManager);
5114
5139
 
5140
+ Object.defineProperty(exports, "BEHAVIOUR_TYPE_ENUM", {
5141
+ enumerable: true,
5142
+ get: function () { return models.BEHAVIOUR_TYPE_ENUM; }
5143
+ });
5144
+ Object.defineProperty(exports, "DAY_OF_WEEK", {
5145
+ enumerable: true,
5146
+ get: function () { return models.DAY_OF_WEEK; }
5147
+ });
5148
+ Object.defineProperty(exports, "OFFERING_BOOKING_TIME_TYPE", {
5149
+ enumerable: true,
5150
+ get: function () { return models.OFFERING_BOOKING_TIME_TYPE; }
5151
+ });
5152
+ Object.defineProperty(exports, "OFFERING_BOOKING_TYPE_ENUM", {
5153
+ enumerable: true,
5154
+ get: function () { return models.OFFERING_BOOKING_TYPE_ENUM; }
5155
+ });
5156
+ Object.defineProperty(exports, "SCHEDULE_MONTHLY_UNIT", {
5157
+ enumerable: true,
5158
+ get: function () { return models.SCHEDULE_MONTHLY_UNIT; }
5159
+ });
5160
+ Object.defineProperty(exports, "SCHEDULE_REPEAT_TYPE", {
5161
+ enumerable: true,
5162
+ get: function () { return models.SCHEDULE_REPEAT_TYPE; }
5163
+ });
5115
5164
  exports.BOOKABLE_ITEM_STATUS_ENUM = BOOKABLE_ITEM_STATUS_ENUM;
5116
5165
  exports.BOOKABLE_ITEM_TYPE_ENUM = BOOKABLE_ITEM_TYPE_ENUM;
5117
5166
  exports.BaseAccessManagement = BaseAccessManagement;
@@ -5144,6 +5193,7 @@ exports.CREDIT_STATUS_ENUM = CREDIT_STATUS_ENUM;
5144
5193
  exports.CREDIT_TYPE_ENUM = CREDIT_TYPE_ENUM;
5145
5194
  exports.DOWNLOAD_CUSTOMER_ACCOUNTING_STATEMENT_FILTER_BY_ENUM = DOWNLOAD_CUSTOMER_ACCOUNTING_STATEMENT_FILTER_BY_ENUM;
5146
5195
  exports.DOWNLOAD_CUSTOMER_ACCOUNTING_STATEMENT_STATUS_ENUM = DOWNLOAD_CUSTOMER_ACCOUNTING_STATEMENT_STATUS_ENUM;
5196
+ exports.EVENT_INSTANCE_KIND = EVENT_INSTANCE_KIND;
5147
5197
  exports.GET_CUSTOMER_CREDIT_NOTES_FILTER_BY = GET_CUSTOMER_CREDIT_NOTES_FILTER_BY;
5148
5198
  exports.GET_CUSTOMER_CREDIT_NOTES_SORT_BY = GET_CUSTOMER_CREDIT_NOTES_SORT_BY;
5149
5199
  exports.GET_INVOICES_FILTER_BY_ENUM = GET_INVOICES_FILTER_BY_ENUM;