@flusys/nestjs-event-manager 4.1.0 → 5.0.0

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.
Files changed (52) hide show
  1. package/README.md +126 -337
  2. package/adapters/event-manager.adapter.d.ts +0 -2
  3. package/cjs/adapters/event-manager.adapter.js +1 -7
  4. package/cjs/config/message-keys.js +1 -31
  5. package/cjs/controllers/event.controller.js +10 -60
  6. package/cjs/controllers/index.js +0 -1
  7. package/cjs/docs/event-manager-swagger.config.js +19 -29
  8. package/cjs/docs/index.js +0 -3
  9. package/cjs/dtos/calendar-query.dto.js +46 -20
  10. package/cjs/dtos/event-participant.dto.js +0 -45
  11. package/cjs/dtos/event.dto.js +97 -45
  12. package/cjs/entities/event-participant.entity.js +1 -8
  13. package/cjs/entities/event.entity.js +38 -26
  14. package/cjs/modules/event-manager.module.js +2 -4
  15. package/cjs/services/event-manager-helper.service.js +15 -83
  16. package/cjs/services/event.service.js +143 -122
  17. package/cjs/services/index.js +0 -1
  18. package/config/message-keys.d.ts +0 -56
  19. package/controllers/event.controller.d.ts +2 -5
  20. package/controllers/index.d.ts +0 -1
  21. package/docs/index.d.ts +1 -1
  22. package/dtos/calendar-query.dto.d.ts +8 -5
  23. package/dtos/event-participant.dto.d.ts +0 -6
  24. package/dtos/event.dto.d.ts +14 -10
  25. package/entities/event-participant.entity.d.ts +0 -1
  26. package/entities/event.entity.d.ts +6 -5
  27. package/fesm/adapters/event-manager.adapter.js +1 -7
  28. package/fesm/config/message-keys.js +1 -29
  29. package/fesm/controllers/event.controller.js +11 -61
  30. package/fesm/controllers/index.js +0 -1
  31. package/fesm/docs/event-manager-swagger.config.js +19 -29
  32. package/fesm/docs/index.js +1 -1
  33. package/fesm/dtos/calendar-query.dto.js +47 -21
  34. package/fesm/dtos/event-participant.dto.js +0 -42
  35. package/fesm/dtos/event.dto.js +98 -46
  36. package/fesm/entities/event-participant.entity.js +1 -8
  37. package/fesm/entities/event.entity.js +38 -26
  38. package/fesm/modules/event-manager.module.js +4 -6
  39. package/fesm/services/event-manager-helper.service.js +17 -85
  40. package/fesm/services/event.service.js +144 -123
  41. package/fesm/services/index.js +0 -1
  42. package/interfaces/event.interface.d.ts +6 -6
  43. package/package.json +3 -3
  44. package/services/event-manager-helper.service.d.ts +1 -3
  45. package/services/event.service.d.ts +8 -8
  46. package/services/index.d.ts +0 -1
  47. package/cjs/controllers/event-participant.controller.js +0 -287
  48. package/cjs/services/event-participant.service.js +0 -198
  49. package/controllers/event-participant.controller.d.ts +0 -35
  50. package/fesm/controllers/event-participant.controller.js +0 -277
  51. package/fesm/services/event-participant.service.js +0 -188
  52. package/services/event-participant.service.d.ts +0 -27
@@ -30,10 +30,11 @@ import { LogAction } from '@flusys/nestjs-shared/decorators';
30
30
  import { RecurrenceType } from '@flusys/nestjs-shared/enums';
31
31
  import { UtilsService } from '@flusys/nestjs-shared/modules';
32
32
  import { applyCompanyFilter } from '@flusys/nestjs-shared/utils';
33
- import { EVENT_MESSAGES } from '../config';
33
+ import { EVENT_MESSAGES, EVENT_PARTICIPANT_MESSAGES } from '../config';
34
34
  import { Inject, Injectable, NotFoundException, Scope } from '@nestjs/common';
