goldstars-services 1.0.70 → 1.0.73

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,75 @@ 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
+ var timeSlot = extractTimeSlotFromTimestamp(timestamp);
51
+
52
+ // 1. Verificar excepciones (tienen prioridad)
53
+ var exceptions = yield _scheduleExceptionService.default.getExceptionsForDate(location, timestamp);
54
+ if (exceptions.length > 0) {
55
+ for (var exc of exceptions) {
56
+ // Si está cerrado, no disponible
57
+ if (exc.exceptionType === 'CLOSED') {
58
+ return false;
59
+ }
60
+
61
+ // Si el slot específico está bloqueado
62
+ if (exc.exceptionType === 'SLOT_BLOCKED' && exc.blockedTimeSlot === timeSlot) {
63
+ return false;
64
+ }
65
+
66
+ // Si hay horarios custom, usar esos
67
+ if (exc.exceptionType === 'CUSTOM_HOURS') {
68
+ return exc.customTimeSlots.some(s => s.time === timeSlot && s.isActive);
69
+ }
70
+ }
71
+ }
72
+
73
+ // 2. Si no hay excepciones, usar template semanal
74
+ var weeklySchedule = yield _weeklyScheduleTemplateService.default.getWeeklyScheduleForDay(location, dayOfWeek);
75
+ if (!weeklySchedule) {
76
+ return false; // No hay horarios configurados para este día
77
+ }
78
+
79
+ // Verificar si el time slot está en el template y está activo
80
+ return weeklySchedule.timeSlots.some(s => s.time === timeSlot && s.isActive);
81
+ } catch (error) {
82
+ console.error('Error verificando disponibilidad de horario:', error);
83
+ return false; // En caso de error, no permitir la reserva
84
+ }
85
+ });
86
+ return function isTimeSlotAvailableForReservation(_x, _x2) {
87
+ return _ref.apply(this, arguments);
88
+ };
89
+ }();
90
+
19
91
  /**
20
92
  * Checks if a bike is already reserved for a specific timestamp.
21
93
  * @param {string} bikeId - The ID of the bike.
@@ -23,7 +95,7 @@ function _asyncToGenerator(n) { return function () { var t = this, e = arguments
23
95
  * @returns {Promise<boolean>} - True if the bike is already reserved, false otherwise.
24
96
  */
