goldstars-services 1.0.69 → 1.0.71

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.
@@ -7,6 +7,9 @@ exports.default = void 0;
7
7
  var _reservationModel = _interopRequireDefault(require("../models/reservation.model.js"));
8
8
  var _bikeModel = _interopRequireDefault(require("../models/bike.model.js"));
9
9
  var _instructorScheduleService = _interopRequireDefault(require("./instructorSchedule.service.js"));
10
+ var _userSuspensionService = _interopRequireDefault(require("./userSuspension.service.js"));
11
+ var _weeklyScheduleTemplateService = _interopRequireDefault(require("./weeklyScheduleTemplate.service.js"));
12
+ var _scheduleExceptionService = _interopRequireDefault(require("./scheduleException.service.js"));
10
13
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
14
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
12
15
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -16,6 +19,80 @@ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e =
16
19
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
17
20
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; } // MicroService/src/services/reservation.service.js
18
21
  // Needed to check bike status/location
22
+ /**
23
+ * Extrae el time slot string (ej: '7am', '5pm') de un timestamp
24
+ * @param {Date} timestamp - Timestamp UTC
25
+ * @returns {string} - Time slot string (ej: '7am', '8:30am')
26
+ */
27
+ var extractTimeSlotFromTimestamp = timestamp => {
28
+ var hours = timestamp.getHours();
29
+ var minutes = timestamp.getMinutes();
30
+ var period = hours >= 12 ? 'pm' : 'am';
31
+ if (hours > 12) hours -= 12;
32
+ if (hours === 0) hours = 12;
33
+ if (minutes === 0) {
34
+ return "".concat(hours).concat(period);
35
+ } else {
36
+ return "".concat(hours, ":").concat(minutes.toString().padStart(2, '0')).concat(period);
37
+ }
38
+ };
39
+
40
+ /**
41
+ * Verifica si un time slot está disponible para reservas basándose en templates y excepciones
42
+ * @param {string} location - Ubicación
43
+ * @param {Date} timestamp - Timestamp de la reserva (UTC)
44
+ * @returns {Promise<boolean>} - True si está disponible, false si no
45
+ */
46
+ var isTimeSlotAvailableForReservation = /*#__PURE__*/function () {
47
+ var _ref = _asyncToGenerator(function* (location, timestamp) {
48
+ try {
49
+ var dayOfWeek = timestamp.getDay();
50
+
51
+ // Fines de semana no disponibles
52
+ if (dayOfWeek === 0 || dayOfWeek === 6) {
53
+ return false;
54
+ }
55
+ var timeSlot = extractTimeSlotFromTimestamp(timestamp);
56
+
57
+ // 1. Verificar excepciones (tienen prioridad)
58
+ var exceptions = yield _scheduleExceptionService.default.getExceptionsForDate(location, timestamp);
59
+ if (exceptions.length > 0) {
60
+ for (var exc of exceptions) {
61
+ // Si está cerrado, no disponible
62
+ if (exc.exceptionType === 'CLOSED') {
63
+ return false;
64
+ }
65
+
66
+ // Si el slot específico está bloqueado
67
+ if (exc.exceptionType === 'SLOT_BLOCKED' && exc.blockedTimeSlot === timeSlot) {
68
+ return false;
69
+ }
70
+
71
+ // Si hay horarios custom, usar esos
72
+ if (exc.exceptionType === 'CUSTOM_HOURS') {
73
+ return exc.customTimeSlots.some(s => s.time === timeSlot && s.isActive);
74
+ }
75
+ }
76
+ }
77
+
78
+ // 2. Si no hay excepciones, usar template semanal
79
+ var weeklySchedule = yield _weeklyScheduleTemplateService.default.getWeeklyScheduleForDay(location, dayOfWeek);
80
+ if (!weeklySchedule) {
81
+ return false; // No hay horarios configurados para este día
82
+ }
83
+
84
+ // Verificar si el time slot está en el template y está activo
85
+ return weeklySchedule.timeSlots.some(s => s.time === timeSlot && s.isActive);
86
+ } catch (error) {
87
+ console.error('Error verificando disponibilidad de horario:', error);
88
+ return false; // En caso de error, no permitir la reserva
89
+ }
90
+ });
91
+ return function isTimeSlotAvailableForReservation(_x, _x2) {
92
+ return _ref.apply(this, arguments);
93
+ };
94
+ }();
95
+
19
96
  /**
20
97
  * Checks if a bike is already reserved for a specific timestamp.
21
98
  * @param {string} bikeId - The ID of the bike.
@@ -23,7 +100,7 @@ function _asyncToGenerator(n) { return function () { var t = this, e = arguments
23
100
  * @returns {Promise<boolean>} - True if the bike is already reserved, false otherwise.
24
101
  */
