@flusys/nestjs-event-manager 3.0.1

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 (89) hide show
  1. package/README.md +1328 -0
  2. package/adapters/event-manager.adapter.d.ts +12 -0
  3. package/adapters/index.d.ts +1 -0
  4. package/cjs/adapters/event-manager.adapter.js +71 -0
  5. package/cjs/adapters/index.js +18 -0
  6. package/cjs/config/event-manager.constants.js +13 -0
  7. package/cjs/config/index.js +18 -0
  8. package/cjs/controllers/event-participant.controller.js +271 -0
  9. package/cjs/controllers/event.controller.js +229 -0
  10. package/cjs/controllers/index.js +19 -0
  11. package/cjs/docs/event-manager-swagger.config.js +135 -0
  12. package/cjs/docs/index.js +24 -0
  13. package/cjs/dtos/calendar-query.dto.js +186 -0
  14. package/cjs/dtos/event-participant.dto.js +226 -0
  15. package/cjs/dtos/event.dto.js +291 -0
  16. package/cjs/dtos/index.js +20 -0
  17. package/cjs/entities/event-participant.entity.js +96 -0
  18. package/cjs/entities/event-with-company.entity.js +56 -0
  19. package/cjs/entities/event.entity.js +143 -0
  20. package/cjs/entities/index.js +55 -0
  21. package/cjs/index.js +27 -0
  22. package/cjs/interfaces/event-manager-module.interface.js +4 -0
  23. package/cjs/interfaces/event.interface.js +4 -0
  24. package/cjs/interfaces/index.js +19 -0
  25. package/cjs/modules/event-manager.module.js +133 -0
  26. package/cjs/modules/index.js +18 -0
  27. package/cjs/services/event-manager-config.service.js +76 -0
  28. package/cjs/services/event-manager-datasource.provider.js +181 -0
  29. package/cjs/services/event-manager-helper.service.js +253 -0
  30. package/cjs/services/event-participant.service.js +164 -0
  31. package/cjs/services/event.service.js +421 -0
  32. package/cjs/services/index.js +22 -0
  33. package/config/event-manager.constants.d.ts +1 -0
  34. package/config/index.d.ts +1 -0
  35. package/controllers/event-participant.controller.d.ts +31 -0
  36. package/controllers/event.controller.d.ts +24 -0
  37. package/controllers/index.d.ts +2 -0
  38. package/docs/event-manager-swagger.config.d.ts +3 -0
  39. package/docs/index.d.ts +2 -0
  40. package/dtos/calendar-query.dto.d.ts +23 -0
  41. package/dtos/event-participant.dto.d.ts +31 -0
  42. package/dtos/event.dto.d.ts +37 -0
  43. package/dtos/index.d.ts +3 -0
  44. package/entities/event-participant.entity.d.ts +8 -0
  45. package/entities/event-with-company.entity.d.ts +4 -0
  46. package/entities/event.entity.d.ts +14 -0
  47. package/entities/index.d.ts +11 -0
  48. package/fesm/adapters/event-manager.adapter.js +61 -0
  49. package/fesm/adapters/index.js +1 -0
  50. package/fesm/config/event-manager.constants.js +3 -0
  51. package/fesm/config/index.js +1 -0
  52. package/fesm/controllers/event-participant.controller.js +261 -0
  53. package/fesm/controllers/event.controller.js +219 -0
  54. package/fesm/controllers/index.js +2 -0
  55. package/fesm/docs/event-manager-swagger.config.js +128 -0
  56. package/fesm/docs/index.js +4 -0
  57. package/fesm/dtos/calendar-query.dto.js +168 -0
  58. package/fesm/dtos/event-participant.dto.js +199 -0
  59. package/fesm/dtos/event.dto.js +270 -0
  60. package/fesm/dtos/index.js +3 -0
  61. package/fesm/entities/event-participant.entity.js +86 -0
  62. package/fesm/entities/event-with-company.entity.js +46 -0
  63. package/fesm/entities/event.entity.js +133 -0
  64. package/fesm/entities/index.js +24 -0
  65. package/fesm/index.js +10 -0
  66. package/fesm/interfaces/event-manager-module.interface.js +3 -0
  67. package/fesm/interfaces/event.interface.js +1 -0
  68. package/fesm/interfaces/index.js +2 -0
  69. package/fesm/modules/event-manager.module.js +123 -0
  70. package/fesm/modules/index.js +1 -0
  71. package/fesm/services/event-manager-config.service.js +66 -0
  72. package/fesm/services/event-manager-datasource.provider.js +130 -0
  73. package/fesm/services/event-manager-helper.service.js +243 -0
  74. package/fesm/services/event-participant.service.js +154 -0
  75. package/fesm/services/event.service.js +411 -0
  76. package/fesm/services/index.js +5 -0
  77. package/index.d.ts +9 -0
  78. package/interfaces/event-manager-module.interface.d.ts +20 -0
  79. package/interfaces/event.interface.d.ts +28 -0
  80. package/interfaces/index.d.ts +2 -0
  81. package/modules/event-manager.module.d.ts +8 -0
  82. package/modules/index.d.ts +1 -0
  83. package/package.json +89 -0
  84. package/services/event-manager-config.service.d.ts +13 -0
  85. package/services/event-manager-datasource.provider.d.ts +23 -0
  86. package/services/event-manager-helper.service.d.ts +27 -0
  87. package/services/event-participant.service.d.ts +27 -0
  88. package/services/event.service.d.ts +49 -0
  89. package/services/index.d.ts +5 -0
