vr-commons 1.0.148 → 1.0.150

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.
@@ -82,4 +82,21 @@ export declare const stockUtil: {
82
82
  error?: string | undefined;
83
83
  devices?: Device[] | undefined;
84
84
  };
85
+ /**
86
+ * Check if pair exists and is not soft deleted
87
+ */
88
+ checkPairExists(pairId: string, productId: string, transaction?: any): Promise<{
89
+ exists: boolean;
90
+ devices?: Device[];
91
+ missing?: string[];
92
+ }>;
93
+ /**
94
+ * Check if pair IDs exist and are not soft deleted (for bulk operations)
95
+ */
96
+ checkMultiplePairsExist(pairIds: string[], productId: string, transaction?: any): Promise<{
97
+ valid: boolean;
98
+ existingPairs: string[];
99
+ missingPairs: string[];
100
+ incompletePairs: string[];
101
+ }>;
85
102
  };
@@ -251,6 +251,7 @@ exports.stockUtil = {
251
251
  return await vr_models_1.Device.findAll({
252
252
  where: {
253
253
  pairId: { [sequelize_1.Op.in]: pairIds },
254
+ deletedAt: null, // ✅ Exclude soft deleted
254
255
  },
255
256
  include: [{ model: vr_models_1.DevicePaymentPlan, as: "paymentPlan" }],
256
257
  transaction,
@@ -288,4 +289,60 @@ exports.stockUtil = {
288
289
  }
289
290
  return { valid: true };
290
291
  },
292
+ /**
293
+ * Check if pair exists and is not soft deleted
294
+ */
295
+ async checkPairExists(pairId, productId, transaction) {
296
+ const devices = await vr_models_1.Device.findAll({
297
+ where: {
298
+ pairId: pairId,
299
+ productId: productId,
300
+ deletedAt: null, // ✅ Exclude soft deleted
301
+ },
302
+ transaction,
303
+ });
304
+ if (devices.length === 0) {
305
+ return { exists: false, missing: ["RIDER", "PASSENGER"] };
306
+ }
307
+ const hasRider = devices.some((d) => d.dedicatedUser === "RIDER");
308
+ const hasPassenger = devices.some((d) => d.dedicatedUser === "PASSENGER");
309
+ const missing = [];
310
+ if (!hasRider)
311
+ missing.push("RIDER");
312
+ if (!hasPassenger)
313
+ missing.push("PASSENGER");
314
+ return {
315
+ exists: devices.length === 2 && hasRider && hasPassenger,
316
+ devices: devices,
317
+ missing: missing,
318
+ };
319
+ },
320
+ /**
321
+ * Check if pair IDs exist and are not soft deleted (for bulk operations)
322
+ */
323
+ async checkMultiplePairsExist(pairIds, productId, transaction) {
324
+ const existingPairs = [];
325
+ const missingPairs = [];
326
+ const incompletePairs = [];
327
+ for (const pairId of pairIds) {
328
+ const result = await this.checkPairExists(pairId, productId, transaction);
329
+ if (!result.exists) {
330
+ if (result.devices && result.devices.length === 1) {
331
+ incompletePairs.push(pairId);
332
+ }
333
+ else {
334
+ missingPairs.push(pairId);
335
+ }
336
+ }
337
+ else {
338
+ existingPairs.push(pairId);
339
+ }
340
+ }
341
+ return {
342
+ valid: existingPairs.length === pairIds.length,
343
+ existingPairs,
344
+ missingPairs,
345
+ incompletePairs,
346
+ };
347
+ },
291
348
  };
@@ -43,48 +43,48 @@ export declare const listPlansSchema: z.ZodObject<{
43
43
  sortBy: z.ZodOptional<z.ZodEnum<["createdAt", "updatedAt", "nextInstallmentDueAt", "paidAmount", "outstandingAmount"]>>;
44
44
  sortOrder: z.ZodOptional<z.ZodEnum<["ASC", "DESC"]>>;
45
45
  }, "strip", z.ZodTypeAny, {
46
- limit: number;
47
46
  page: number;
48
- search?: string | undefined;
47
+ limit: number;
49
48
  status?: "ACTIVE" | "PENDING" | "COMPLETED" | "DEFAULTED" | "CANCELLED" | undefined;
49
+ search?: string | undefined;
50
+ sortBy?: "createdAt" | "updatedAt" | "paidAmount" | "outstandingAmount" | "nextInstallmentDueAt" | undefined;
51
+ sortOrder?: "ASC" | "DESC" | undefined;
50
52
  userId?: string | undefined;
51
53
  isOverdue?: "true" | "false" | undefined;
52
- sortBy?: "createdAt" | "updatedAt" | "paidAmount" | "outstandingAmount" | "nextInstallmentDueAt" | undefined;
53
- sortOrder?: "DESC" | "ASC" | undefined;
54
54
  deviceId?: string | undefined;
55
55
  }, {
56
+ status?: "ACTIVE" | "PENDING" | "COMPLETED" | "DEFAULTED" | "CANCELLED" | undefined;
57
+ page?: string | undefined;
56
58
  limit?: string | undefined;
57
59
  search?: string | undefined;
58
- status?: "ACTIVE" | "PENDING" | "COMPLETED" | "DEFAULTED" | "CANCELLED" | undefined;
60
+ sortBy?: "createdAt" | "updatedAt" | "paidAmount" | "outstandingAmount" | "nextInstallmentDueAt" | undefined;
61
+ sortOrder?: "ASC" | "DESC" | undefined;
59
62
  userId?: string | undefined;
60
63
  isOverdue?: "true" | "false" | undefined;
61
- page?: string | undefined;
62
- sortBy?: "createdAt" | "updatedAt" | "paidAmount" | "outstandingAmount" | "nextInstallmentDueAt" | undefined;
63
- sortOrder?: "DESC" | "ASC" | undefined;
64
64
  deviceId?: string | undefined;
65
65
  }>;
66
66
  }, "strip", z.ZodTypeAny, {
67
67
  query: {
68
- limit: number;
69
68
  page: number;
70
- search?: string | undefined;
69
+ limit: number;
71
70
  status?: "ACTIVE" | "PENDING" | "COMPLETED" | "DEFAULTED" | "CANCELLED" | undefined;
71
+ search?: string | undefined;
72
+ sortBy?: "createdAt" | "updatedAt" | "paidAmount" | "outstandingAmount" | "nextInstallmentDueAt" | undefined;
73
+ sortOrder?: "ASC" | "DESC" | undefined;
72
74
  userId?: string | undefined;
73
75
  isOverdue?: "true" | "false" | undefined;
74
- sortBy?: "createdAt" | "updatedAt" | "paidAmount" | "outstandingAmount" | "nextInstallmentDueAt" | undefined;
75
- sortOrder?: "DESC" | "ASC" | undefined;
76
76
  deviceId?: string | undefined;
77
77
  };
78
78
  }, {
79
79
  query: {
80
+ status?: "ACTIVE" | "PENDING" | "COMPLETED" | "DEFAULTED" | "CANCELLED" | undefined;
81
+ page?: string | undefined;
80
82
  limit?: string | undefined;
81
83
  search?: string | undefined;
82
- status?: "ACTIVE" | "PENDING" | "COMPLETED" | "DEFAULTED" | "CANCELLED" | undefined;
84
+ sortBy?: "createdAt" | "updatedAt" | "paidAmount" | "outstandingAmount" | "nextInstallmentDueAt" | undefined;
85
+ sortOrder?: "ASC" | "DESC" | undefined;
83
86
  userId?: string | undefined;
84
87
  isOverdue?: "true" | "false" | undefined;
85
- page?: string | undefined;
86
- sortBy?: "createdAt" | "updatedAt" | "paidAmount" | "outstandingAmount" | "nextInstallmentDueAt" | undefined;
87
- sortOrder?: "DESC" | "ASC" | undefined;
88
88
  deviceId?: string | undefined;
89
89
  };
90
90
  }>;