25
97
  var isBikeReserved = /*#__PURE__*/function () {
26
- var _ref = _asyncToGenerator(function* (bikeId, timestamp) {
98
+ var _ref2 = _asyncToGenerator(function* (bikeId, timestamp) {
27
99
  var searchTimestamp = new Date(timestamp);
28
100
  if (isNaN(searchTimestamp.getTime())) {
29
101
  throw new Error('Timestamp inválido proporcionado a isBikeReserved.');
@@ -36,8 +108,8 @@ var isBikeReserved = /*#__PURE__*/function () {
36
108
  });
37
109
  return !!existingReservation;
38
110
  });
39
- return function isBikeReserved(_x, _x2) {
40
- return _ref.apply(this, arguments);
111
+ return function isBikeReserved(_x3, _x4) {
112
+ return _ref2.apply(this, arguments);
41
113
  };
42
114
  }();
43
115
 
@@ -52,7 +124,7 @@ var isBikeReserved = /*#__PURE__*/function () {
52
124
  * @throws {Error} - If bike not found, is instructor bike, timestamp invalid, or already reserved.
53
125
  */
54
126
  var createReservation = /*#__PURE__*/function () {
55
- var _ref2 = _asyncToGenerator(function* (reservationData) {
127
+ var _ref3 = _asyncToGenerator(function* (reservationData) {
56
128
  var {
57
129
  userId,
58
130
  bikeId,
@@ -68,7 +140,14 @@ var createReservation = /*#__PURE__*/function () {
68
140
 
69
141
  // 1. Validaciones por usuario solo aplican cuando hay usuario asociado
70
142
  if (userId) {
71
- // 1.a Check if user already has a reservation for this EXACT timestamp
143
+ // 1.a Verificar suspensión de usuario
144
+ var suspensionCheck = yield _userSuspensionService.default.checkUserSuspension(userId, 'bikes');
145
+ if (suspensionCheck.isSuspended) {
146
+ var untilMessage = suspensionCheck.suspendedUntil ? " hasta ".concat(new Date(suspensionCheck.suspendedUntil).toLocaleDateString('es-VE')) : ' indefinidamente';
147
+ throw new Error("Tu cuenta est\xE1 suspendida".concat(untilMessage, ". Raz\xF3n: ").concat(suspensionCheck.reason));
148
+ }
149
+
150
+ // 1.b Check if user already has a reservation for this EXACT timestamp
72
151
  var existingReservationSameSlot = yield _reservationModel.default.findOne({
73
152
  userId,
74
153
  timestamp: reservationTimestamp
@@ -77,7 +156,7 @@ var createReservation = /*#__PURE__*/function () {
77
156
  throw new Error('Ya tienes una reserva agendada para esta fecha y hora.');
78
157
  }
79
158
 
80
- // 1.b Check if user already has an UPCOMING reservation
159
+ // 1.c Check if user already has an UPCOMING reservation
81
160
  var now = new Date();
82
161
  var existingUpcomingReservation = yield _reservationModel.default.findOne({
83
162
  userId,
@@ -86,13 +165,16 @@ var createReservation = /*#__PURE__*/function () {
86
165
  } // Find reservations where the timestamp is now or in the future
87
166
  });
88
167
  if (existingUpcomingReservation) {
89
- // Optional: Provide more details about the existing reservation if needed
90
- // const existingTime = existingUpcomingReservation.timestamp.toLocaleString('es-VE');
91
- // throw new Error(`Ya tienes una reserva activa para ${existingTime}. Debes esperar a que pase para agendar otra.`);
92
168
  throw new Error('Ya tienes una reserva activa. Debes esperar a que pase para agendar otra.');
93
169
  }
94
170
  }
95
171
 
172
+ // 2. Verificar disponibilidad de horario (templates y excepciones)
173
+ var isSlotAvailable = yield isTimeSlotAvailableForReservation(location, reservationTimestamp);
174
+ if (!isSlotAvailable) {
175
+ throw new Error('Este horario no está disponible para reservas en esta ubicación.');
176
+ }
177
+
96
178
  // --- END NEW VALIDATIONS ---
97
179
 
98
180
  // 1. Validate Bike
@@ -124,8 +206,8 @@ var createReservation = /*#__PURE__*/function () {
124
206
  yield newReservation.save();
125
207
  return newReservation;
126
208
  });
127
- return function createReservation(_x3) {
128
- return _ref2.apply(this, arguments);
209
+ return function createReservation(_x5) {
210
+ return _ref3.apply(this, arguments);
129
211
  };
130
212
  }();
131
213
 
@@ -137,13 +219,23 @@ var createReservation = /*#__PURE__*/function () {
137
219
  * @returns {Promise<Array<object>>} - An array of bike objects, each with an added 'reservationStatus' field.
138
220
  */
139
221
  var getBikeAvailabilityForSlot = /*#__PURE__*/function () {
140
- var _ref3 = _asyncToGenerator(function* (location, timestamp) {
222
+ var _ref4 = _asyncToGenerator(function* (location, timestamp) {
141
223
  var includeInstructor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
142
224
  var checkTimestamp = new Date(timestamp);
143
225
  if (isNaN(checkTimestamp.getTime())) {
144
226
  throw new Error('Timestamp inválido proporcionado para obtener disponibilidad.');
145
227
  }
146
228
 
229
+ // ===== NUEVA VALIDACIÓN: Verificar si el horario está disponible en el nuevo sistema =====
230
+ var isSlotAvailable = yield isTimeSlotAvailableForReservation(location, checkTimestamp);
231
+ if (!isSlotAvailable) {
232
+ // Si el horario no está configurado en WeeklyScheduleTemplate o ScheduleException,
233
+ // retornar array vacío (no hay horarios disponibles)
234
+ console.log("Horario no disponible para ".concat(location, " en ").concat(checkTimestamp.toISOString()));
235
+ return [];
236
+ }
237
+ // ===== FIN NUEVA VALIDACIÓN =====
238
+
147
239
  // 1. Find all bikes for the given location
148
240
  var bikesInLocation = yield _bikeModel.default.find({
149
241
  location
@@ -224,8 +316,8 @@ var getBikeAvailabilityForSlot = /*#__PURE__*/function () {
224
316
  });
225
317
  return bikesWithStatus;
226
318
  });
227
- return function getBikeAvailabilityForSlot(_x4, _x5) {
228
- return _ref3.apply(this, arguments);
319
+ return function getBikeAvailabilityForSlot(_x6, _x7) {
320
+ return _ref4.apply(this, arguments);
229
321
  };
230
322
  }();
231
323
 
@@ -244,7 +336,7 @@ var getBikeAvailabilityForSlot = /*#__PURE__*/function () {
244
336
  * @throws {Error} - If reservation not found or user is not authorized.
245
337
  */
246
338
  var cancelReservation = /*#__PURE__*/function () {
247
- var _ref4 = _asyncToGenerator(function* (reservationId, userId, userRole) {
339
+ var _ref5 = _asyncToGenerator(function* (reservationId, userId, userRole) {
248
340
  var reservation = yield _reservationModel.default.findById(reservationId);
249
341
  if (!reservation) {
250
342
  throw new Error('Reserva no encontrada.');
@@ -264,8 +356,8 @@ var cancelReservation = /*#__PURE__*/function () {
264
356
  message: 'Reserva cancelada exitosamente.'
265
357
  };
266
358
  });
267
- return function cancelReservation(_x6, _x7, _x8) {
268
- return _ref4.apply(this, arguments);
359
+ return function cancelReservation(_x8, _x9, _x10) {
360
+ return _ref5.apply(this, arguments);
269
361
  };
270
362
  }();
271
363
 
@@ -275,12 +367,12 @@ var cancelReservation = /*#__PURE__*/function () {
275
367
  * @returns {Promise<object|null>} - El documento de la reservación o null si no existe.
276
368
  */
277
369
  var getReservationById = /*#__PURE__*/function () {
278
- var _ref5 = _asyncToGenerator(function* (reservationId) {
370
+ var _ref6 = _asyncToGenerator(function* (reservationId) {
279
371
  var reservation = yield _reservationModel.default.findById(reservationId).populate('bikeId', 'name location').populate('userId', 'firstName lastName email');
280
372
  return reservation;
281
373
  });
282
- return function getReservationById(_x9) {
283
- return _ref5.apply(this, arguments);
374
+ return function getReservationById(_x11) {
375
+ return _ref6.apply(this, arguments);
284
376
  };
285
377
  }();
286
378
 
@@ -291,7 +383,7 @@ var getReservationById = /*#__PURE__*/function () {
291
383
  * @throws {Error} - Si la reserva no se encuentra o no se puede cancelar.
292
384
  */
293
385
  var cancelReservationById = /*#__PURE__*/function () {
294
- var _ref6 = _asyncToGenerator(function* (reservationId) {
386
+ var _ref7 = _asyncToGenerator(function* (reservationId) {
295
387
  var reservation = yield _reservationModel.default.findById(reservationId);
296
388
  if (!reservation) {
297
389
  throw new Error('Reserva no encontrada.');
@@ -307,8 +399,8 @@ var cancelReservationById = /*#__PURE__*/function () {
307
399
  deletedReservation: reservation
308
400
  };
309
401
  });
310
- return function cancelReservationById(_x10) {
311
- return _ref6.apply(this, arguments);
402
+ return function cancelReservationById(_x12) {
403
+ return _ref7.apply(this, arguments);
312
404
  };
313
405
  }();
314
406
 
@@ -319,7 +411,7 @@ var cancelReservationById = /*#__PURE__*/function () {
319
411
  * @throws {Error} - Si no se proporciona el ID de usuario.
320
412
  */
321
413
  var getReservationsByUserId = /*#__PURE__*/function () {
322
- var _ref7 = _asyncToGenerator(function* (userId) {
414
+ var _ref8 = _asyncToGenerator(function* (userId) {
323
415
  if (!userId) {
324
416
  throw new Error('El ID de usuario es requerido para obtener las reservaciones.');
325
417
  }
@@ -332,8 +424,8 @@ var getReservationsByUserId = /*#__PURE__*/function () {
332
424
 
333
425
  return reservations;
334
426
  });
335
- return function getReservationsByUserId(_x11) {
336
- return _ref7.apply(this, arguments);
427
+ return function getReservationsByUserId(_x13) {
428
+ return _ref8.apply(this, arguments);
337
429
  };
338
430
  }();
339
431
  var _default = exports.default = {
@@ -344,5 +436,8 @@ var _default = exports.default = {
344
436
  cancelReservationById,
345
437
  isBikeReserved,
346
438
  // Keep exporting isBikeReserved if used elsewhere, otherwise could be removed if only internal
347
- getReservationsByUserId
439
+ getReservationsByUserId,
440
+ isTimeSlotAvailableForReservation,
441
+ // Export for potential use in API layer
442
+ extractTimeSlotFromTimestamp // Export for potential use in API layer
348
443
  };
@@ -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
+ };