35
35
  import { In, IsNull } from 'typeorm';
36
36
  import { EventManagerConfigService } from './event-manager-config.service';
37
+ import { UpdateParticipantStatusDto } from '../dtos';
37
38
  import { Event, EventWithCompany, EventParticipant } from '../entities';
38
39
  import { EventManagerDataSourceProvider } from './event-manager-datasource.provider';
39
40
  export class EventService extends RequestScopedApiService {
@@ -46,6 +47,7 @@ export class EventService extends RequestScopedApiService {
46
47
  }
47
48
  // Override methods
48
49
  async convertSingleDtoToEntity(dto, user) {
50
+ await this.ensureRepositoryInitialized();
49
51
  let entity = {};
50
52
  if ('id' in dto && dto.id && typeof dto.id === 'string') {
51
53
  const existing = await this.repository.findOne({
@@ -59,19 +61,21 @@ export class EventService extends RequestScopedApiService {
59
61
  });
60
62
  entity = existing;
61
63
  }
64
+ const isAllDay = dto.isAllDay ?? entity.isAllDay ?? false;
62
65
  const merged = {
63
66
  ...entity,
64
67
  title: dto.title ?? entity.title,
65
68
  description: dto.description ?? entity.description,
66
- meetingLink: dto.meetingLink ?? entity.meetingLink,
67
- startDateTime: dto.startDateTime ?? entity.startDateTime,
68
- endDateTime: dto.endDateTime ?? entity.endDateTime,
69
- isAllDay: dto.isAllDay ?? entity.isAllDay ?? false,
69
+ eventDate: dto.eventDate ?? entity.eventDate,
70
+ startTime: isAllDay ? '00:00' : dto.startTime ?? entity.startTime ?? '00:00',
71
+ endTime: isAllDay ? '23:59' : dto.endTime ?? entity.endTime ?? '23:59',
72
+ isAllDay,
70
73
  recurrenceType: dto.recurrenceType ?? entity.recurrenceType ?? RecurrenceType.NONE,
71
- recurrenceEndDate: dto.recurrenceEndDate ?? entity.recurrenceEndDate,
74
+ recurrenceEndDate: dto.recurrenceEndDate ?? entity.recurrenceEndDate ?? null,
75
+ weekDays: dto.weekDays ?? entity.weekDays ?? null,
72
76
  color: dto.color ?? entity.color ?? this.eventConfig.getDefaultColor(),
73
- isActive: dto.isActive ?? entity.isActive ?? true,
74
- metadata: dto.metadata ?? entity.metadata
77
+ meetingLink: dto.meetingLink !== undefined ? dto.meetingLink ?? null : entity.meetingLink ?? null,
78
+ isActive: dto.isActive ?? entity.isActive ?? true
75
79
  };
76
80
  if (this.eventConfig.isCompanyFeatureEnabled()) {
77
81
  merged.companyId = user?.companyId ?? null;
@@ -114,6 +118,8 @@ export class EventService extends RequestScopedApiService {
114
118
  async getExtraManipulateQuery(query, filterDto, user) {
115
119
  const result = await super.getExtraManipulateQuery(query, filterDto, user);
116
120
  this.applyEventCompanyFilter(query, user);
121
+ await this.ensureParticipantRepositoryInitialized();
122
+ query.leftJoinAndMapMany(`${this.entityName}.participants`, EventParticipant, 'ep', 'ep.event_id = event.id AND ep.deleted_at IS NULL');
117
123
  return result;
118
124
  }
119
125
  async afterInsertOperation(entities, user, _qr) {
@@ -123,20 +129,29 @@ export class EventService extends RequestScopedApiService {
123
129
  }
124
130
  this.pendingParticipantsList = [];
125
131
  }
132
+ async afterUpdateOperation(entities, user, _qr) {
133
+ const participantRepo = await this.ensureParticipantRepositoryInitialized();
134
+ for(let i = 0; i < entities.length; i++){
135
+ const participantIds = this.pendingParticipantsList[i] ?? [];
136
+ await participantRepo.update({
137
+ eventId: entities[i].id,
138
+ deletedAt: IsNull()
139
+ }, {
140
+ deletedAt: new Date()
141
+ });
142
+ await this.addCreatorAndParticipants(entities[i].id, participantIds, user);
143
+ }
144
+ this.pendingParticipantsList = [];
145
+ }
126
146
  // Public API methods
127
147
  async getEventsForCalendarRange(queryDto, user) {
128
148
  await this.ensureRepositoryInitialized();
129
149
  const query = this.repository.createQueryBuilder('event').where('event.deletedAt IS NULL').andWhere('event.isActive = :isActive', {
130
150
  isActive: queryDto.activeOnly !== false
131
- });
132
- query.andWhere('(event.startDateTime <= :endDate AND event.endDateTime >= :startDate)', {
151
+ }).andWhere('((event.eventDate >= :startDate AND event.eventDate <= :endDate) OR (event.recurrenceType != :none AND event.eventDate <= :endDate AND (event.recurrenceEndDate IS NULL OR event.recurrenceEndDate >= :startDate)))', {
133
152
  startDate: queryDto.startDate,
134
- endDate: queryDto.endDate
135
- });
136
- query.orWhere('event.deletedAt IS NULL AND event.recurrenceType != :none AND event.startDateTime <= :endDate AND (event.recurrenceEndDate IS NULL OR event.recurrenceEndDate >= :startDate)', {
137
- none: RecurrenceType.NONE,
138
- startDate: queryDto.startDate,
139
- endDate: queryDto.endDate
153
+ endDate: queryDto.endDate,
154
+ none: RecurrenceType.NONE
140
155
  });
141
156
  this.applyEventCompanyFilter(query, user);
142
157
  if (queryDto.userId) {
@@ -155,75 +170,57 @@ export class EventService extends RequestScopedApiService {
155
170
  }
156
171
  return this.expandRecurringEvents(events, queryDto.startDate, queryDto.endDate);
157
172
  }
158
- async getEventWithParticipants(id, user) {
159
- await this.ensureRepositoryInitialized();
160
- const query = this.repository.createQueryBuilder('event').where('event.id = :id', {
161
- id
162
- }).andWhere('event.deletedAt IS NULL');
163
- this.applyEventCompanyFilter(query, user);
164
- const event = await query.getOne();
165
- if (event) {
166
- const participantRepo = await this.ensureParticipantRepositoryInitialized();
167
- event.participants = await participantRepo.find({
168
- where: {
169
- eventId: id,
170
- deletedAt: IsNull()
171
- }
172
- });
173
- }
174
- return event;
175
- }
176
- async addParticipants(eventId, userIds, _user) {
177
- await this.ensureRepositoryInitialized();
173
+ async updateParticipantStatus(dto, _user) {
178
174
  const participantRepo = await this.ensureParticipantRepositoryInitialized();
179
- const event = await this.repository.findOne({
175
+ const participant = await participantRepo.findOne({
180
176
  where: {
181
- id: eventId,
182
- deletedAt: IsNull()
177
+ id: dto.id
183
178
  }
184
179
  });
185
- if (!event) {
180
+ if (!participant) {
186
181
  throw new NotFoundException({
187
- message: 'Event not found',
188
- messageKey: EVENT_MESSAGES.NOT_FOUND
182
+ message: 'Event participant not found',
183
+ messageKey: EVENT_PARTICIPANT_MESSAGES.NOT_FOUND
189
184
  });
190
185
  }
191
- const existingParticipants = await participantRepo.find({
192
- where: {
193
- eventId,
194
- userId: In(userIds),
195
- deletedAt: IsNull()
196
- }
197
- });
198
- const existingUserIds = new Set(existingParticipants.map((p)=>p.userId));
199
- const newParticipants = userIds.filter((userId)=>!existingUserIds.has(userId)).map((userId)=>({
200
- eventId,
201
- userId,
202
- isOrganizer: false
203
- }));
204
- if (newParticipants.length === 0) {
205
- return existingParticipants;
206
- }
207
- const created = await participantRepo.save(newParticipants);
208
- return [
209
- ...existingParticipants,
210
- ...created
211
- ];
186
+ participant.status = dto.status;
187
+ return participantRepo.save(participant);
212
188
  }
213
189
  // Private business logic helpers
214
190
  async addCreatorAndParticipants(eventId, participantIds, user) {
215
191
  if (!user?.id) return;
216
192
  const participantRepo = await this.ensureParticipantRepositoryInitialized();
217
- const allUserIds = new Set([
193
+ const allUserIds = Array.from(new Set([
218
194
  user.id,
219
195
  ...participantIds
220
- ]);
221
- const participants = Array.from(allUserIds).map((userId)=>({
196
+ ]));
197
+ const existing = await participantRepo.find({
198
+ where: {
199
+ eventId,
200
+ userId: In(allUserIds)
201
+ },
202
+ withDeleted: true
203
+ });
204
+ const existingByUserId = new Map(existing.map((p)=>[
205
+ p.userId,
206
+ p
207
+ ]));
208
+ const toSave = allUserIds.map((userId)=>{
209
+ const existingRecord = existingByUserId.get(userId);
210
+ if (existingRecord) {
211
+ return {
212
+ ...existingRecord,
213
+ deletedAt: null,
214
+ isOrganizer: userId === user.id
215
+ };
216
+ }
217
+ return {
222
218
  eventId,
223
219
  userId,
224
220
  isOrganizer: userId === user.id
225
- }));
226
- await participantRepo.save(participants);
221
+ };
222
+ });
223
+ await participantRepo.save(toSave);
227
224
  }
228
225
  expandRecurringEvents(events, rangeStart, rangeEnd) {
229
226
  const result = [];
@@ -235,48 +232,44 @@ export class EventService extends RequestScopedApiService {
235
232
  result.push(...this.generateOccurrences(event, rangeStart, rangeEnd, maxOccurrences));
236
233
  }
237
234
  }
238
- return result.sort((a, b)=>new Date(a.startDateTime).getTime() - new Date(b.startDateTime).getTime());
235
+ return result.sort((a, b)=>a.eventDate.localeCompare(b.eventDate));
239
236
  }
240
237
  generateOccurrences(event, rangeStart, rangeEnd, maxOccurrences) {
241
238
  const occurrences = [];
242
- const eventDuration = new Date(event.endDateTime).getTime() - new Date(event.startDateTime).getTime();
243
- const recurrenceEnd = event.recurrenceEndDate ? new Date(event.recurrenceEndDate) : null;
239
+ const recurrenceEnd = event.recurrenceEndDate ?? null;
244
240
  const recurrenceType = event.recurrenceType;
245
- const recurrenceDays = event.metadata?.recurrenceDays || [
246
- new Date(event.startDateTime).getDay()
241
+ const weekDays = event.weekDays ?? [
242
+ this.getDayOfWeek(event.eventDate)
247
243
  ];
248
- let currentStart = new Date(event.startDateTime);
244
+ let currentDate = event.eventDate;
249
245
  let count = 0;
250
246
  if (recurrenceType === RecurrenceType.WEEKLY || recurrenceType === RecurrenceType.BIWEEKLY) {
251
- let weekStart = new Date(event.startDateTime);
252
- weekStart.setDate(weekStart.getDate() - weekStart.getDay());
247
+ let weekStart = this.getWeekStart(event.eventDate);
253
248
  while(count < maxOccurrences){
254
- for (const dayOfWeek of recurrenceDays){
249
+ for (const dayOfWeek of weekDays){
255
250
  if (count >= maxOccurrences) break;
256
- currentStart = new Date(weekStart);
257
- currentStart.setDate(currentStart.getDate() + dayOfWeek);
258
- currentStart.setHours(new Date(event.startDateTime).getHours());
259
- currentStart.setMinutes(new Date(event.startDateTime).getMinutes());
260
- if (currentStart < new Date(event.startDateTime)) continue;
261
- const shouldBreak = this.shouldStopRecurrence(currentStart, recurrenceEnd, rangeEnd);
262
- if (shouldBreak) {
251
+ currentDate = this.addDaysToDate(weekStart, this.weekdayNameToIndex(dayOfWeek));
252
+ if (currentDate < event.eventDate) continue;
253
+ if (this.shouldStopRecurrence(currentDate, recurrenceEnd, rangeEnd)) {
263
254
  count = maxOccurrences;
264
255
  break;
265
256
  }
266
- const occurrence = this.tryCreateOccurrence(event, currentStart, eventDuration, rangeStart, rangeEnd, occurrences.length > 0);
267
- if (occurrence) occurrences.push(occurrence);
257
+ if (currentDate >= rangeStart && currentDate <= rangeEnd) {
258
+ occurrences.push(this.toCalendarEventOnDate(event, currentDate, occurrences.length > 0));
259
+ }
268
260
  count++;
269
261
  }
270
262
  const weeksToAdd = recurrenceType === RecurrenceType.BIWEEKLY ? 2 : 1;
271
- weekStart.setDate(weekStart.getDate() + 7 * weeksToAdd);
263
+ weekStart = this.addDaysToDate(weekStart, 7 * weeksToAdd);
272
264
  }
273
265
  } else {
274
- const originalDayOfMonth = new Date(event.startDateTime).getDate();
266
+ const originalDayOfMonth = parseInt(event.eventDate.split('-')[2], 10);
275
267
  while(count < maxOccurrences){
276
- if (this.shouldStopRecurrence(currentStart, recurrenceEnd, rangeEnd)) break;
277
- const occurrence = this.tryCreateOccurrence(event, currentStart, eventDuration, rangeStart, rangeEnd, count > 0);
278
- if (occurrence) occurrences.push(occurrence);
279
- currentStart = this.getNextOccurrenceDate(currentStart, recurrenceType, originalDayOfMonth);
268
+ if (this.shouldStopRecurrence(currentDate, recurrenceEnd, rangeEnd)) break;
269
+ if (currentDate >= rangeStart && currentDate <= rangeEnd) {
270
+ occurrences.push(this.toCalendarEventOnDate(event, currentDate, count > 0));
271
+ }
272
+ currentDate = this.getNextOccurrenceDate(currentDate, recurrenceType, originalDayOfMonth);
280
273
  count++;
281
274
  }
282
275
  }
@@ -321,41 +314,61 @@ export class EventService extends RequestScopedApiService {
321
314
  entityAlias: 'event'
322
315
  }, user);
323
316
  }
324
- shouldStopRecurrence(currentStart, recurrenceEnd, rangeEnd) {
325
- return recurrenceEnd && currentStart > recurrenceEnd || currentStart > rangeEnd;
317
+ shouldStopRecurrence(currentDate, recurrenceEnd, rangeEnd) {
318
+ return recurrenceEnd !== null && currentDate > recurrenceEnd || currentDate > rangeEnd;
326
319
  }
327
- tryCreateOccurrence(event, currentStart, eventDuration, rangeStart, rangeEnd, isRecurrenceInstance) {
328
- const currentEnd = new Date(currentStart.getTime() + eventDuration);
329
- if (currentEnd >= rangeStart && currentStart <= rangeEnd) {
330
- return {
331
- ...this.toCalendarEvent(event),
332
- id: `${event.id}_${currentStart.toISOString()}`,
333
- originalEventId: event.id,
334
- isRecurrenceInstance,
335
- startDateTime: new Date(currentStart),
336
- endDateTime: currentEnd
337
- };
338
- }
339
- return null;
320
+ getDayOfWeek(dateStr) {
321
+ const days = [
322
+ 'SUN',
323
+ 'MON',
324
+ 'TUE',
325
+ 'WED',
326
+ 'THU',
327
+ 'FRI',
328
+ 'SAT'
329
+ ];
330
+ return days[new Date(`${dateStr}T00:00:00Z`).getUTCDay()];
331
+ }
332
+ weekdayNameToIndex(day) {
333
+ const map = {
334
+ SUN: 0,
335
+ MON: 1,
336
+ TUE: 2,
337
+ WED: 3,
338
+ THU: 4,
339
+ FRI: 5,
340
+ SAT: 6
341
+ };
342
+ return map[day.toUpperCase()] ?? 0;
343
+ }
344
+ getWeekStart(dateStr) {
345
+ const d = new Date(`${dateStr}T00:00:00Z`);
346
+ d.setUTCDate(d.getUTCDate() - d.getUTCDay());
347
+ return d.toISOString().slice(0, 10);
348
+ }
349
+ addDaysToDate(dateStr, days) {
350
+ const d = new Date(`${dateStr}T00:00:00Z`);
351
+ d.setUTCDate(d.getUTCDate() + days);
352
+ return d.toISOString().slice(0, 10);
340
353
  }
341
354
  getNextOccurrenceDate(current, recurrenceType, originalDayOfMonth) {
342
- const next = new Date(current);
355
+ const d = new Date(`${current}T00:00:00Z`);
343
356
  switch(recurrenceType){
344
357
  case RecurrenceType.DAILY:
345
- next.setDate(next.getDate() + 1);
358
+ d.setUTCDate(d.getUTCDate() + 1);
346
359
  break;
347
360
  case RecurrenceType.MONTHLY:
348
361
  {
349
- const targetDay = originalDayOfMonth ?? current.getDate();
350
- next.setMonth(next.getMonth() + 1);
351
- const lastDayOfMonth = new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate();
352
- next.setDate(Math.min(targetDay, lastDayOfMonth));
362
+ const targetDay = originalDayOfMonth ?? d.getUTCDate();
363
+ d.setUTCMonth(d.getUTCMonth() + 1);
364
+ const lastDayOfMonth = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 0)).getUTCDate();
365
+ d.setUTCDate(Math.min(targetDay, lastDayOfMonth));
353
366
  break;
354
367
  }
355
368
  default:
356
369
  break;
357
370
  }
358
- return next;
371
+ return d.toISOString().slice(0, 10);
359
372
  }
360
373
  // Private transformation helpers
361
374
  toCalendarEvent(event) {
@@ -363,15 +376,16 @@ export class EventService extends RequestScopedApiService {
363
376
  id: event.id,
364
377
  title: event.title,
365
378
  description: event.description,
366
- meetingLink: event.meetingLink,
367
- startDateTime: event.startDateTime,
368
- endDateTime: event.endDateTime,
379
+ eventDate: event.eventDate,
380
+ startTime: event.startTime,
381
+ endTime: event.endTime,
369
382
  isAllDay: event.isAllDay,
370
383
  recurrenceType: event.recurrenceType,
371
384
  recurrenceEndDate: event.recurrenceEndDate,
385
+ weekDays: event.weekDays,
372
386
  color: event.color,
387
+ meetingLink: event.meetingLink ?? null,
373
388
  isActive: event.isActive,
374
- metadata: event.metadata,
375
389
  createdAt: event.createdAt,
376
390
  updatedAt: event.updatedAt,
377
391
  deletedAt: event.deletedAt,
@@ -381,6 +395,15 @@ export class EventService extends RequestScopedApiService {
381
395
  participants: event.participants?.map((p)=>this.toParticipantInfo(p))
382
396
  };
383
397
  }
398
+ toCalendarEventOnDate(event, occurrenceDate, isRecurrenceInstance) {
399
+ return {
400
+ ...this.toCalendarEvent(event),
401
+ id: `${event.id}_${occurrenceDate}`,
402
+ originalEventId: event.id,
403
+ isRecurrenceInstance,
404
+ eventDate: occurrenceDate
405
+ };
406
+ }
384
407
  toParticipantInfo(p) {
385
408
  return {
386
409
  id: p.id,
@@ -388,7 +411,6 @@ export class EventService extends RequestScopedApiService {
388
411
  userId: p.userId,
389
412
  status: p.status,
390
413
  isOrganizer: p.isOrganizer,
391
- metadata: p.metadata,
392
414
  createdAt: p.createdAt,
393
415
  updatedAt: p.updatedAt,
394
416
  deletedAt: p.deletedAt,
@@ -403,17 +425,16 @@ export class EventService extends RequestScopedApiService {
403
425
  }
404
426
  _ts_decorate([
405
427
  LogAction({
406
- action: 'event.addParticipants',
428
+ action: 'eventParticipant.updateStatus',
407
429
  module: 'event-manager'
408
430
  }),
409
431
  _ts_metadata("design:type", Function),
410
432
  _ts_metadata("design:paramtypes", [
411
- String,
412
- Array,
433
+ typeof UpdateParticipantStatusDto === "undefined" ? Object : UpdateParticipantStatusDto,
413
434
  Object
414
435
  ]),
415
436
  _ts_metadata("design:returntype", Promise)
416
- ], EventService.prototype, "addParticipants", null);
437
+ ], EventService.prototype, "updateParticipantStatus", null);
417
438
  EventService = _ts_decorate([
418
439
  Injectable({
419
440
  scope: Scope.REQUEST
@@ -2,4 +2,3 @@ export * from './event-manager-config.service';
2
2
  export * from './event-manager-datasource.provider';
3
3
  export * from './event-manager-helper.service';
4
4
  export * from './event.service';
5
- export * from './event-participant.service';
@@ -3,15 +3,16 @@ import { IIdentity } from '@flusys/nestjs-shared/interfaces';
3
3
  export interface IEvent extends IIdentity {
4
4
  title: string;
5
5
  description: string | null;
6
- meetingLink: string | null;
7
- startDateTime: Date;
8
- endDateTime: Date;
6
+ eventDate: string;
7
+ startTime: string;
8
+ endTime: string;
9
9
  isAllDay: boolean;
10
10
  recurrenceType: RecurrenceType | string;
11
- recurrenceEndDate: Date | null;
11
+ recurrenceEndDate: string | null;
12
+ weekDays: string[] | null;
12
13
  color: string;
14
+ meetingLink: string | null;
13
15
  isActive: boolean;
14
- metadata: Record<string, unknown> | null;
15
16
  companyId?: string | null;
16
17
  }
17
18
  export interface IEventParticipant extends IIdentity {
@@ -19,7 +20,6 @@ export interface IEventParticipant extends IIdentity {
19
20
  userId: string;
20
21
  status: ParticipantStatus | string;
21
22
  isOrganizer: boolean;
22
- metadata: Record<string, unknown> | null;
23
23
  }
24
24
  export interface ICalendarEvent extends IEvent {
25
25
  originalEventId?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flusys/nestjs-event-manager",
3
- "version": "4.1.0",
3
+ "version": "5.0.0",
4
4
  "description": "Event manager module with calendar support and recurrence",
5
5
  "main": "cjs/index.js",
6
6
  "module": "fesm/index.js",
@@ -84,7 +84,7 @@
84
84
  "express": "^4.18.0"
85
85
  },
86
86
  "dependencies": {
87
- "@flusys/nestjs-core": "4.1.0",
88
- "@flusys/nestjs-shared": "4.1.0"
87
+ "@flusys/nestjs-core": "5.0.0",
88
+ "@flusys/nestjs-shared": "5.0.0"
89
89
  }
90
90
  }
@@ -15,10 +15,8 @@ export declare class EventManagerHelperService {
15
15
  private getEventRepository;
16
16
  private getParticipantRepository;
17
17
  createEvent(options: CreateEventOptions): Promise<EventResult>;
18
- addParticipants(eventId: string, userIds: string[], _companyId?: string): Promise<void>;
19
- removeParticipant(eventId: string, userId: string): Promise<void>;
20
18
  updateParticipantStatus(participantId: string, status: ParticipantStatus): Promise<void>;
21
- getEventsForUser(userId: string, startDate: Date, endDate: Date, companyId?: string): Promise<EventResult[]>;
19
+ getEventsForUser(userId: string, startDate: string, endDate: string, companyId?: string): Promise<EventResult[]>;
22
20
  getEventById(eventId: string): Promise<EventResult | null>;
23
21
  private addEventParticipants;
24
22
  private toEventResult;
@@ -3,13 +3,10 @@ import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
3
  import { UtilsService } from '@flusys/nestjs-shared/modules';
4
4
  import { EntityTarget, QueryRunner, Repository, SelectQueryBuilder } from 'typeorm';
5
5
  import { EventManagerConfigService } from './event-manager-config.service';
6
- import { CalendarQueryDto, CreateEventDto, UpdateEventDto } from '../dtos';
6
+ import { CalendarQueryDto, CreateEventDto, UpdateEventDto, UpdateParticipantStatusDto } from '../dtos';
7
7
  import { EventBase, EventParticipant } from '../entities';
8
8
  import { ICalendarEvent, IEvent } from '../interfaces';
9
9
  import { EventManagerDataSourceProvider } from './event-manager-datasource.provider';
10
- type EventWithParticipants = Omit<EventBase, 'participants'> & {
11
- participants?: EventParticipant[];
12
- };
13
10
  export declare class EventService extends RequestScopedApiService<CreateEventDto, UpdateEventDto, IEvent, EventBase, Repository<EventBase>> {
14
11
  protected cacheManager: HybridCache;
15
12
  protected utilsService: UtilsService;
@@ -30,9 +27,9 @@ export declare class EventService extends RequestScopedApiService<CreateEventDto
30
27
  isRaw: boolean;
31
28
  }>;
32
29
  protected afterInsertOperation(entities: EventBase[], user: ILoggedUserInfo | null, _qr: QueryRunner): Promise<void>;
30
+ protected afterUpdateOperation(entities: EventBase[], user: ILoggedUserInfo | null, _qr: QueryRunner): Promise<void>;
33
31
  getEventsForCalendarRange(queryDto: CalendarQueryDto, user: ILoggedUserInfo | null): Promise<ICalendarEvent[]>;
34
- getEventWithParticipants(id: string, user: ILoggedUserInfo | null): Promise<EventWithParticipants | null>;
35
- addParticipants(eventId: string, userIds: string[], _user: ILoggedUserInfo | null): Promise<EventParticipant[]>;
32
+ updateParticipantStatus(dto: UpdateParticipantStatusDto, _user: ILoggedUserInfo | null): Promise<EventParticipant>;
36
33
  private addCreatorAndParticipants;
37
34
  private expandRecurringEvents;
38
35
  private generateOccurrences;
@@ -41,9 +38,12 @@ export declare class EventService extends RequestScopedApiService<CreateEventDto
41
38
  private loadParticipantsForEvents;
42
39
  private applyEventCompanyFilter;
43
40
  private shouldStopRecurrence;
44
- private tryCreateOccurrence;
41
+ private getDayOfWeek;
42
+ private weekdayNameToIndex;
43
+ private getWeekStart;
44
+ private addDaysToDate;
45
45
  private getNextOccurrenceDate;
46
46
  private toCalendarEvent;
47
+ private toCalendarEventOnDate;
47
48
  private toParticipantInfo;
48
49
  }
49
- export {};
@@ -2,4 +2,3 @@ export * from './event-manager-config.service';
2
2
  export * from './event-manager-datasource.provider';
3
3
  export * from './event-manager-helper.service';
4
4
  export * from './event.service';
5
- export * from './event-participant.service';