@@ -192,25 +192,25 @@ export declare const limitedUpdateSchema: z.ZodObject<{
192
192
  pricingId?: string | undefined;
193
193
  }>;
194
194
  }, "strip", z.ZodTypeAny, {
195
+ params: {
196
+ id: string;
197
+ };
195
198
  body: {
196
199
  productId?: string | undefined;
197
200
  userId?: string | undefined;
198
201
  deviceIds?: string[] | undefined;
199
202
  pricingId?: string | undefined;
200
203
  };
204
+ }, {
201
205
  params: {
202
206
  id: string;
203
207
  };
204
- }, {
205
208
  body: {
206
209
  productId?: string | undefined;
207
210
  userId?: string | undefined;
208
211
  deviceIds?: string[] | undefined;
209
212
  pricingId?: string | undefined;
210
213
  };
211
- params: {
212
- id: string;
213
- };
214
214
  }>;
215
215
  export declare const recordPaymentSchema: z.ZodObject<{
216
216
  params: z.ZodObject<{
@@ -246,6 +246,9 @@ export declare const recordPaymentSchema: z.ZodObject<{
246
246
  notes?: string | undefined;
247
247
  }>;
248
248
  }, "strip", z.ZodTypeAny, {
249
+ params: {
250
+ id: string;
251
+ };
249
252
  body: {
250
253
  amount: number;
251
254
  provider: "AIRTEL_MONEY" | "CASH" | "MOMO_PAY";
@@ -255,10 +258,10 @@ export declare const recordPaymentSchema: z.ZodObject<{
255
258
  customerName?: string | undefined;
256
259
  notes?: string | undefined;
257
260
  };
261
+ }, {
258
262
  params: {
259
263
  id: string;
260
264
  };
261
- }, {
262
265
  body: {
263
266
  amount: number;
264
267
  metadata?: Record<string, any> | undefined;
@@ -268,9 +271,6 @@ export declare const recordPaymentSchema: z.ZodObject<{
268
271
  customerName?: string | undefined;
269
272
  notes?: string | undefined;
270
273
  };
271
- params: {
272
- id: string;
273
- };
274
274
  }>;
275
275
  export declare const deletePlanSchema: z.ZodObject<{
276
276
  params: z.ZodObject<{
@@ -59,164 +59,218 @@ export declare const getDevicesSchema: z.ZodObject<{
59
59
  sortBy: z.ZodOptional<z.ZodEnum<["serialNumber", "status", "createdAt", "updatedAt"]>>;
60
60
  sortOrder: z.ZodOptional<z.ZodEnum<["ASC", "DESC"]>>;
61
61
  }, "strip", z.ZodTypeAny, {
62
- limit?: number | undefined;
63
- search?: string | undefined;
64
62
  productId?: string | undefined;
65
63
  status?: "locked" | "unlocked" | "disabled" | undefined;
64
+ page?: number | undefined;
65
+ limit?: number | undefined;
66
+ dedicatedUser?: "PASSENGER" | "RIDER" | "N/A" | undefined;
66
67
  isPermanentlyUnlocked?: "true" | "false" | undefined;
67
- dedicatedUser?: "RIDER" | "PASSENGER" | "N/A" | undefined;
68
68
  isAssigned?: "true" | "false" | undefined;
69
- page?: number | undefined;
70
- sortBy?: "createdAt" | "updatedAt" | "serialNumber" | "status" | undefined;
71
- sortOrder?: "DESC" | "ASC" | undefined;
72
- }, {
73
- limit?: string | undefined;
74
69
  search?: string | undefined;
70
+ sortBy?: "status" | "serialNumber" | "createdAt" | "updatedAt" | undefined;
71
+ sortOrder?: "ASC" | "DESC" | undefined;
72
+ }, {
75
73
  productId?: string | undefined;
76
74
  status?: "locked" | "unlocked" | "disabled" | undefined;
75
+ page?: string | undefined;
76
+ limit?: string | undefined;
77
+ dedicatedUser?: "PASSENGER" | "RIDER" | "N/A" | undefined;
77
78
  isPermanentlyUnlocked?: "true" | "false" | undefined;
78
- dedicatedUser?: "RIDER" | "PASSENGER" | "N/A" | undefined;
79
79
  isAssigned?: "true" | "false" | undefined;
80
- page?: string | undefined;
81
- sortBy?: "createdAt" | "updatedAt" | "serialNumber" | "status" | undefined;
82
- sortOrder?: "DESC" | "ASC" | undefined;
80
+ search?: string | undefined;
81
+ sortBy?: "status" | "serialNumber" | "createdAt" | "updatedAt" | undefined;
82
+ sortOrder?: "ASC" | "DESC" | undefined;
83
83
  }>;
84
84
  }, "strip", z.ZodTypeAny, {
85
85
  query: {
86
- limit?: number | undefined;
87
- search?: string | undefined;
88
86
  productId?: string | undefined;
89
87
  status?: "locked" | "unlocked" | "disabled" | undefined;
88
+ page?: number | undefined;
89
+ limit?: number | undefined;
90
+ dedicatedUser?: "PASSENGER" | "RIDER" | "N/A" | undefined;
90
91
  isPermanentlyUnlocked?: "true" | "false" | undefined;
91
- dedicatedUser?: "RIDER" | "PASSENGER" | "N/A" | undefined;
92
92
  isAssigned?: "true" | "false" | undefined;
93
- page?: number | undefined;
94
- sortBy?: "createdAt" | "updatedAt" | "serialNumber" | "status" | undefined;
95
- sortOrder?: "DESC" | "ASC" | undefined;
93
+ search?: string | undefined;
94
+ sortBy?: "status" | "serialNumber" | "createdAt" | "updatedAt" | undefined;
95
+ sortOrder?: "ASC" | "DESC" | undefined;
96
96
  };
97
97
  }, {
98
98
  query: {
99
- limit?: string | undefined;
100
- search?: string | undefined;
101
99
  productId?: string | undefined;
102
100
  status?: "locked" | "unlocked" | "disabled" | undefined;
101
+ page?: string | undefined;
102
+ limit?: string | undefined;
103
+ dedicatedUser?: "PASSENGER" | "RIDER" | "N/A" | undefined;
103
104
  isPermanentlyUnlocked?: "true" | "false" | undefined;
104
- dedicatedUser?: "RIDER" | "PASSENGER" | "N/A" | undefined;
105
105
  isAssigned?: "true" | "false" | undefined;
106
- page?: string | undefined;
107
- sortBy?: "createdAt" | "updatedAt" | "serialNumber" | "status" | undefined;
108
- sortOrder?: "DESC" | "ASC" | undefined;
106
+ search?: string | undefined;
107
+ sortBy?: "status" | "serialNumber" | "createdAt" | "updatedAt" | undefined;
108
+ sortOrder?: "ASC" | "DESC" | undefined;
109
109
  };
110
110
  }>;
111
- export declare const deleteDeviceSchema: z.ZodObject<{
112
- params: z.ZodObject<{
113
- id: z.ZodString;
111
+ export declare const deleteDevicesByPairsSchema: z.ZodObject<{
112
+ body: z.ZodObject<{
113
+ pairIds: z.ZodArray<z.ZodString, "many">;
114
+ reason: z.ZodOptional<z.ZodString>;
114
115
  }, "strip", z.ZodTypeAny, {
115
- id: string;
116
+ pairIds: string[];
117
+ reason?: string | undefined;
116
118
  }, {
117
- id: string;
119
+ pairIds: string[];
120
+ reason?: string | undefined;
118
121
  }>;
119
122
  }, "strip", z.ZodTypeAny, {
120
- params: {
121
- id: string;
123
+ body: {
124
+ pairIds: string[];
125
+ reason?: string | undefined;
122
126
  };
123
127
  }, {
124
- params: {
125
- id: string;
128
+ body: {
129
+ pairIds: string[];
130
+ reason?: string | undefined;
126
131
  };
127
132
  }>;
128
- export declare const adminLockDeviceSchema: z.ZodObject<{
129
- params: z.ZodObject<{
130
- id: z.ZodString;
133
+ export declare const permanentDeleteDevicesByPairsSchema: z.ZodObject<{
134
+ body: z.ZodObject<{
135
+ pairIds: z.ZodArray<z.ZodString, "many">;
131
136
  }, "strip", z.ZodTypeAny, {
132
- id: string;
137
+ pairIds: string[];
133
138
  }, {
134
- id: string;
139
+ pairIds: string[];
135
140
  }>;
136
- body: z.ZodOptional<z.ZodObject<{
141
+ }, "strip", z.ZodTypeAny, {
142
+ body: {
143
+ pairIds: string[];
144
+ };
145
+ }, {
146
+ body: {
147
+ pairIds: string[];
148
+ };
149
+ }>;
150
+ export declare const lockDevicesSchema: z.ZodObject<{
151
+ body: z.ZodEffects<z.ZodObject<{
137
152
  reason: z.ZodOptional<z.ZodString>;
153
+ pairIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
154
+ serialNumbers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
138
155
  }, "strip", z.ZodTypeAny, {
156
+ pairIds?: string[] | undefined;
157
+ reason?: string | undefined;
158
+ serialNumbers?: string[] | undefined;
159
+ }, {
160
+ pairIds?: string[] | undefined;
161
+ reason?: string | undefined;
162
+ serialNumbers?: string[] | undefined;
163
+ }>, {
164
+ pairIds?: string[] | undefined;
139
165
  reason?: string | undefined;
166
+ serialNumbers?: string[] | undefined;
140
167
  }, {
168
+ pairIds?: string[] | undefined;
141
169
  reason?: string | undefined;
142
- }>>;
170
+ serialNumbers?: string[] | undefined;
171
+ }>;
143
172
  }, "strip", z.ZodTypeAny, {
144
- params: {
145
- id: string;
146
- };
147
- body?: {
173
+ body: {
174
+ pairIds?: string[] | undefined;
148
175
  reason?: string | undefined;
149
- } | undefined;
150
- }, {
151
- params: {
152
- id: string;
176
+ serialNumbers?: string[] | undefined;
153
177
  };
154
- body?: {
178
+ }, {
179
+ body: {
180
+ pairIds?: string[] | undefined;
155
181
  reason?: string | undefined;
156
- } | undefined;
182
+ serialNumbers?: string[] | undefined;
183
+ };
157
184
  }>;
158
- export declare const adminUnlockDeviceSchema: z.ZodObject<{
159
- params: z.ZodObject<{
160
- id: z.ZodString;
185
+ export declare const unlockDevicesSchema: z.ZodObject<{
186
+ body: z.ZodEffects<z.ZodObject<{
187
+ pairIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
188
+ serialNumbers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
161
189
  }, "strip", z.ZodTypeAny, {
162
- id: string;
190
+ pairIds?: string[] | undefined;
191
+ serialNumbers?: string[] | undefined;
163
192
  }, {
164
- id: string;
193
+ pairIds?: string[] | undefined;
194
+ serialNumbers?: string[] | undefined;
195
+ }>, {
196
+ pairIds?: string[] | undefined;
197
+ serialNumbers?: string[] | undefined;
198
+ }, {
199
+ pairIds?: string[] | undefined;
200
+ serialNumbers?: string[] | undefined;
165
201
  }>;
166
202
  }, "strip", z.ZodTypeAny, {
167
- params: {
168
- id: string;
203
+ body: {
204
+ pairIds?: string[] | undefined;
205
+ serialNumbers?: string[] | undefined;
169
206
  };
170
207
  }, {
171
- params: {
172
- id: string;
208
+ body: {
209
+ pairIds?: string[] | undefined;
210
+ serialNumbers?: string[] | undefined;
173
211
  };
174
212
  }>;
175
- export declare const disableDeviceSchema: z.ZodObject<{
176
- params: z.ZodObject<{
177
- id: z.ZodString;
178
- }, "strip", z.ZodTypeAny, {
179
- id: string;
180
- }, {
181
- id: string;
182
- }>;
183
- body: z.ZodObject<{
213
+ export declare const disableDevicesSchema: z.ZodObject<{
214
+ body: z.ZodEffects<z.ZodObject<{
184
215
  reason: z.ZodString;
216
+ pairIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
217
+ serialNumbers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
185
218
  }, "strip", z.ZodTypeAny, {
186
219
  reason: string;
220
+ pairIds?: string[] | undefined;
221
+ serialNumbers?: string[] | undefined;
187
222
  }, {
188
223
  reason: string;
224
+ pairIds?: string[] | undefined;
225
+ serialNumbers?: string[] | undefined;
226
+ }>, {
227
+ reason: string;
228
+ pairIds?: string[] | undefined;
229
+ serialNumbers?: string[] | undefined;
230
+ }, {
231
+ reason: string;
232
+ pairIds?: string[] | undefined;
233
+ serialNumbers?: string[] | undefined;
189
234
  }>;
190
235
  }, "strip", z.ZodTypeAny, {
191
236
  body: {
192
237
  reason: string;
193
- };
194
- params: {
195
- id: string;
238
+ pairIds?: string[] | undefined;
239
+ serialNumbers?: string[] | undefined;
196
240
  };
197
241
  }, {
198
242
  body: {
199
243
  reason: string;
200
- };
201
- params: {
202
- id: string;
244
+ pairIds?: string[] | undefined;
245
+ serialNumbers?: string[] | undefined;
203
246
  };
204
247
  }>;
205
- export declare const makePermanentSchema: z.ZodObject<{
206
- params: z.ZodObject<{
207
- id: z.ZodString;
248
+ export declare const makeDevicesPermanentSchema: z.ZodObject<{
249
+ body: z.ZodEffects<z.ZodObject<{
250
+ pairIds: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
251
+ serialNumbers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
208
252
  }, "strip", z.ZodTypeAny, {
209
- id: string;
253
+ pairIds?: string[] | undefined;
254
+ serialNumbers?: string[] | undefined;
210
255
  }, {
211
- id: string;
256
+ pairIds?: string[] | undefined;
257
+ serialNumbers?: string[] | undefined;
258
+ }>, {
259
+ pairIds?: string[] | undefined;
260
+ serialNumbers?: string[] | undefined;
261
+ }, {
262
+ pairIds?: string[] | undefined;
263
+ serialNumbers?: string[] | undefined;
212
264
  }>;
213
265
  }, "strip", z.ZodTypeAny, {
214
- params: {
215
- id: string;
266
+ body: {
267
+ pairIds?: string[] | undefined;
268
+ serialNumbers?: string[] | undefined;
216
269
  };
217
270
  }, {
218
- params: {
219
- id: string;
271
+ body: {
272
+ pairIds?: string[] | undefined;
273
+ serialNumbers?: string[] | undefined;
220
274
  };
221
275
  }>;
222
276
  export declare const checkAvailabilitySchema: z.ZodObject<{
@@ -1,22 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.checkAvailabilitySchema = exports.makePermanentSchema = exports.disableDeviceSchema = exports.adminUnlockDeviceSchema = exports.adminLockDeviceSchema = exports.deleteDeviceSchema = exports.getDevicesSchema = exports.getDeviceSchema = exports.createDevicePairsSchema = exports.deduplicatePairIds = exports.PAIR_ID_REGEX = void 0;
3
+ exports.checkAvailabilitySchema = exports.makeDevicesPermanentSchema = exports.disableDevicesSchema = exports.unlockDevicesSchema = exports.lockDevicesSchema = exports.permanentDeleteDevicesByPairsSchema = exports.deleteDevicesByPairsSchema = exports.getDevicesSchema = exports.getDeviceSchema = exports.createDevicePairsSchema = exports.deduplicatePairIds = exports.PAIR_ID_REGEX = void 0;
4
4
  // src/validations/device.validations.ts
5
5
  const zod_1 = require("zod");
6
6
  const vr_models_1 = require("vr-models");
7
- // Constants
8
- // Base device schema
9
- const deviceBaseSchema = {
10
- serialNumber: zod_1.z
11
- .string()
12
- .min(5, "Serial number must be at least 5 characters")
13
- .max(64, "Serial number too long")
14
- .regex(/^[A-Z0-9-]+$/, "Serial number must contain only uppercase letters, numbers, and hyphens"),
15
- productId: zod_1.z.string().uuid("Invalid product ID"),
16
- status: zod_1.z.enum(vr_models_1.DEVICE_STATUS).optional(),
17
- isPermanentlyUnlocked: zod_1.z.boolean().optional(),
18
- dedicatedUser: zod_1.z.enum(vr_models_1.DEVICE_DEDICATION).nullable().optional(),
19
- };
20
7
  // ✅ Pair ID format: 2 letters + 3 numbers + 1 letter
21
8
  // Example: AA001A, AB123B, XZ999Z
22
9
  // No letter 'O' to avoid confusion with 0
@@ -71,39 +58,83 @@ exports.getDevicesSchema = zod_1.z.object({
71
58
  sortOrder: zod_1.z.enum(["ASC", "DESC"]).optional(),
72
59
  }),
73
60
  });
74
- // Delete device schema
75
- exports.deleteDeviceSchema = zod_1.z.object({
76
- params: zod_1.z.object({
77
- id: zod_1.z.string().uuid("Invalid device ID"),
61
+ // src/validations/device.validations.ts
62
+ // ==================== DELETE SCHEMAS (PAIR ONLY) ====================
63
+ // Soft delete by pair IDs
64
+ exports.deleteDevicesByPairsSchema = zod_1.z.object({
65
+ body: zod_1.z.object({
66
+ pairIds: zod_1.z
67
+ .array(zod_1.z.string().regex(exports.PAIR_ID_REGEX, PAIR_ID_ERROR))
68
+ .min(1, "At least one pair ID required"),
69
+ reason: zod_1.z.string().optional(),
78
70
  }),
79
71
  });
80
- // Device status management schemas
81
- exports.adminLockDeviceSchema = zod_1.z.object({
82
- params: zod_1.z.object({
83
- id: zod_1.z.string().uuid("Invalid device ID"),
72
+ // Permanent delete by pair IDs (SUPER_ADMIN only)
73
+ exports.permanentDeleteDevicesByPairsSchema = zod_1.z.object({
74
+ body: zod_1.z.object({
75
+ pairIds: zod_1.z
76
+ .array(zod_1.z.string().regex(exports.PAIR_ID_REGEX, PAIR_ID_ERROR))
77
+ .min(1, "At least one pair ID required"),
84
78
  }),
79
+ });
80
+ // ==================== STATUS MANAGEMENT SCHEMAS (FLEXIBLE) ====================
81
+ // Base schema for flexible identifier (pairIds OR serialNumbers)
82
+ const flexibleIdentifiersSchema = {
83
+ pairIds: zod_1.z.array(zod_1.z.string().regex(exports.PAIR_ID_REGEX, PAIR_ID_ERROR)).optional(),
84
+ serialNumbers: zod_1.z.array(zod_1.z.string()).optional(),
85
+ };
86
+ // Lock devices schema
87
+ exports.lockDevicesSchema = zod_1.z.object({
85
88
  body: zod_1.z
86
89
  .object({
87
- reason: zod_1.z.string().optional(), // Why locking? Maintenance, lost, etc.
90
+ ...flexibleIdentifiersSchema,
91
+ reason: zod_1.z.string().optional(),
88
92
  })
89
- .optional(),
90
- });
91
- exports.adminUnlockDeviceSchema = zod_1.z.object({
92
- params: zod_1.z.object({
93
- id: zod_1.z.string().uuid("Invalid device ID"),
93
+ .refine((data) => {
94
+ const hasPairIds = data.pairIds && data.pairIds.length > 0;
95
+ const hasSerialNumbers = data.serialNumbers && data.serialNumbers.length > 0;
96
+ return ((hasPairIds || hasSerialNumbers) && !(hasPairIds && hasSerialNumbers));
97
+ }, {
98
+ message: "Either pairIds or serialNumbers must be provided, but not both",
99
+ path: ["pairIds"],
94
100
  }),
95
101
  });
96
- exports.disableDeviceSchema = zod_1.z.object({
97
- params: zod_1.z.object({
98
- id: zod_1.z.string().uuid("Invalid device ID"),
102
+ // Unlock devices schema
103
+ exports.unlockDevicesSchema = zod_1.z.object({
104
+ body: zod_1.z.object(flexibleIdentifiersSchema).refine((data) => {
105
+ const hasPairIds = data.pairIds && data.pairIds.length > 0;
106
+ const hasSerialNumbers = data.serialNumbers && data.serialNumbers.length > 0;
107
+ return ((hasPairIds || hasSerialNumbers) && !(hasPairIds && hasSerialNumbers));
108
+ }, {
109
+ message: "Either pairIds or serialNumbers must be provided, but not both",
110
+ path: ["pairIds"],
99
111
  }),
100
- body: zod_1.z.object({
101
- reason: zod_1.z.string().min(1, "Reason required for disabling"),
112
+ });
113
+ // Disable devices schema
114
+ exports.disableDevicesSchema = zod_1.z.object({
115
+ body: zod_1.z
116
+ .object({
117
+ ...flexibleIdentifiersSchema,
118
+ reason: zod_1.z.string().min(1, "Reason is required"),
119
+ })
120
+ .refine((data) => {
121
+ const hasPairIds = data.pairIds && data.pairIds.length > 0;
122
+ const hasSerialNumbers = data.serialNumbers && data.serialNumbers.length > 0;
123
+ return ((hasPairIds || hasSerialNumbers) && !(hasPairIds && hasSerialNumbers));
124
+ }, {
125
+ message: "Either pairIds or serialNumbers must be provided, but not both",
126
+ path: ["pairIds"],
102
127
  }),
103
128
  });
104
- exports.makePermanentSchema = zod_1.z.object({
105
- params: zod_1.z.object({
106
- id: zod_1.z.string().uuid("Invalid device ID"),
129
+ // Make permanent schema
130
+ exports.makeDevicesPermanentSchema = zod_1.z.object({
131
+ body: zod_1.z.object(flexibleIdentifiersSchema).refine((data) => {
132
+ const hasPairIds = data.pairIds && data.pairIds.length > 0;
133
+ const hasSerialNumbers = data.serialNumbers && data.serialNumbers.length > 0;
134
+ return ((hasPairIds || hasSerialNumbers) && !(hasPairIds && hasSerialNumbers));
135
+ }, {
136
+ message: "Either pairIds or serialNumbers must be provided, but not both",
137
+ path: ["pairIds"],
107
138
  }),
108
139
  });
109
140
  // Check availability schema (for assignment flow)