25
102
  var isBikeReserved = /*#__PURE__*/function () {
26
- var _ref = _asyncToGenerator(function* (bikeId, timestamp) {
103
+ var _ref2 = _asyncToGenerator(function* (bikeId, timestamp) {
27
104
  var searchTimestamp = new Date(timestamp);
28
105
  if (isNaN(searchTimestamp.getTime())) {
29
106
  throw new Error('Timestamp inválido proporcionado a isBikeReserved.');
@@ -36,8 +113,8 @@ var isBikeReserved = /*#__PURE__*/function () {
36
113
  });
37
114
  return !!existingReservation;
38
115
  });
39
- return function isBikeReserved(_x, _x2) {
40
- return _ref.apply(this, arguments);
116
+ return function isBikeReserved(_x3, _x4) {
117
+ return _ref2.apply(this, arguments);
41
118
  };
42
119
  }();
43
120
 
@@ -52,7 +129,7 @@ var isBikeReserved = /*#__PURE__*/function () {
52
129
  * @throws {Error} - If bike not found, is instructor bike, timestamp invalid, or already reserved.
53
130
  */
54
131
  var createReservation = /*#__PURE__*/function () {
55
- var _ref2 = _asyncToGenerator(function* (reservationData) {
132
+ var _ref3 = _asyncToGenerator(function* (reservationData) {
56
133
  var {
57
134
  userId,
58
135
  bikeId,
@@ -66,28 +143,41 @@ var createReservation = /*#__PURE__*/function () {
66
143
 
67
144
  // --- BEGIN NEW VALIDATIONS ---
68
145
 
69
- // 1. Check if user already has a reservation for this EXACT timestamp
70
- var existingReservationSameSlot = yield _reservationModel.default.findOne({
71
- userId,
72
- timestamp: reservationTimestamp
73
- });
74
- if (existingReservationSameSlot) {
75
- throw new Error('Ya tienes una reserva agendada para esta fecha y hora.');
146
+ // 1. Validaciones por usuario solo aplican cuando hay usuario asociado
147
+ if (userId) {
148
+ // 1.a Verificar suspensión de usuario
149
+ var suspensionCheck = yield _userSuspensionService.default.checkUserSuspension(userId, 'bikes');
150
+ if (suspensionCheck.isSuspended) {
151
+ var untilMessage = suspensionCheck.suspendedUntil ? " hasta ".concat(new Date(suspensionCheck.suspendedUntil).toLocaleDateString('es-VE')) : ' indefinidamente';
152
+ throw new Error("Tu cuenta est\xE1 suspendida".concat(untilMessage, ". Raz\xF3n: ").concat(suspensionCheck.reason));
153
+ }
154
+
155
+ // 1.b Check if user already has a reservation for this EXACT timestamp
156
+ var existingReservationSameSlot = yield _reservationModel.default.findOne({
157
+ userId,
158
+ timestamp: reservationTimestamp
159
+ });
160
+ if (existingReservationSameSlot) {
161
+ throw new Error('Ya tienes una reserva agendada para esta fecha y hora.');
162
+ }
163
+
164
+ // 1.c Check if user already has an UPCOMING reservation
165
+ var now = new Date();
166
+ var existingUpcomingReservation = yield _reservationModel.default.findOne({
167
+ userId,
168
+ timestamp: {
169
+ $gte: now
170
+ } // Find reservations where the timestamp is now or in the future
171
+ });
172
+ if (existingUpcomingReservation) {
173
+ throw new Error('Ya tienes una reserva activa. Debes esperar a que pase para agendar otra.');
174
+ }
76
175
  }
77
176
 
78
- // 2. Check if user already has an UPCOMING reservation
79
- var now = new Date();
80
- var existingUpcomingReservation = yield _reservationModel.default.findOne({
81
- userId,
82
- timestamp: {
83
- $gte: now
84
- } // Find reservations where the timestamp is now or in the future
85
- });
86
- if (existingUpcomingReservation) {
87
- // Optional: Provide more details about the existing reservation if needed
88
- // const existingTime = existingUpcomingReservation.timestamp.toLocaleString('es-VE');
89
- // throw new Error(`Ya tienes una reserva activa para ${existingTime}. Debes esperar a que pase para agendar otra.`);
90
- throw new Error('Ya tienes una reserva activa. Debes esperar a que pase para agendar otra.');
177
+ // 2. Verificar disponibilidad de horario (templates y excepciones)
178
+ var isSlotAvailable = yield isTimeSlotAvailableForReservation(location, reservationTimestamp);
179
+ if (!isSlotAvailable) {
180
+ throw new Error('Este horario no está disponible para reservas en esta ubicación.');
91
181
  }
92
182
 
93
183
  // --- END NEW VALIDATIONS ---
@@ -121,8 +211,8 @@ var createReservation = /*#__PURE__*/function () {
121
211
  yield newReservation.save();
122
212
  return newReservation;
123
213
  });
124
- return function createReservation(_x3) {
125
- return _ref2.apply(this, arguments);
214
+ return function createReservation(_x5) {
215
+ return _ref3.apply(this, arguments);
126
216
  };
127
217
  }();
128
218
 
@@ -134,7 +224,7 @@ var createReservation = /*#__PURE__*/function () {
134
224
  * @returns {Promise<Array<object>>} - An array of bike objects, each with an added 'reservationStatus' field.
135
225
  */
136
226
  var getBikeAvailabilityForSlot = /*#__PURE__*/function () {
137
- var _ref3 = _asyncToGenerator(function* (location, timestamp) {
227
+ var _ref4 = _asyncToGenerator(function* (location, timestamp) {
138
228
  var includeInstructor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
139
229
  var checkTimestamp = new Date(timestamp);
140
230
  if (isNaN(checkTimestamp.getTime())) {
@@ -221,8 +311,8 @@ var getBikeAvailabilityForSlot = /*#__PURE__*/function () {
221
311
  });
222
312
  return bikesWithStatus;
223
313
  });
224
- return function getBikeAvailabilityForSlot(_x4, _x5) {
225
- return _ref3.apply(this, arguments);
314
+ return function getBikeAvailabilityForSlot(_x6, _x7) {
315
+ return _ref4.apply(this, arguments);
226
316
  };
227
317
  }();
228
318
 
@@ -241,7 +331,7 @@ var getBikeAvailabilityForSlot = /*#__PURE__*/function () {
241
331
  * @throws {Error} - If reservation not found or user is not authorized.
242
332
  */
243
333
  var cancelReservation = /*#__PURE__*/function () {
244
- var _ref4 = _asyncToGenerator(function* (reservationId, userId, userRole) {
334
+ var _ref5 = _asyncToGenerator(function* (reservationId, userId, userRole) {
245
335
  var reservation = yield _reservationModel.default.findById(reservationId);
246
336
  if (!reservation) {
247
337
  throw new Error('Reserva no encontrada.');
@@ -261,8 +351,8 @@ var cancelReservation = /*#__PURE__*/function () {
261
351
  message: 'Reserva cancelada exitosamente.'
262
352
  };
263
353
  });
264
- return function cancelReservation(_x6, _x7, _x8) {
265
- return _ref4.apply(this, arguments);
354
+ return function cancelReservation(_x8, _x9, _x10) {
355
+ return _ref5.apply(this, arguments);
266
356
  };
267
357
  }();
268
358
 
@@ -272,12 +362,12 @@ var cancelReservation = /*#__PURE__*/function () {
272
362
  * @returns {Promise<object|null>} - El documento de la reservación o null si no existe.
273
363
  */
274
364
  var getReservationById = /*#__PURE__*/function () {
275
- var _ref5 = _asyncToGenerator(function* (reservationId) {
365
+ var _ref6 = _asyncToGenerator(function* (reservationId) {
276
366
  var reservation = yield _reservationModel.default.findById(reservationId).populate('bikeId', 'name location').populate('userId', 'firstName lastName email');
277
367
  return reservation;
278
368
  });
279
- return function getReservationById(_x9) {
280
- return _ref5.apply(this, arguments);
369
+ return function getReservationById(_x11) {
370
+ return _ref6.apply(this, arguments);
281
371
  };
282
372
  }();
283
373
 
@@ -288,7 +378,7 @@ var getReservationById = /*#__PURE__*/function () {
288
378
  * @throws {Error} - Si la reserva no se encuentra o no se puede cancelar.
289
379
  */
290
380
  var cancelReservationById = /*#__PURE__*/function () {
291
- var _ref6 = _asyncToGenerator(function* (reservationId) {
381
+ var _ref7 = _asyncToGenerator(function* (reservationId) {
292
382
  var reservation = yield _reservationModel.default.findById(reservationId);
293
383
  if (!reservation) {
294
384
  throw new Error('Reserva no encontrada.');
@@ -304,8 +394,8 @@ var cancelReservationById = /*#__PURE__*/function () {
304
394
  deletedReservation: reservation
305
395
  };
306
396
  });
307
- return function cancelReservationById(_x10) {
308
- return _ref6.apply(this, arguments);
397
+ return function cancelReservationById(_x12) {
398
+ return _ref7.apply(this, arguments);
309
399
  };
310
400
  }();
311
401
 
@@ -316,7 +406,7 @@ var cancelReservationById = /*#__PURE__*/function () {
316
406
  * @throws {Error} - Si no se proporciona el ID de usuario.
317
407
  */
318
408
  var getReservationsByUserId = /*#__PURE__*/function () {
319
- var _ref7 = _asyncToGenerator(function* (userId) {
409
+ var _ref8 = _asyncToGenerator(function* (userId) {
320
410
  if (!userId) {
321
411
  throw new Error('El ID de usuario es requerido para obtener las reservaciones.');
322
412
  }
@@ -329,8 +419,8 @@ var getReservationsByUserId = /*#__PURE__*/function () {
329
419
 
330
420
  return reservations;
331
421
  });
332
- return function getReservationsByUserId(_x11) {
333
- return _ref7.apply(this, arguments);
422
+ return function getReservationsByUserId(_x13) {
423
+ return _ref8.apply(this, arguments);
334
424
  };
335
425
  }();
336
426
  var _default = exports.default = {
@@ -341,5 +431,8 @@ var _default = exports.default = {
341
431
  cancelReservationById,
342
432
  isBikeReserved,
343
433
  // Keep exporting isBikeReserved if used elsewhere, otherwise could be removed if only internal
344
- getReservationsByUserId
434
+ getReservationsByUserId,
435
+ isTimeSlotAvailableForReservation,
436
+ // Export for potential use in API layer
437
+ extractTimeSlotFromTimestamp // Export for potential use in API layer
345
438
  };
@@ -0,0 +1,288 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.updateScheduleException = exports.toggleExceptionStatus = exports.getExceptionsForDateRange = exports.getExceptionsForDate = exports.getAllScheduleExceptions = exports.deleteScheduleException = exports.default = exports.createScheduleException = void 0;
7
+ var _scheduleExceptionModel = _interopRequireDefault(require("../models/scheduleException.model.js"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
10
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
11
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
12
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
13
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
14
+ function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
15
+ function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
16
+ /**
17
+ * Crear una excepción de horario
18
+ * @param {Object} exceptionData - Datos de la excepción
19
+ * @returns {Object} Excepción creada
20
+ */
21
+ var createScheduleException = exports.createScheduleException = /*#__PURE__*/function () {
22
+ var _ref = _asyncToGenerator(function* (exceptionData) {
23
+ try {
24
+ var {
25
+ location,
26
+ exceptionDate,
27
+ exceptionType,
28
+ customTimeSlots,
29
+ blockedTimeSlot,
30
+ reason,
31
+ createdBy
32
+ } = exceptionData;
33
+
34
+ // Validar ubicación
35
+ var validLocations = ['C.C Las Virtudes', 'Sambil Paraguaná'];
36
+ if (!validLocations.includes(location)) {
37
+ throw new Error("Ubicaci\xF3n inv\xE1lida. Debe ser: ".concat(validLocations.join(' o ')));
38
+ }
39
+
40
+ // Validar tipo de excepción
41
+ var validTypes = ['CLOSED', 'CUSTOM_HOURS', 'SLOT_BLOCKED'];
42
+ if (!validTypes.includes(exceptionType)) {
43
+ throw new Error("Tipo de excepci\xF3n inv\xE1lido. Debe ser: ".concat(validTypes.join(', ')));
44
+ }
45
+
46
+ // Validaciones específicas por tipo
47
+ if (exceptionType === 'CUSTOM_HOURS' && (!customTimeSlots || customTimeSlots.length === 0)) {
48
+ throw new Error('CUSTOM_HOURS requiere customTimeSlots');
49
+ }
50
+ if (exceptionType === 'SLOT_BLOCKED' && !blockedTimeSlot) {
51
+ throw new Error('SLOT_BLOCKED requiere blockedTimeSlot');
52
+ }
53
+
54
+ // Validar formato de timeSlots si existen
55
+ var timeRegex = /^(1[0-2]|[1-9])(:([0-5][0-9]))?(am|pm)$/i;
56
+ if (customTimeSlots && customTimeSlots.length > 0) {
57
+ for (var slot of customTimeSlots) {
58
+ if (!timeRegex.test(slot.time)) {
59
+ throw new Error("Formato de hora inv\xE1lido: ".concat(slot.time));
60
+ }
61
+ }
62
+ }
63
+ if (blockedTimeSlot && !timeRegex.test(blockedTimeSlot)) {
64
+ throw new Error("Formato de hora inv\xE1lido: ".concat(blockedTimeSlot));
65
+ }
66
+
67
+ // Normalizar fecha a medianoche UTC
68
+ var normalizedDate = new Date(exceptionDate);
69
+ normalizedDate.setHours(0, 0, 0, 0);
70
+ var exception = new _scheduleExceptionModel.default({
71
+ location,
72
+ exceptionDate: normalizedDate,
73
+ exceptionType,
74
+ customTimeSlots: customTimeSlots || [],
75
+ blockedTimeSlot: blockedTimeSlot || null,
76
+ reason: reason || '',
77
+ isActive: true,
78
+ createdBy
79
+ });
80
+ yield exception.save();
81
+ return exception;
82
+ } catch (error) {
83
+ throw new Error("Error al crear excepci\xF3n: ".concat(error.message));
84
+ }
85
+ });
86
+ return function createScheduleException(_x) {
87
+ return _ref.apply(this, arguments);
88
+ };
89
+ }();
90
+
91
+ /**
92
+ * Obtener excepciones para una fecha específica
93
+ * @param {String} location - Ubicación
94
+ * @param {Date} date - Fecha a consultar
95
+ * @returns {Array} Excepciones activas para esa fecha
96
+ */
97
+ var getExceptionsForDate = exports.getExceptionsForDate = /*#__PURE__*/function () {
98
+ var _ref2 = _asyncToGenerator(function* (location, date) {
99
+ try {
100
+ // Normalizar fecha a medianoche
101
+ var normalizedDate = new Date(date);
102
+ normalizedDate.setHours(0, 0, 0, 0);
103
+ var endOfDay = new Date(normalizedDate);
104
+ endOfDay.setHours(23, 59, 59, 999);
105
+ var exceptions = yield _scheduleExceptionModel.default.find({
106
+ location,
107
+ exceptionDate: {
108
+ $gte: normalizedDate,
109
+ $lte: endOfDay
110
+ },
111
+ isActive: true
112
+ }).populate('createdBy', 'firstName lastName email');
113
+ return exceptions;
114
+ } catch (error) {
115
+ throw new Error("Error al obtener excepciones para fecha: ".concat(error.message));
116
+ }
117
+ });
118
+ return function getExceptionsForDate(_x2, _x3) {
119
+ return _ref2.apply(this, arguments);
120
+ };
121
+ }();
122
+
123
+ /**
124
+ * Obtener excepciones para un rango de fechas
125
+ * @param {String} location - Ubicación
126
+ * @param {Date} startDate - Fecha inicial
127
+ * @param {Date} endDate - Fecha final
128
+ * @returns {Array} Excepciones en el rango
129
+ */
130
+ var getExceptionsForDateRange = exports.getExceptionsForDateRange = /*#__PURE__*/function () {
131
+ var _ref3 = _asyncToGenerator(function* (location, startDate, endDate) {
132
+ try {
133
+ // Normalizar fechas
134
+ var normalizedStart = new Date(startDate);
135
+ normalizedStart.setHours(0, 0, 0, 0);
136
+ var normalizedEnd = new Date(endDate);
137
+ normalizedEnd.setHours(23, 59, 59, 999);
138
+ var exceptions = yield _scheduleExceptionModel.default.find({
139
+ location,
140
+ exceptionDate: {
141
+ $gte: normalizedStart,
142
+ $lte: normalizedEnd
143
+ },
144
+ isActive: true
145
+ }).populate('createdBy', 'firstName lastName email').sort({
146
+ exceptionDate: 1
147
+ });
148
+ return exceptions;
149
+ } catch (error) {
150
+ throw new Error("Error al obtener excepciones para rango: ".concat(error.message));
151
+ }
152
+ });
153
+ return function getExceptionsForDateRange(_x4, _x5, _x6) {
154
+ return _ref3.apply(this, arguments);
155
+ };
156
+ }();
157
+
158
+ /**
159
+ * Eliminar una excepción
160
+ * @param {String} exceptionId - ID de la excepción
161
+ * @returns {Object} Excepción eliminada
162
+ */
163
+ var deleteScheduleException = exports.deleteScheduleException = /*#__PURE__*/function () {
164
+ var _ref4 = _asyncToGenerator(function* (exceptionId) {
165
+ try {
166
+ var exception = yield _scheduleExceptionModel.default.findByIdAndDelete(exceptionId);
167
+ if (!exception) {
168
+ throw new Error('Excepción no encontrada');
169
+ }
170
+ return exception;
171
+ } catch (error) {
172
+ throw new Error("Error al eliminar excepci\xF3n: ".concat(error.message));
173
+ }
174
+ });
175
+ return function deleteScheduleException(_x7) {
176
+ return _ref4.apply(this, arguments);
177
+ };
178
+ }();
179
+
180
+ /**
181
+ * Actualizar una excepción
182
+ * @param {String} exceptionId - ID de la excepción
183
+ * @param {Object} updateData - Datos a actualizar
184
+ * @returns {Object} Excepción actualizada
185
+ */
186
+ var updateScheduleException = exports.updateScheduleException = /*#__PURE__*/function () {
187
+ var _ref5 = _asyncToGenerator(function* (exceptionId, updateData) {
188
+ try {
189
+ // Validar formato de timeSlots si se están actualizando
190
+ var timeRegex = /^(1[0-2]|[1-9])(:([0-5][0-9]))?(am|pm)$/i;
191
+ if (updateData.customTimeSlots && updateData.customTimeSlots.length > 0) {
192
+ for (var slot of updateData.customTimeSlots) {
193
+ if (!timeRegex.test(slot.time)) {
194
+ throw new Error("Formato de hora inv\xE1lido: ".concat(slot.time));
195
+ }
196
+ }
197
+ }
198
+ if (updateData.blockedTimeSlot && !timeRegex.test(updateData.blockedTimeSlot)) {
199
+ throw new Error("Formato de hora inv\xE1lido: ".concat(updateData.blockedTimeSlot));
200
+ }
201
+ var exception = yield _scheduleExceptionModel.default.findByIdAndUpdate(exceptionId, _objectSpread(_objectSpread({}, updateData), {}, {
202
+ updatedAt: new Date()
203
+ }), {
204
+ new: true,
205
+ runValidators: true
206
+ }).populate('createdBy', 'firstName lastName email');
207
+ if (!exception) {
208
+ throw new Error('Excepción no encontrada');
209
+ }
210
+ return exception;
211
+ } catch (error) {
212
+ throw new Error("Error al actualizar excepci\xF3n: ".concat(error.message));
213
+ }
214
+ });
215
+ return function updateScheduleException(_x8, _x9) {
216
+ return _ref5.apply(this, arguments);
217
+ };
218
+ }();
219
+
220
+ /**
221
+ * Obtener todas las excepciones con filtros opcionales
222
+ * @param {Object} filters - Filtros (location, isActive, etc.)
223
+ * @returns {Array} Excepciones
224
+ */
225
+ var getAllScheduleExceptions = exports.getAllScheduleExceptions = /*#__PURE__*/function () {
226
+ var _ref6 = _asyncToGenerator(function* () {
227
+ var filters = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
228
+ try {
229
+ var query = {};
230
+ if (filters.location) {
231
+ query.location = filters.location;
232
+ }
233
+ if (filters.isActive !== undefined) {
234
+ query.isActive = filters.isActive;
235
+ }
236
+ if (filters.exceptionType) {
237
+ query.exceptionType = filters.exceptionType;
238
+ }
239
+ var exceptions = yield _scheduleExceptionModel.default.find(query).populate('createdBy', 'firstName lastName email').sort({
240
+ exceptionDate: -1
241
+ });
242
+ return exceptions;
243
+ } catch (error) {
244
+ throw new Error("Error al obtener excepciones: ".concat(error.message));
245
+ }
246
+ });
247
+ return function getAllScheduleExceptions() {
248
+ return _ref6.apply(this, arguments);
249
+ };
250
+ }();
251
+
252
+ /**
253
+ * Activar/desactivar una excepción
254
+ * @param {String} exceptionId - ID de la excepción
255
+ * @param {Boolean} isActive - Estado
256
+ * @returns {Object} Excepción actualizada
257
+ */
258
+ var toggleExceptionStatus = exports.toggleExceptionStatus = /*#__PURE__*/function () {
259
+ var _ref7 = _asyncToGenerator(function* (exceptionId, isActive) {
260
+ try {
261
+ var exception = yield _scheduleExceptionModel.default.findByIdAndUpdate(exceptionId, {
262
+ isActive,
263
+ updatedAt: new Date()
264
+ }, {
265
+ new: true,
266
+ runValidators: true
267
+ }).populate('createdBy', 'firstName lastName email');
268
+ if (!exception) {
269
+ throw new Error('Excepción no encontrada');
270
+ }
271
+ return exception;
272
+ } catch (error) {
273
+ throw new Error("Error al cambiar estado de excepci\xF3n: ".concat(error.message));
274
+ }
275
+ });
276
+ return function toggleExceptionStatus(_x10, _x11) {
277
+ return _ref7.apply(this, arguments);
278
+ };
279
+ }();
280
+ var _default = exports.default = {
281
+ createScheduleException,
282
+ getExceptionsForDate,
283
+ getExceptionsForDateRange,
284
+ deleteScheduleException,
285
+ updateScheduleException,
286
+ getAllScheduleExceptions,
287
+ toggleExceptionStatus
288
+ };