@@ -0,0 +1,164 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "EventParticipantService", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return EventParticipantService;
9
+ }
10
+ });
11
+ const _classes = require("@flusys/nestjs-shared/classes");
12
+ const _enums = require("@flusys/nestjs-shared/enums");
13
+ const _modules = require("@flusys/nestjs-shared/modules");
14
+ const _common = require("@nestjs/common");
15
+ const _eventmanagerconfigservice = require("./event-manager-config.service");
16
+ const _entities = require("../entities");
17
+ const _eventmanagerdatasourceprovider = require("./event-manager-datasource.provider");
18
+ function _define_property(obj, key, value) {
19
+ if (key in obj) {
20
+ Object.defineProperty(obj, key, {
21
+ value: value,
22
+ enumerable: true,
23
+ configurable: true,
24
+ writable: true
25
+ });
26
+ } else {
27
+ obj[key] = value;
28
+ }
29
+ return obj;
30
+ }
31
+ function _ts_decorate(decorators, target, key, desc) {
32
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
33
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
34
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
35
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
36
+ }
37
+ function _ts_metadata(k, v) {
38
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
39
+ }
40
+ function _ts_param(paramIndex, decorator) {
41
+ return function(target, key) {
42
+ decorator(target, key, paramIndex);
43
+ };
44
+ }
45
+ let EventParticipantService = class EventParticipantService extends _classes.RequestScopedApiService {
46
+ resolveEntity() {
47
+ // EventParticipant doesn't need company variant - company context is inherited through Event
48
+ return _entities.EventParticipant;
49
+ }
50
+ getDataSourceProvider() {
51
+ return this.dataSourceProvider;
52
+ }
53
+ // Override Methods
54
+ async convertSingleDtoToEntity(dto, _user) {
55
+ let entity = {};
56
+ if ('id' in dto && dto.id && typeof dto.id === 'string') {
57
+ const existing = await this.repository.findOne({
58
+ where: {
59
+ id: dto.id
60
+ }
61
+ });
62
+ if (!existing) throw new _common.NotFoundException('Event participant not found');
63
+ entity = existing;
64
+ }
65
+ // EventParticipant doesn't have companyId - company context comes from Event
66
+ return {
67
+ ...entity,
68
+ eventId: dto.eventId ?? entity.eventId,
69
+ userId: dto.userId ?? entity.userId,
70
+ status: dto.status ?? entity.status ?? _enums.ParticipantStatus.PENDING,
71
+ isOrganizer: dto.isOrganizer ?? entity.isOrganizer ?? false,
72
+ metadata: dto.metadata ?? entity.metadata
73
+ };
74
+ }
75
+ async getFilterQuery(query, filter, _user) {
76
+ for (const [key, value] of Object.entries(filter)){
77
+ if (key === 'eventId') {
78
+ query.andWhere(`${this.entityName}.eventId = :eventId`, {
79
+ eventId: value
80
+ });
81
+ } else if (key === 'userId') {
82
+ query.andWhere(`${this.entityName}.userId = :userId`, {
83
+ userId: value
84
+ });
85
+ } else if (key === 'status') {
86
+ query.andWhere(`${this.entityName}.status = :status`, {
87
+ status: value
88
+ });
89
+ } else if (key === 'isOrganizer' && typeof value === 'boolean') {
90
+ query.andWhere(`${this.entityName}.isOrganizer = :isOrganizer`, {
91
+ isOrganizer: value
92
+ });
93
+ } else {
94
+ query.andWhere(`${this.entityName}.${key} = :value`, {
95
+ value
96
+ });
97
+ }
98
+ }
99
+ return {
100
+ query,
101
+ isRaw: false
102
+ };
103
+ }
104
+ // Public Methods
105
+ // Note: EventParticipant doesn't have companyId - company filtering happens at Event level
106
+ async updateStatus(dto, _user) {
107
+ await this.ensureRepositoryInitialized();
108
+ const participant = await this.repository.findOne({
109
+ where: {
110
+ id: dto.id
111
+ }
112
+ });
113
+ if (!participant) {
114
+ throw new _common.NotFoundException('Event participant not found');
115
+ }
116
+ participant.status = dto.status;
117
+ return this.repository.save(participant);
118
+ }
119
+ async getParticipantsByEvent(eventId, _user) {
120
+ await this.ensureRepositoryInitialized();
121
+ // Company filtering happens at Event level, not participant level
122
+ return this.repository.createQueryBuilder('event_participant').where('event_participant.eventId = :eventId', {
123
+ eventId
124
+ }).andWhere('event_participant.deletedAt IS NULL').getMany();
125
+ }
126
+ async getParticipantsByUser(userId, _user) {
127
+ await this.ensureRepositoryInitialized();
128
+ // Company filtering happens at Event level, not participant level
129
+ return this.repository.createQueryBuilder('event_participant').where('event_participant.userId = :userId', {
130
+ userId
131
+ }).andWhere('event_participant.deletedAt IS NULL').getMany();
132
+ }
133
+ async removeParticipant(eventId, userId, _user) {
134
+ await this.ensureRepositoryInitialized();
135
+ const participant = await this.repository.findOne({
136
+ where: {
137
+ eventId,
138
+ userId
139
+ }
140
+ });
141
+ if (participant) {
142
+ await this.repository.softRemove(participant);
143
+ }
144
+ }
145
+ constructor(cacheManager, utilsService, eventConfig, dataSourceProvider){
146
+ super('event_participant', null, cacheManager, utilsService, EventParticipantService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "eventConfig", void 0), _define_property(this, "dataSourceProvider", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.eventConfig = eventConfig, this.dataSourceProvider = dataSourceProvider;
147
+ }
148
+ };
149
+ EventParticipantService = _ts_decorate([
150
+ (0, _common.Injectable)({
151
+ scope: _common.Scope.REQUEST
152
+ }),
153
+ _ts_param(0, (0, _common.Inject)('CACHE_INSTANCE')),
154
+ _ts_param(1, (0, _common.Inject)(_modules.UtilsService)),
155
+ _ts_param(2, (0, _common.Inject)(_eventmanagerconfigservice.EventManagerConfigService)),
156
+ _ts_param(3, (0, _common.Inject)(_eventmanagerdatasourceprovider.EventManagerDataSourceProvider)),
157
+ _ts_metadata("design:type", Function),
158
+ _ts_metadata("design:paramtypes", [
159
+ typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
160
+ typeof _modules.UtilsService === "undefined" ? Object : _modules.UtilsService,
161
+ typeof _eventmanagerconfigservice.EventManagerConfigService === "undefined" ? Object : _eventmanagerconfigservice.EventManagerConfigService,
162
+ typeof _eventmanagerdatasourceprovider.EventManagerDataSourceProvider === "undefined" ? Object : _eventmanagerdatasourceprovider.EventManagerDataSourceProvider
163
+ ])
164
+ ], EventParticipantService);
@@ -0,0 +1,421 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "EventService", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return EventService;
9
+ }
10
+ });
11
+ const _classes = require("@flusys/nestjs-shared/classes");
12
+ const _enums = require("@flusys/nestjs-shared/enums");
13
+ const _modules = require("@flusys/nestjs-shared/modules");
14
+ const _utils = require("@flusys/nestjs-shared/utils");
15
+ const _common = require("@nestjs/common");
16
+ const _typeorm = require("typeorm");
17
+ const _eventmanagerconfigservice = require("./event-manager-config.service");
18
+ const _entities = require("../entities");
19
+ const _eventmanagerdatasourceprovider = require("./event-manager-datasource.provider");
20
+ function _define_property(obj, key, value) {
21
+ if (key in obj) {
22
+ Object.defineProperty(obj, key, {
23
+ value: value,
24
+ enumerable: true,
25
+ configurable: true,
26
+ writable: true
27
+ });
28
+ } else {
29
+ obj[key] = value;
30
+ }
31
+ return obj;
32
+ }
33
+ function _ts_decorate(decorators, target, key, desc) {
34
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
35
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
36
+ else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
37
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
38
+ }
39
+ function _ts_metadata(k, v) {
40
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
41
+ }
42
+ function _ts_param(paramIndex, decorator) {
43
+ return function(target, key) {
44
+ decorator(target, key, paramIndex);
45
+ };
46
+ }
47
+ let EventService = class EventService extends _classes.RequestScopedApiService {
48
+ // Abstract implementations
49
+ resolveEntity() {
50
+ return this.eventConfig.isCompanyFeatureEnabled() ? _entities.EventWithCompany : _entities.Event;
51
+ }
52
+ getDataSourceProvider() {
53
+ return this.dataSourceProvider;
54
+ }
55
+ // Override methods
56
+ async convertSingleDtoToEntity(dto, user) {
57
+ let entity = {};
58
+ if ('id' in dto && dto.id && typeof dto.id === 'string') {
59
+ const existing = await this.repository.findOne({
60
+ where: {
61
+ id: dto.id
62
+ }
63
+ });
64
+ if (!existing) throw new _common.NotFoundException('Event not found');
65
+ entity = existing;
66
+ }
67
+ const merged = {
68
+ ...entity,
69
+ title: dto.title ?? entity.title,
70
+ description: dto.description ?? entity.description,
71
+ meetingLink: dto.meetingLink ?? entity.meetingLink,
72
+ startDateTime: dto.startDateTime ?? entity.startDateTime,
73
+ endDateTime: dto.endDateTime ?? entity.endDateTime,
74
+ isAllDay: dto.isAllDay ?? entity.isAllDay ?? false,
75
+ recurrenceType: dto.recurrenceType ?? entity.recurrenceType ?? _enums.RecurrenceType.NONE,
76
+ recurrenceEndDate: dto.recurrenceEndDate ?? entity.recurrenceEndDate,
77
+ color: dto.color ?? entity.color ?? this.eventConfig.getDefaultColor(),
78
+ isActive: dto.isActive ?? entity.isActive ?? true,
79
+ metadata: dto.metadata ?? entity.metadata
80
+ };
81
+ if (this.eventConfig.isCompanyFeatureEnabled()) {
82
+ merged.companyId = user?.companyId ?? null;
83
+ }
84
+ if ('participantIds' in dto) {
85
+ this.pendingParticipantsList.push(dto.participantIds ?? []);
86
+ }
87
+ return merged;
88
+ }
89
+ async getFilterQuery(query, filter, _user) {
90
+ for (const [key, value] of Object.entries(filter)){
91
+ if (key === 'isActive' && typeof value === 'boolean') {
92
+ query.andWhere(`${this.entityName}.isActive = :isActive`, {
93
+ isActive: value
94
+ });
95
+ } else if (key === 'recurrenceType') {
96
+ query.andWhere(`${this.entityName}.recurrenceType = :recurrenceType`, {
97
+ recurrenceType: value
98
+ });
99
+ } else if (key === 'participantUserId' && value) {
100
+ const eventIds = await this.getParticipantEventIds(value);
101
+ if (eventIds.length > 0) {
102
+ query.andWhere(`${this.entityName}.id IN (:...participantEventIds)`, {
103
+ participantEventIds: eventIds
104
+ });
105
+ } else {
106
+ query.andWhere('1 = 0');
107
+ }
108
+ } else {
109
+ query.andWhere(`${this.entityName}.${key} = :value`, {
110
+ value
111
+ });
112
+ }
113
+ }
114
+ return {
115
+ query,
116
+ isRaw: false
117
+ };
118
+ }
119
+ async getExtraManipulateQuery(query, filterDto, user) {
120
+ const result = await super.getExtraManipulateQuery(query, filterDto, user);
121
+ this.applyEventCompanyFilter(query, user);
122
+ return result;
123
+ }
124
+ async afterInsertOperation(entities, user, _qr) {
125
+ for(let i = 0; i < entities.length; i++){
126
+ const participantIds = this.pendingParticipantsList[i] ?? [];
127
+ await this.addCreatorAndParticipants(entities[i].id, participantIds, user);
128
+ }
129
+ this.pendingParticipantsList = [];
130
+ }
131
+ // Public API methods
132
+ async getEventsForCalendarRange(queryDto, user) {
133
+ await this.ensureRepositoryInitialized();
134
+ const query = this.repository.createQueryBuilder('event').where('event.deletedAt IS NULL').andWhere('event.isActive = :isActive', {
135
+ isActive: queryDto.activeOnly !== false
136
+ });
137
+ query.andWhere('(event.startDateTime <= :endDate AND event.endDateTime >= :startDate)', {
138
+ startDate: queryDto.startDate,
139
+ endDate: queryDto.endDate
140
+ });
141
+ query.orWhere('event.deletedAt IS NULL AND event.recurrenceType != :none AND event.startDateTime <= :endDate AND (event.recurrenceEndDate IS NULL OR event.recurrenceEndDate >= :startDate)', {
142
+ none: _enums.RecurrenceType.NONE,
143
+ startDate: queryDto.startDate,
144
+ endDate: queryDto.endDate
145
+ });
146
+ this.applyEventCompanyFilter(query, user);
147
+ if (queryDto.userId) {
148
+ const eventIds = await this.getParticipantEventIds(queryDto.userId);
149
+ if (eventIds.length > 0) {
150
+ query.andWhere('event.id IN (:...eventIds)', {
151
+ eventIds
152
+ });
153
+ } else {
154
+ return [];
155
+ }
156
+ }
157
+ const events = await query.getMany();
158
+ if (queryDto.includeParticipants && events.length > 0) {
159
+ await this.loadParticipantsForEvents(events);
160
+ }
161
+ return this.expandRecurringEvents(events, queryDto.startDate, queryDto.endDate);
162
+ }
163
+ async getEventWithParticipants(id, user) {
164
+ await this.ensureRepositoryInitialized();
165
+ const query = this.repository.createQueryBuilder('event').where('event.id = :id', {
166
+ id
167
+ }).andWhere('event.deletedAt IS NULL');
168
+ this.applyEventCompanyFilter(query, user);
169
+ const event = await query.getOne();
170
+ if (event) {
171
+ const participantRepo = await this.ensureParticipantRepositoryInitialized();
172
+ event.participants = await participantRepo.find({
173
+ where: {
174
+ eventId: id,
175
+ deletedAt: (0, _typeorm.IsNull)()
176
+ }
177
+ });
178
+ }
179
+ return event;
180
+ }
181
+ async addParticipants(eventId, userIds, _user) {
182
+ await this.ensureRepositoryInitialized();
183
+ const participantRepo = await this.ensureParticipantRepositoryInitialized();
184
+ const event = await this.repository.findOne({
185
+ where: {
186
+ id: eventId,
187
+ deletedAt: (0, _typeorm.IsNull)()
188
+ }
189
+ });
190
+ if (!event) {
191
+ throw new _common.NotFoundException('Event not found');
192
+ }
193
+ const existingParticipants = await participantRepo.find({
194
+ where: {
195
+ eventId,
196
+ userId: (0, _typeorm.In)(userIds),
197
+ deletedAt: (0, _typeorm.IsNull)()
198
+ }
199
+ });
200
+ const existingUserIds = new Set(existingParticipants.map((p)=>p.userId));
201
+ const newParticipants = userIds.filter((userId)=>!existingUserIds.has(userId)).map((userId)=>({
202
+ eventId,
203
+ userId,
204
+ isOrganizer: false
205
+ }));
206
+ if (newParticipants.length === 0) {
207
+ return existingParticipants;
208
+ }
209
+ const created = await participantRepo.save(newParticipants);
210
+ return [
211
+ ...existingParticipants,
212
+ ...created
213
+ ];
214
+ }
215
+ // Private business logic helpers
216
+ async addCreatorAndParticipants(eventId, participantIds, user) {
217
+ if (!user?.id) return;
218
+ const participantRepo = await this.ensureParticipantRepositoryInitialized();
219
+ const allUserIds = new Set([
220
+ user.id,
221
+ ...participantIds
222
+ ]);
223
+ const participants = Array.from(allUserIds).map((userId)=>({
224
+ eventId,
225
+ userId,
226
+ isOrganizer: userId === user.id
227
+ }));
228
+ await participantRepo.save(participants);
229
+ }
230
+ expandRecurringEvents(events, rangeStart, rangeEnd) {
231
+ const result = [];
232
+ const maxOccurrences = this.eventConfig.getMaxRecurrenceOccurrences();
233
+ for (const event of events){
234
+ if (event.recurrenceType === _enums.RecurrenceType.NONE) {
235
+ result.push(this.toCalendarEvent(event));
236
+ } else {
237
+ result.push(...this.generateOccurrences(event, rangeStart, rangeEnd, maxOccurrences));
238
+ }
239
+ }
240
+ return result.sort((a, b)=>new Date(a.startDateTime).getTime() - new Date(b.startDateTime).getTime());
241
+ }
242
+ generateOccurrences(event, rangeStart, rangeEnd, maxOccurrences) {
243
+ const occurrences = [];
244
+ const eventDuration = new Date(event.endDateTime).getTime() - new Date(event.startDateTime).getTime();
245
+ const recurrenceEnd = event.recurrenceEndDate ? new Date(event.recurrenceEndDate) : null;
246
+ const recurrenceType = event.recurrenceType;
247
+ const recurrenceDays = event.metadata?.recurrenceDays || [
248
+ new Date(event.startDateTime).getDay()
249
+ ];
250
+ let currentStart = new Date(event.startDateTime);
251
+ let count = 0;
252
+ if (recurrenceType === _enums.RecurrenceType.WEEKLY || recurrenceType === _enums.RecurrenceType.BIWEEKLY) {
253
+ let weekStart = new Date(event.startDateTime);
254
+ weekStart.setDate(weekStart.getDate() - weekStart.getDay());
255
+ while(count < maxOccurrences){
256
+ for (const dayOfWeek of recurrenceDays){
257
+ if (count >= maxOccurrences) break;
258
+ currentStart = new Date(weekStart);
259
+ currentStart.setDate(currentStart.getDate() + dayOfWeek);
260
+ currentStart.setHours(new Date(event.startDateTime).getHours());
261
+ currentStart.setMinutes(new Date(event.startDateTime).getMinutes());
262
+ if (currentStart < new Date(event.startDateTime)) continue;
263
+ const shouldBreak = this.shouldStopRecurrence(currentStart, recurrenceEnd, rangeEnd);
264
+ if (shouldBreak) {
265
+ count = maxOccurrences;
266
+ break;
267
+ }
268
+ const occurrence = this.tryCreateOccurrence(event, currentStart, eventDuration, rangeStart, rangeEnd, occurrences.length > 0);
269
+ if (occurrence) occurrences.push(occurrence);
270
+ count++;
271
+ }
272
+ const weeksToAdd = recurrenceType === _enums.RecurrenceType.BIWEEKLY ? 2 : 1;
273
+ weekStart.setDate(weekStart.getDate() + 7 * weeksToAdd);
274
+ }
275
+ } else {
276
+ const originalDayOfMonth = new Date(event.startDateTime).getDate();
277
+ while(count < maxOccurrences){
278
+ if (this.shouldStopRecurrence(currentStart, recurrenceEnd, rangeEnd)) break;
279
+ const occurrence = this.tryCreateOccurrence(event, currentStart, eventDuration, rangeStart, rangeEnd, count > 0);
280
+ if (occurrence) occurrences.push(occurrence);
281
+ currentStart = this.getNextOccurrenceDate(currentStart, recurrenceType, originalDayOfMonth);
282
+ count++;
283
+ }
284
+ }
285
+ return occurrences;
286
+ }
287
+ // Private utility helpers
288
+ async ensureParticipantRepositoryInitialized() {
289
+ if (!this.participantRepository) {
290
+ this.participantRepository = await this.dataSourceProvider.getRepository(_entities.EventParticipant);
291
+ }
292
+ return this.participantRepository;
293
+ }
294
+ async getParticipantEventIds(userId) {
295
+ const participantRepo = await this.ensureParticipantRepositoryInitialized();
296
+ const results = await participantRepo.createQueryBuilder('ep').select('ep.eventId').where('ep.userId = :userId', {
297
+ userId
298
+ }).andWhere('ep.deletedAt IS NULL').getRawMany();
299
+ return results.map((p)=>p.ep_event_id);
300
+ }
301
+ async loadParticipantsForEvents(events) {
302
+ const participantRepo = await this.ensureParticipantRepositoryInitialized();
303
+ const eventIds = events.map((e)=>e.id);
304
+ const participants = await participantRepo.find({
305
+ where: {
306
+ eventId: (0, _typeorm.In)(eventIds),
307
+ deletedAt: (0, _typeorm.IsNull)()
308
+ }
309
+ });
310
+ const participantsByEvent = new Map();
311
+ for (const p of participants){
312
+ const list = participantsByEvent.get(p.eventId) || [];
313
+ list.push(p);
314
+ participantsByEvent.set(p.eventId, list);
315
+ }
316
+ for (const event of events){
317
+ event.participants = participantsByEvent.get(event.id) || [];
318
+ }
319
+ }
320
+ applyEventCompanyFilter(query, user) {
321
+ (0, _utils.applyCompanyFilter)(query, {
322
+ isCompanyFeatureEnabled: this.eventConfig.isCompanyFeatureEnabled(),
323
+ entityAlias: 'event'
324
+ }, user);
325
+ }
326
+ shouldStopRecurrence(currentStart, recurrenceEnd, rangeEnd) {
327
+ return recurrenceEnd && currentStart > recurrenceEnd || currentStart > rangeEnd;
328
+ }
329
+ tryCreateOccurrence(event, currentStart, eventDuration, rangeStart, rangeEnd, isRecurrenceInstance) {
330
+ const currentEnd = new Date(currentStart.getTime() + eventDuration);
331
+ if (currentEnd >= rangeStart && currentStart <= rangeEnd) {
332
+ return {
333
+ ...this.toCalendarEvent(event),
334
+ id: `${event.id}_${currentStart.toISOString()}`,
335
+ originalEventId: event.id,
336
+ isRecurrenceInstance,
337
+ startDateTime: new Date(currentStart),
338
+ endDateTime: currentEnd
339
+ };
340
+ }
341
+ return null;
342
+ }
343
+ getNextOccurrenceDate(current, recurrenceType, originalDayOfMonth) {
344
+ const next = new Date(current);
345
+ switch(recurrenceType){
346
+ case _enums.RecurrenceType.DAILY:
347
+ next.setDate(next.getDate() + 1);
348
+ break;
349
+ case _enums.RecurrenceType.MONTHLY:
350
+ {
351
+ const targetDay = originalDayOfMonth ?? current.getDate();
352
+ next.setMonth(next.getMonth() + 1);
353
+ const lastDayOfMonth = new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate();
354
+ next.setDate(Math.min(targetDay, lastDayOfMonth));
355
+ break;
356
+ }
357
+ default:
358
+ break;
359
+ }
360
+ return next;
361
+ }
362
+ // Private transformation helpers
363
+ toCalendarEvent(event) {
364
+ return {
365
+ id: event.id,
366
+ title: event.title,
367
+ description: event.description,
368
+ meetingLink: event.meetingLink,
369
+ startDateTime: event.startDateTime,
370
+ endDateTime: event.endDateTime,
371
+ isAllDay: event.isAllDay,
372
+ recurrenceType: event.recurrenceType,
373
+ recurrenceEndDate: event.recurrenceEndDate,
374
+ color: event.color,
375
+ isActive: event.isActive,
376
+ metadata: event.metadata,
377
+ createdAt: event.createdAt,
378
+ updatedAt: event.updatedAt,
379
+ deletedAt: event.deletedAt,
380
+ createdById: event.createdById,
381
+ updatedById: event.updatedById,
382
+ deletedById: event.deletedById,
383
+ participants: event.participants?.map((p)=>this.toParticipantInfo(p))
384
+ };
385
+ }
386
+ toParticipantInfo(p) {
387
+ return {
388
+ id: p.id,
389
+ eventId: p.eventId,
390
+ userId: p.userId,
391
+ status: p.status,
392
+ isOrganizer: p.isOrganizer,
393
+ metadata: p.metadata,
394
+ createdAt: p.createdAt,
395
+ updatedAt: p.updatedAt,
396
+ deletedAt: p.deletedAt,
397
+ createdById: p.createdById,
398
+ updatedById: p.updatedById,
399
+ deletedById: p.deletedById
400
+ };
401
+ }
402
+ constructor(cacheManager, utilsService, eventConfig, dataSourceProvider){
403
+ super('event', null, cacheManager, utilsService, EventService.name, true), _define_property(this, "cacheManager", void 0), _define_property(this, "utilsService", void 0), _define_property(this, "eventConfig", void 0), _define_property(this, "dataSourceProvider", void 0), _define_property(this, "participantRepository", void 0), _define_property(this, "pendingParticipantsList", void 0), this.cacheManager = cacheManager, this.utilsService = utilsService, this.eventConfig = eventConfig, this.dataSourceProvider = dataSourceProvider, this.participantRepository = null, this.pendingParticipantsList = [];
404
+ }
405
+ };
406
+ EventService = _ts_decorate([
407
+ (0, _common.Injectable)({
408
+ scope: _common.Scope.REQUEST
409
+ }),
410
+ _ts_param(0, (0, _common.Inject)('CACHE_INSTANCE')),
411
+ _ts_param(1, (0, _common.Inject)(_modules.UtilsService)),
412
+ _ts_param(2, (0, _common.Inject)(_eventmanagerconfigservice.EventManagerConfigService)),
413
+ _ts_param(3, (0, _common.Inject)(_eventmanagerdatasourceprovider.EventManagerDataSourceProvider)),
414
+ _ts_metadata("design:type", Function),
415
+ _ts_metadata("design:paramtypes", [
416
+ typeof _classes.HybridCache === "undefined" ? Object : _classes.HybridCache,
417
+ typeof _modules.UtilsService === "undefined" ? Object : _modules.UtilsService,
418
+ typeof _eventmanagerconfigservice.EventManagerConfigService === "undefined" ? Object : _eventmanagerconfigservice.EventManagerConfigService,
419
+ typeof _eventmanagerdatasourceprovider.EventManagerDataSourceProvider === "undefined" ? Object : _eventmanagerdatasourceprovider.EventManagerDataSourceProvider
420
+ ])
421
+ ], EventService);
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ _export_star(require("./event-manager-config.service"), exports);
6
+ _export_star(require("./event-manager-datasource.provider"), exports);
7
+ _export_star(require("./event-manager-helper.service"), exports);
8
+ _export_star(require("./event.service"), exports);
9
+ _export_star(require("./event-participant.service"), exports);
10
+ function _export_star(from, to) {
11
+ Object.keys(from).forEach(function(k) {
12
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
13
+ Object.defineProperty(to, k, {
14
+ enumerable: true,
15
+ get: function() {
16
+ return from[k];
17
+ }
18
+ });
19
+ }
20
+ });
21
+ return from;
22
+ }
@@ -0,0 +1 @@
1
+ export declare const EVENT_MANAGER_MODULE_OPTIONS = "EVENT_MANAGER_MODULE_OPTIONS";
@@ -0,0 +1 @@
1
+ export * from './event-manager.constants';
@@ -0,0 +1,31 @@
1
+ import { ListResponseDto, MessageResponseDto, SingleResponseDto } from '@flusys/nestjs-shared/dtos';
2
+ import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
+ import { CreateEventParticipantDto, EventParticipantResponseDto, UpdateParticipantStatusDto, UpdateEventParticipantDto } from '../dtos';
4
+ import { EventParticipantService } from '../services/event-participant.service';
5
+ declare const EventParticipantController_base: abstract new (service: EventParticipantService) => {
6
+ service: EventParticipantService;
7
+ insert(addDto: CreateEventParticipantDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<EventParticipantResponseDto>>;
8
+ insertMany(addDto: CreateEventParticipantDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<EventParticipantResponseDto>>;
9
+ getById(id: string, body: import("@flusys/nestjs-shared/dtos").GetByIdBodyDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<EventParticipantResponseDto>>;
10
+ update(updateDto: UpdateEventParticipantDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<EventParticipantResponseDto>>;
11
+ updateMany(updateDtos: UpdateEventParticipantDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<EventParticipantResponseDto>>;
12
+ getAll(filterAndPaginationDto: import("@flusys/nestjs-shared/dtos").FilterAndPaginationDto, user: ILoggedUserInfo | null, search?: string): Promise<ListResponseDto<EventParticipantResponseDto>>;
13
+ delete(deleteDto: import("@flusys/nestjs-shared/dtos").DeleteDto, user: ILoggedUserInfo | null): Promise<MessageResponseDto>;
14
+ };
15
+ export declare class EventParticipantController extends EventParticipantController_base {
16
+ protected participantService: EventParticipantService;
17
+ constructor(participantService: EventParticipantService);
18
+ updateStatus(dto: UpdateParticipantStatusDto, user: ILoggedUserInfo): Promise<SingleResponseDto<EventParticipantResponseDto>>;
19
+ getByEvent(body: {
20
+ eventId: string;
21
+ }, user: ILoggedUserInfo): Promise<ListResponseDto<EventParticipantResponseDto>>;
22
+ getByUser(body: {
23
+ userId: string;
24
+ }, user: ILoggedUserInfo): Promise<ListResponseDto<EventParticipantResponseDto>>;
25
+ removeParticipant(body: {
26
+ eventId: string;
27
+ userId: string;
28
+ }, user: ILoggedUserInfo): Promise<MessageResponseDto>;
29
+ private buildListResponse;
30
+ }
31
+ export {};
@@ -0,0 +1,24 @@
1
+ import { ListResponseDto, SingleResponseDto } from '@flusys/nestjs-shared/dtos';
2
+ import { ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
3
+ import { BulkAddParticipantsDto, CalendarQueryDto, CalendarEventResponseDto, CreateEventDto, EventParticipantResponseDto, EventResponseDto, UpdateEventDto } from '../dtos';
4
+ import { EventService } from '../services/event.service';
5
+ declare const EventController_base: abstract new (service: EventService) => {
6
+ service: EventService;
7
+ insert(addDto: CreateEventDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<EventResponseDto>>;
8
+ insertMany(addDto: CreateEventDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<EventResponseDto>>;
9
+ getById(id: string, body: import("@flusys/nestjs-shared/dtos").GetByIdBodyDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<EventResponseDto>>;
10
+ update(updateDto: UpdateEventDto, user: ILoggedUserInfo | null): Promise<SingleResponseDto<EventResponseDto>>;
11
+ updateMany(updateDtos: UpdateEventDto[], user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").BulkResponseDto<EventResponseDto>>;
12
+ getAll(filterAndPaginationDto: import("@flusys/nestjs-shared/dtos").FilterAndPaginationDto, user: ILoggedUserInfo | null, search?: string): Promise<ListResponseDto<EventResponseDto>>;
13
+ delete(deleteDto: import("@flusys/nestjs-shared/dtos").DeleteDto, user: ILoggedUserInfo | null): Promise<import("@flusys/nestjs-shared/dtos").MessageResponseDto>;
14
+ };
15
+ export declare class EventController extends EventController_base {
16
+ protected eventService: EventService;
17
+ constructor(eventService: EventService);
18
+ getCalendarEvents(dto: CalendarQueryDto, user: ILoggedUserInfo): Promise<ListResponseDto<CalendarEventResponseDto>>;
19
+ getEventWithParticipants(body: {
20
+ id: string;
21
+ }, user: ILoggedUserInfo): Promise<SingleResponseDto<EventResponseDto>>;
22
+ addParticipants(dto: BulkAddParticipantsDto, user: ILoggedUserInfo): Promise<SingleResponseDto<EventParticipantResponseDto[]>>;
23
+ }
24
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from './event.controller';
2
+ export * from './event-participant.controller';