Skip to content

Commit

Permalink
create a new series on event instance duration change
Browse files Browse the repository at this point in the history
  • Loading branch information
meetulr committed Apr 18, 2024
1 parent 40eda05 commit 37b8862
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 65 deletions.
7 changes: 6 additions & 1 deletion src/helpers/event/deleteEventHelpers/deleteRecurringEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ export const deleteRecurringEvent = async (
) {
// if the event is an exception or if it's deleting thisInstance only,
// just delete this single instance
await deleteSingleEvent(event._id.toString(), session);
await deleteSingleEvent(
event._id.toString(),
session,
recurrenceRule._id.toString(),
baseRecurringEvent._id.toString(),
);
} else if (args.recurringEventDeleteType === "allInstances") {
// delete all the instances
// and update the recurrenceRule and baseRecurringEvent accordingly
Expand Down
9 changes: 9 additions & 0 deletions src/helpers/event/deleteEventHelpers/deleteSingleEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
EventAttendee,
User,
} from "../../../models";
import { removeDanglingDocuments } from "../recurringEventHelpers";

/**
* This function deletes a single event.
Expand All @@ -18,6 +19,8 @@ import {
export const deleteSingleEvent = async (
eventId: string,
session: mongoose.ClientSession,
recurrenceRule?: string,
baseRecurringEvent?: string,
): Promise<void> => {
// remove the associations of the current event
await Promise.all([
Expand Down Expand Up @@ -62,4 +65,10 @@ export const deleteSingleEvent = async (
},
),
]);

if (recurrenceRule && baseRecurringEvent) {
// they would exist while we're deleting a recurring event
// remove any dangling recurrence rule and base recurring event documents
await removeDanglingDocuments(recurrenceRule, baseRecurringEvent, session);
}
};
108 changes: 61 additions & 47 deletions src/helpers/event/updateEventHelpers/updateRecurringEventInstances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,22 @@ export const updateRecurringEventInstances = async (
currentRecurrenceRuleString !== newRecurrenceRuleString;
}

// whether instance duration has changed
let hasEventInstanceDurationChanged = false;

if (updateEventInputData.startDate && updateEventInputData.endDate) {
const { startDate: newStartDate, endDate: newEndDate } =
updateEventInputData;
const { startDate: originalStartDate, endDate: originalEndDate } = event;

hasEventInstanceDurationChanged =
newStartDate.toString() !== originalStartDate.toString() ||
newEndDate.toString() !== originalEndDate?.toString();
}

const shouldCreateNewSeries =
hasRecurrenceRuleChanged || hasEventInstanceDurationChanged;

// get the query object to filter events to be updated:
// - if we're updating thisAndFollowingInstance, it will find all the instances after(and including) this one
// - if we're updating allInstances, it will find all the instances
Expand All @@ -93,51 +109,10 @@ export const updateRecurringEventInstances = async (
eventsQueryObject.startDate = { $gte: event.startDate };
}

if (hasRecurrenceRuleChanged) {
// if the recurrence rule has changed, delete the current series
// and generate a new one starting from the current instance

// get latest eventData to be used for new recurring instances and base recurring event
const eventData = getEventData(updateEventInputData, event);

// get the recurrence start and end dates
({ recurrenceStartDate, recurrenceEndDate } =
recurrenceRuleData as RecurrenceRuleInput);

// get recurrence dates
const recurringInstanceDates = getRecurringInstanceDates(
newRecurrenceRuleString,
recurrenceStartDate,
recurrenceEndDate,
);
if (shouldCreateNewSeries) {
// delete the current series, remove their associations, and generate a new one

// get the startDate of the latest instance following the recurrence
const latestInstanceDate =
recurringInstanceDates[recurringInstanceDates.length - 1];

// create the recurrencerule
const newRecurrenceRule = await createRecurrenceRule(
newRecurrenceRuleString,
recurrenceStartDate,
recurrenceEndDate,
eventData.organizationId,
baseRecurringEvent._id.toString(),
latestInstanceDate,
session,
);

// generate the recurring instances and get an instance back
updatedEvent = await generateRecurringEventInstances({
data: eventData,
baseRecurringEventId: baseRecurringEvent._id.toString(),
recurrenceRuleId: newRecurrenceRule?._id.toString(),
recurringInstanceDates,
creatorId: event.creatorId,
organizationId: eventData.organizationId,
session,
});

// remove the events conforming to the current recurrence rule and their associations
// first, remove the events conforming to the current recurrence rule and their associations
const recurringEventInstances = await Event.find(
{
...eventsQueryObject,
Expand Down Expand Up @@ -217,10 +192,49 @@ export const updateRecurringEventInstances = async (
{ session },
).lean();
}

// now generate a new series
// get latest eventData to be used for new recurring instances and base recurring event
const eventData = getEventData(updateEventInputData, event);

// get the recurrence start and end dates
({ recurrenceStartDate, recurrenceEndDate } =
recurrenceRuleData as RecurrenceRuleInput);

// get recurrence dates
const recurringInstanceDates = getRecurringInstanceDates(
newRecurrenceRuleString,
recurrenceStartDate,
recurrenceEndDate,
);

// get the startDate of the latest instance following the recurrence
const latestInstanceDate =
recurringInstanceDates[recurringInstanceDates.length - 1];

// create the recurrencerule
const newRecurrenceRule = await createRecurrenceRule(
newRecurrenceRuleString,
recurrenceStartDate,
recurrenceEndDate,
eventData.organizationId,
baseRecurringEvent._id.toString(),
latestInstanceDate,
session,
);

// generate the recurring instances and get an instance back
updatedEvent = await generateRecurringEventInstances({
data: eventData,
baseRecurringEventId: baseRecurringEvent._id.toString(),
recurrenceRuleId: newRecurrenceRule?._id.toString(),
recurringInstanceDates,
creatorId: event.creatorId,
organizationId: eventData.organizationId,
session,
});
} else {
// i.e. recurrence rule has not changed
// perform bulk update on all the events starting from this event,
// that are following the current recurrence rule and are not exceptions
// perform bulk update on all the events that are queried according to the eventsQueryObject,

// get the generic data to be updated
const updateData = { ...args.data };
Expand Down
Loading

0 comments on commit 37b8862

Please sign in to comment.