vr-commons 1.0.158 → 1.0.160
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.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Device, UserRole } from "vr-models";
|
|
2
2
|
import { Transaction } from "sequelize";
|
|
3
|
-
import {
|
|
3
|
+
import { DeviceResetOptions, DeviceResetResult, StockChangeResult } from "./types";
|
|
4
4
|
export declare const stockUtil: {
|
|
5
5
|
/**
|
|
6
6
|
* Increment stock when devices are added/created
|
|
@@ -121,9 +121,10 @@ export declare const stockUtil: {
|
|
|
121
121
|
devices: Device[];
|
|
122
122
|
}>;
|
|
123
123
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
124
|
+
* Reset device pairs status based on conditions
|
|
125
|
+
* - Locks/unlocks both RIDER and PASSENGER devices in each pair together
|
|
126
|
+
* - Flexible conditions and updates
|
|
127
|
+
* - Uses batch processing for large datasets
|
|
127
128
|
*/
|
|
128
|
-
|
|
129
|
+
resetAllDevicesStatus(options?: DeviceResetOptions): Promise<DeviceResetResult>;
|
|
129
130
|
};
|
|
@@ -17,6 +17,155 @@ const extractDedicationFromSerial = (serialNumber) => {
|
|
|
17
17
|
return "PASSENGER";
|
|
18
18
|
return "N/A";
|
|
19
19
|
};
|
|
20
|
+
// ==================== HELPER FUNCTIONS ====================
|
|
21
|
+
function buildWhereClause(condition) {
|
|
22
|
+
const parts = [];
|
|
23
|
+
if (condition.status) {
|
|
24
|
+
const statuses = Array.isArray(condition.status)
|
|
25
|
+
? condition.status
|
|
26
|
+
: [condition.status];
|
|
27
|
+
const quoted = statuses.map((s) => `'${s}'`).join(", ");
|
|
28
|
+
parts.push(`"status" IN (${quoted})`);
|
|
29
|
+
}
|
|
30
|
+
if (condition.excludeStatus) {
|
|
31
|
+
const statuses = Array.isArray(condition.excludeStatus)
|
|
32
|
+
? condition.excludeStatus
|
|
33
|
+
: [condition.excludeStatus];
|
|
34
|
+
const quoted = statuses.map((s) => `'${s}'`).join(", ");
|
|
35
|
+
parts.push(`"status" NOT IN (${quoted})`);
|
|
36
|
+
}
|
|
37
|
+
if (condition.isPermanentlyUnlocked !== undefined) {
|
|
38
|
+
parts.push(`"isPermanentlyUnlocked" = ${condition.isPermanentlyUnlocked}`);
|
|
39
|
+
}
|
|
40
|
+
if (condition.pairId) {
|
|
41
|
+
const pairIds = Array.isArray(condition.pairId)
|
|
42
|
+
? condition.pairId
|
|
43
|
+
: [condition.pairId];
|
|
44
|
+
const quoted = pairIds.map((p) => `'${p}'`).join(", ");
|
|
45
|
+
parts.push(`"pairId" IN (${quoted})`);
|
|
46
|
+
}
|
|
47
|
+
if (condition.excludePairIds) {
|
|
48
|
+
const pairIds = Array.isArray(condition.excludePairIds)
|
|
49
|
+
? condition.excludePairIds
|
|
50
|
+
: [condition.excludePairIds];
|
|
51
|
+
const quoted = pairIds.map((p) => `'${p}'`).join(", ");
|
|
52
|
+
parts.push(`"pairId" NOT IN (${quoted})`);
|
|
53
|
+
}
|
|
54
|
+
if (condition.productId) {
|
|
55
|
+
const productIds = Array.isArray(condition.productId)
|
|
56
|
+
? condition.productId
|
|
57
|
+
: [condition.productId];
|
|
58
|
+
const quoted = productIds.map((p) => `'${p}'`).join(", ");
|
|
59
|
+
parts.push(`"productId" IN (${quoted})`);
|
|
60
|
+
}
|
|
61
|
+
if (condition.dedicatedUser) {
|
|
62
|
+
const users = Array.isArray(condition.dedicatedUser)
|
|
63
|
+
? condition.dedicatedUser
|
|
64
|
+
: [condition.dedicatedUser];
|
|
65
|
+
const quoted = users.map((u) => `'${u}'`).join(", ");
|
|
66
|
+
parts.push(`"dedicatedUser" IN (${quoted})`);
|
|
67
|
+
}
|
|
68
|
+
if (condition.createdBefore) {
|
|
69
|
+
parts.push(`"createdAt" < '${condition.createdBefore.toISOString()}'`);
|
|
70
|
+
}
|
|
71
|
+
if (condition.createdAfter) {
|
|
72
|
+
parts.push(`"createdAt" > '${condition.createdAfter.toISOString()}'`);
|
|
73
|
+
}
|
|
74
|
+
return parts.length > 0 ? parts.join(" AND ") : "1=1";
|
|
75
|
+
}
|
|
76
|
+
function buildSequelizeWhere(condition) {
|
|
77
|
+
const where = {};
|
|
78
|
+
if (condition.status) {
|
|
79
|
+
where.status = {
|
|
80
|
+
[sequelize_1.Op.in]: Array.isArray(condition.status)
|
|
81
|
+
? condition.status
|
|
82
|
+
: [condition.status],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (condition.excludeStatus) {
|
|
86
|
+
where.status = {
|
|
87
|
+
...where.status,
|
|
88
|
+
[sequelize_1.Op.notIn]: Array.isArray(condition.excludeStatus)
|
|
89
|
+
? condition.excludeStatus
|
|
90
|
+
: [condition.excludeStatus],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
if (condition.isPermanentlyUnlocked !== undefined) {
|
|
94
|
+
where.isPermanentlyUnlocked = condition.isPermanentlyUnlocked;
|
|
95
|
+
}
|
|
96
|
+
if (condition.pairId) {
|
|
97
|
+
where.pairId = {
|
|
98
|
+
[sequelize_1.Op.in]: Array.isArray(condition.pairId)
|
|
99
|
+
? condition.pairId
|
|
100
|
+
: [condition.pairId],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
if (condition.excludePairIds) {
|
|
104
|
+
where.pairId = {
|
|
105
|
+
[sequelize_1.Op.notIn]: Array.isArray(condition.excludePairIds)
|
|
106
|
+
? condition.excludePairIds
|
|
107
|
+
: [condition.excludePairIds],
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
if (condition.productId) {
|
|
111
|
+
where.productId = {
|
|
112
|
+
[sequelize_1.Op.in]: Array.isArray(condition.productId)
|
|
113
|
+
? condition.productId
|
|
114
|
+
: [condition.productId],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
if (condition.dedicatedUser) {
|
|
118
|
+
where.dedicatedUser = {
|
|
119
|
+
[sequelize_1.Op.in]: Array.isArray(condition.dedicatedUser)
|
|
120
|
+
? condition.dedicatedUser
|
|
121
|
+
: [condition.dedicatedUser],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if (condition.createdBefore) {
|
|
125
|
+
where.createdAt = { [sequelize_1.Op.lt]: condition.createdBefore };
|
|
126
|
+
}
|
|
127
|
+
if (condition.createdAfter) {
|
|
128
|
+
where.createdAt = { ...where.createdAt, [sequelize_1.Op.gt]: condition.createdAfter };
|
|
129
|
+
}
|
|
130
|
+
return where;
|
|
131
|
+
}
|
|
132
|
+
function buildSetClause(update) {
|
|
133
|
+
const parts = [];
|
|
134
|
+
if (update.status !== undefined) {
|
|
135
|
+
parts.push(`"status" = '${update.status}'`);
|
|
136
|
+
}
|
|
137
|
+
if (update.isPermanentlyUnlocked !== undefined) {
|
|
138
|
+
parts.push(`"isPermanentlyUnlocked" = ${update.isPermanentlyUnlocked}`);
|
|
139
|
+
}
|
|
140
|
+
if (update.dedicatedUser !== undefined) {
|
|
141
|
+
parts.push(`"dedicatedUser" = '${update.dedicatedUser}'`);
|
|
142
|
+
}
|
|
143
|
+
if (update.devicePaymentPlanId !== undefined) {
|
|
144
|
+
parts.push(`"devicePaymentPlanId" = ${update.devicePaymentPlanId === null
|
|
145
|
+
? "NULL"
|
|
146
|
+
: `'${update.devicePaymentPlanId}'`}`);
|
|
147
|
+
}
|
|
148
|
+
if (update.activatedAt !== undefined) {
|
|
149
|
+
parts.push(`"activatedAt" = ${update.activatedAt === null
|
|
150
|
+
? "NULL"
|
|
151
|
+
: `'${update.activatedAt.toISOString()}'`}`);
|
|
152
|
+
}
|
|
153
|
+
return parts.length > 0 ? parts.join(", ") : "1=1";
|
|
154
|
+
}
|
|
155
|
+
function buildUpdateObject(update) {
|
|
156
|
+
const obj = {};
|
|
157
|
+
if (update.status !== undefined)
|
|
158
|
+
obj.status = update.status;
|
|
159
|
+
if (update.isPermanentlyUnlocked !== undefined)
|
|
160
|
+
obj.isPermanentlyUnlocked = update.isPermanentlyUnlocked;
|
|
161
|
+
if (update.dedicatedUser !== undefined)
|
|
162
|
+
obj.dedicatedUser = update.dedicatedUser;
|
|
163
|
+
if (update.devicePaymentPlanId !== undefined)
|
|
164
|
+
obj.devicePaymentPlanId = update.devicePaymentPlanId;
|
|
165
|
+
if (update.activatedAt !== undefined)
|
|
166
|
+
obj.activatedAt = update.activatedAt;
|
|
167
|
+
return obj;
|
|
168
|
+
}
|
|
20
169
|
exports.stockUtil = {
|
|
21
170
|
/**
|
|
22
171
|
* Increment stock when devices are added/created
|
|
@@ -453,166 +602,219 @@ exports.stockUtil = {
|
|
|
453
602
|
};
|
|
454
603
|
},
|
|
455
604
|
/**
|
|
456
|
-
*
|
|
457
|
-
*
|
|
458
|
-
*
|
|
605
|
+
* Reset device pairs status based on conditions
|
|
606
|
+
* - Locks/unlocks both RIDER and PASSENGER devices in each pair together
|
|
607
|
+
* - Flexible conditions and updates
|
|
608
|
+
* - Uses batch processing for large datasets
|
|
459
609
|
*/
|
|
460
|
-
async
|
|
461
|
-
const { actorId = "SYSTEM", actorRole = "SYSTEM", transaction, batchSize = 100, maxRetries = 3, triggeredBy = "manual", } = options;
|
|
610
|
+
async resetAllDevicesStatus(options = {}) {
|
|
611
|
+
const { actorId = "SYSTEM", actorRole = "SYSTEM", transaction, batchSize = 100, maxRetries = 3, triggeredBy = "manual", condition = {}, update = {}, } = options;
|
|
462
612
|
const isSystem = actorRole === "SYSTEM" || triggeredBy === "cronjob";
|
|
463
|
-
const isAdmin = !isSystem;
|
|
464
613
|
try {
|
|
465
|
-
const
|
|
466
|
-
const
|
|
614
|
+
const updatedPairIds = [];
|
|
615
|
+
const failedPairIds = [];
|
|
467
616
|
const errors = [];
|
|
468
|
-
|
|
469
|
-
let
|
|
617
|
+
const allDeviceIds = [];
|
|
618
|
+
let totalUpdatedDevices = 0;
|
|
619
|
+
let totalProcessedPairs = 0;
|
|
470
620
|
let batchNumber = 0;
|
|
471
621
|
let hasMore = true;
|
|
472
|
-
|
|
473
|
-
//
|
|
622
|
+
let offset = 0;
|
|
623
|
+
// Build WHERE clause for the query
|
|
624
|
+
const whereClause = buildWhereClause(condition);
|
|
625
|
+
// Build UPDATE SET clause
|
|
626
|
+
const setClause = buildSetClause(update);
|
|
627
|
+
console.log(`🔄 Resetting device pairs at ${new Date().toISOString()}`);
|
|
628
|
+
console.log(`📋 WHERE: ${whereClause}`);
|
|
629
|
+
console.log(`📝 SET: ${setClause}`);
|
|
630
|
+
// Log start
|
|
474
631
|
if (isSystem) {
|
|
475
|
-
await (0, systemLog_utils_1.logInfo)(`
|
|
632
|
+
await (0, systemLog_utils_1.logInfo)(`Reset device pairs job started`, {
|
|
476
633
|
category: "CRONJOB",
|
|
477
|
-
source: "device-
|
|
478
|
-
details: { triggeredBy, batchSize, maxRetries },
|
|
634
|
+
source: "device-reset.cronjob",
|
|
635
|
+
details: { triggeredBy, batchSize, maxRetries, condition, update },
|
|
479
636
|
});
|
|
480
637
|
}
|
|
481
638
|
else {
|
|
482
|
-
await (0, systemLog_utils_1.logInfo)(`
|
|
639
|
+
await (0, systemLog_utils_1.logInfo)(`Reset device pairs triggered by ${actorRole}`, {
|
|
483
640
|
category: "DEVICE",
|
|
484
641
|
userId: actorId || undefined,
|
|
485
642
|
userRole: actorRole,
|
|
486
|
-
source: "device-
|
|
487
|
-
details: { triggeredBy, batchSize, maxRetries },
|
|
643
|
+
source: "device-reset.manual",
|
|
644
|
+
details: { triggeredBy, batchSize, maxRetries, condition, update },
|
|
488
645
|
});
|
|
489
646
|
}
|
|
647
|
+
const sequelizeInstance = vr_models_1.Device.sequelize;
|
|
648
|
+
if (!sequelizeInstance) {
|
|
649
|
+
throw new Error("Sequelize instance not available");
|
|
650
|
+
}
|
|
490
651
|
// Process in batches
|
|
491
652
|
while (hasMore) {
|
|
492
653
|
batchNumber++;
|
|
493
|
-
|
|
494
|
-
// Get
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
654
|
+
offset = (batchNumber - 1) * batchSize;
|
|
655
|
+
// Get distinct pairIds that match the condition
|
|
656
|
+
const [pairIdsResult] = await sequelizeInstance.query(`
|
|
657
|
+
SELECT "pairId"
|
|
658
|
+
FROM "devices"
|
|
659
|
+
WHERE "deletedAt" IS NULL
|
|
660
|
+
AND ${whereClause}
|
|
661
|
+
GROUP BY "pairId"
|
|
662
|
+
HAVING COUNT(*) = 2
|
|
663
|
+
ORDER BY "pairId" ASC
|
|
664
|
+
LIMIT :limit
|
|
665
|
+
OFFSET :offset
|
|
666
|
+
`, {
|
|
667
|
+
replacements: {
|
|
668
|
+
limit: batchSize,
|
|
669
|
+
offset: offset,
|
|
499
670
|
},
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
transaction: transaction, // Use transaction if provided, otherwise undefined
|
|
671
|
+
type: "SELECT",
|
|
672
|
+
transaction: transaction,
|
|
503
673
|
});
|
|
504
|
-
|
|
674
|
+
const pairIds = pairIdsResult.map((p) => p.pairId);
|
|
675
|
+
if (pairIds.length === 0) {
|
|
505
676
|
hasMore = false;
|
|
506
677
|
break;
|
|
507
678
|
}
|
|
508
|
-
|
|
509
|
-
console.log(`📦 Batch ${batchNumber}: Processing ${
|
|
510
|
-
|
|
511
|
-
for (const device of devices) {
|
|
679
|
+
totalProcessedPairs += pairIds.length;
|
|
680
|
+
console.log(`📦 Batch ${batchNumber}: Processing ${pairIds.length} pairs (Total: ${totalProcessedPairs})`);
|
|
681
|
+
for (const pairId of pairIds) {
|
|
512
682
|
let retries = 0;
|
|
513
|
-
let
|
|
514
|
-
while (!
|
|
683
|
+
let pairUpdated = false;
|
|
684
|
+
while (!pairUpdated && retries < maxRetries) {
|
|
515
685
|
try {
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
686
|
+
const devices = await vr_models_1.Device.findAll({
|
|
687
|
+
where: {
|
|
688
|
+
pairId: pairId,
|
|
689
|
+
deletedAt: null,
|
|
690
|
+
...buildSequelizeWhere(condition),
|
|
691
|
+
},
|
|
692
|
+
transaction: transaction,
|
|
693
|
+
});
|
|
694
|
+
if (devices.length !== 2) {
|
|
695
|
+
throw new Error(`Incomplete pair ${pairId}: expected 2 devices, found ${devices.length}`);
|
|
696
|
+
}
|
|
697
|
+
// Check if update would be a no-op
|
|
698
|
+
const shouldUpdate = devices.some((d) => {
|
|
699
|
+
const updateObj = buildUpdateObject(update);
|
|
700
|
+
return Object.keys(updateObj).some((key) => d[key] !== updateObj[key]);
|
|
701
|
+
});
|
|
702
|
+
if (!shouldUpdate) {
|
|
703
|
+
console.log(`⏭️ Pair ${pairId} already matches target state`);
|
|
704
|
+
pairUpdated = true;
|
|
520
705
|
break;
|
|
521
706
|
}
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
)
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
locked = true;
|
|
528
|
-
console.log(`🔒 Locked device ${device.serialNumber} (${device.id})`);
|
|
529
|
-
// Log event for each lock
|
|
530
|
-
await (0, eventLog_utils_1.logEvent)({
|
|
531
|
-
actorId: isSystem ? null : actorId,
|
|
532
|
-
actorType: isSystem ? "ADMIN" : actorRole,
|
|
533
|
-
action: "DEVICES_LOCKED",
|
|
534
|
-
entity: "Device",
|
|
535
|
-
entityId: device.id,
|
|
536
|
-
metadata: {
|
|
537
|
-
serialNumber: device.serialNumber,
|
|
538
|
-
pairId: device.pairId,
|
|
539
|
-
productId: device.productId,
|
|
540
|
-
lockedAt: new Date().toISOString(),
|
|
541
|
-
reason: "Scheduled lock all devices",
|
|
542
|
-
triggeredBy: triggeredBy,
|
|
543
|
-
batchNumber,
|
|
544
|
-
previousStatus: device.status,
|
|
707
|
+
const deviceIds = devices.map((d) => d.id);
|
|
708
|
+
allDeviceIds.push(...deviceIds);
|
|
709
|
+
await vr_models_1.Device.update(buildUpdateObject(update), {
|
|
710
|
+
where: {
|
|
711
|
+
id: { [sequelize_1.Op.in]: deviceIds },
|
|
545
712
|
},
|
|
546
|
-
deviceSession: null,
|
|
547
713
|
transaction: transaction,
|
|
548
714
|
});
|
|
715
|
+
updatedPairIds.push(pairId);
|
|
716
|
+
totalUpdatedDevices += devices.length;
|
|
717
|
+
pairUpdated = true;
|
|
718
|
+
console.log(`✅ Updated pair ${pairId} (${devices.length} devices)`);
|
|
549
719
|
}
|
|
550
720
|
catch (err) {
|
|
551
721
|
retries++;
|
|
552
|
-
console.error(`❌ Failed to
|
|
722
|
+
console.error(`❌ Failed to update pair ${pairId} (attempt ${retries}/${maxRetries}):`, err instanceof Error ? err.message : "Unknown error");
|
|
553
723
|
if (retries >= maxRetries) {
|
|
554
|
-
|
|
555
|
-
errors.push(`
|
|
724
|
+
failedPairIds.push(pairId);
|
|
725
|
+
errors.push(`Pair ${pairId}: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
556
726
|
}
|
|
557
727
|
else {
|
|
558
|
-
// Wait before retry (exponential backoff)
|
|
559
728
|
await new Promise((resolve) => setTimeout(resolve, retries * 1000));
|
|
560
729
|
}
|
|
561
730
|
}
|
|
562
731
|
}
|
|
563
732
|
}
|
|
564
|
-
|
|
565
|
-
if (devices.length < batchSize) {
|
|
733
|
+
if (pairIds.length < batchSize) {
|
|
566
734
|
hasMore = false;
|
|
567
735
|
}
|
|
568
736
|
}
|
|
569
737
|
const result = {
|
|
570
738
|
success: true,
|
|
571
|
-
|
|
572
|
-
failedCount:
|
|
573
|
-
|
|
739
|
+
updatedCount: totalUpdatedDevices,
|
|
740
|
+
failedCount: failedPairIds.length,
|
|
741
|
+
failedPairIds,
|
|
574
742
|
errors,
|
|
575
|
-
totalProcessed,
|
|
576
|
-
|
|
743
|
+
totalProcessed: totalProcessedPairs,
|
|
744
|
+
pairsProcessed: totalProcessedPairs,
|
|
745
|
+
message: `Successfully updated ${totalUpdatedDevices} devices (${updatedPairIds.length} pairs) out of ${totalProcessedPairs} pairs processed${failedPairIds.length > 0
|
|
746
|
+
? `, ${failedPairIds.length} pairs failed`
|
|
747
|
+
: ""}`,
|
|
577
748
|
};
|
|
578
|
-
console.log(`✅
|
|
579
|
-
// Log
|
|
749
|
+
console.log(`✅ Reset device pairs completed:`, result);
|
|
750
|
+
// Log single event with summary
|
|
751
|
+
await (0, eventLog_utils_1.logEvent)({
|
|
752
|
+
actorId: isSystem ? null : actorId,
|
|
753
|
+
actorType: isSystem ? "ADMIN" : actorRole,
|
|
754
|
+
action: "DEVICES_UPDATED",
|
|
755
|
+
entity: "Device",
|
|
756
|
+
entityId: null,
|
|
757
|
+
metadata: {
|
|
758
|
+
action: "RESET_DEVICES_STATUS",
|
|
759
|
+
triggeredBy: triggeredBy,
|
|
760
|
+
condition: condition,
|
|
761
|
+
update: update,
|
|
762
|
+
summary: {
|
|
763
|
+
totalPairsProcessed: result.pairsProcessed,
|
|
764
|
+
totalDevicesUpdated: result.updatedCount,
|
|
765
|
+
totalPairsUpdated: updatedPairIds.length,
|
|
766
|
+
failedPairs: result.failedCount,
|
|
767
|
+
failedPairIds: result.failedPairIds,
|
|
768
|
+
errors: result.errors,
|
|
769
|
+
deviceIds: allDeviceIds.slice(0, 100),
|
|
770
|
+
},
|
|
771
|
+
batchDetails: {
|
|
772
|
+
totalBatches: batchNumber,
|
|
773
|
+
batchSize: batchSize,
|
|
774
|
+
maxRetries: maxRetries,
|
|
775
|
+
},
|
|
776
|
+
timestamp: new Date().toISOString(),
|
|
777
|
+
},
|
|
778
|
+
deviceSession: null,
|
|
779
|
+
transaction: transaction,
|
|
780
|
+
});
|
|
781
|
+
// Log to system logs
|
|
580
782
|
if (isSystem) {
|
|
581
|
-
await (0, systemLog_utils_1.logInfo)(`
|
|
783
|
+
await (0, systemLog_utils_1.logInfo)(`Reset device pairs job completed`, {
|
|
582
784
|
category: "CRONJOB",
|
|
583
|
-
source: "device-
|
|
785
|
+
source: "device-reset.cronjob",
|
|
584
786
|
details: {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
787
|
+
updatedDevices: result.updatedCount,
|
|
788
|
+
updatedPairs: updatedPairIds.length,
|
|
789
|
+
failedPairs: result.failedCount,
|
|
790
|
+
totalPairs: result.pairsProcessed,
|
|
588
791
|
hasErrors: result.errors.length > 0,
|
|
589
792
|
},
|
|
590
793
|
});
|
|
591
794
|
}
|
|
592
795
|
else {
|
|
593
|
-
await (0, systemLog_utils_1.logInfo)(`
|
|
796
|
+
await (0, systemLog_utils_1.logInfo)(`Reset device pairs completed by ${actorRole}`, {
|
|
594
797
|
category: "DEVICE",
|
|
595
798
|
userId: actorId || undefined,
|
|
596
799
|
userRole: actorRole,
|
|
597
|
-
source: "device-
|
|
800
|
+
source: "device-reset.manual",
|
|
598
801
|
details: {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
802
|
+
updatedDevices: result.updatedCount,
|
|
803
|
+
updatedPairs: updatedPairIds.length,
|
|
804
|
+
failedPairs: result.failedCount,
|
|
805
|
+
totalPairs: result.pairsProcessed,
|
|
602
806
|
hasErrors: result.errors.length > 0,
|
|
603
807
|
},
|
|
604
808
|
});
|
|
605
809
|
}
|
|
606
|
-
// Log errors if any
|
|
607
810
|
if (result.errors.length > 0) {
|
|
608
|
-
await (0, systemLog_utils_1.logError)(`
|
|
811
|
+
await (0, systemLog_utils_1.logError)(`Reset device pairs had ${result.errors.length} failures`, {
|
|
609
812
|
category: isSystem ? "CRONJOB" : "DEVICE",
|
|
610
|
-
source: isSystem ? "device-
|
|
813
|
+
source: isSystem ? "device-reset.cronjob" : "device-reset.manual",
|
|
611
814
|
userId: isSystem ? null : actorId || undefined,
|
|
612
815
|
userRole: isSystem ? null : actorRole,
|
|
613
816
|
details: {
|
|
614
|
-
|
|
615
|
-
failedDeviceIds: result.failedDeviceIds,
|
|
817
|
+
failedPairs: result.failedPairIds,
|
|
616
818
|
errors: result.errors,
|
|
617
819
|
},
|
|
618
820
|
});
|
|
@@ -620,31 +822,31 @@ exports.stockUtil = {
|
|
|
620
822
|
return result;
|
|
621
823
|
}
|
|
622
824
|
catch (err) {
|
|
623
|
-
console.error("❌
|
|
825
|
+
console.error("❌ Reset device pairs failed:", err);
|
|
624
826
|
const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
|
|
625
827
|
const result = {
|
|
626
828
|
success: false,
|
|
627
|
-
|
|
829
|
+
updatedCount: 0,
|
|
628
830
|
failedCount: 0,
|
|
629
|
-
|
|
831
|
+
failedPairIds: [],
|
|
630
832
|
errors: [errorMessage],
|
|
631
833
|
totalProcessed: 0,
|
|
632
|
-
|
|
834
|
+
pairsProcessed: 0,
|
|
835
|
+
message: `Reset device pairs job failed: ${errorMessage}`,
|
|
633
836
|
};
|
|
634
|
-
// Log failure
|
|
635
837
|
if (isSystem) {
|
|
636
|
-
await (0, systemLog_utils_1.logError)(`
|
|
838
|
+
await (0, systemLog_utils_1.logError)(`Reset device pairs job failed`, {
|
|
637
839
|
category: "CRONJOB",
|
|
638
|
-
source: "device-
|
|
840
|
+
source: "device-reset.cronjob",
|
|
639
841
|
details: { error: errorMessage },
|
|
640
842
|
});
|
|
641
843
|
}
|
|
642
844
|
else {
|
|
643
|
-
await (0, systemLog_utils_1.logError)(`
|
|
845
|
+
await (0, systemLog_utils_1.logError)(`Reset device pairs failed`, {
|
|
644
846
|
category: "DEVICE",
|
|
645
847
|
userId: actorId || undefined,
|
|
646
848
|
userRole: actorRole,
|
|
647
|
-
source: "device-
|
|
849
|
+
source: "device-reset.manual",
|
|
648
850
|
details: { error: errorMessage },
|
|
649
851
|
});
|
|
650
852
|
}
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -35,20 +35,39 @@ export interface StockChangeResult {
|
|
|
35
35
|
productId: string;
|
|
36
36
|
productName: string;
|
|
37
37
|
}
|
|
38
|
-
export interface
|
|
38
|
+
export interface DeviceResetResult {
|
|
39
39
|
success: boolean;
|
|
40
|
-
|
|
40
|
+
updatedCount: number;
|
|
41
41
|
failedCount: number;
|
|
42
|
-
|
|
42
|
+
failedPairIds: string[];
|
|
43
43
|
errors: string[];
|
|
44
44
|
message: string;
|
|
45
45
|
totalProcessed: number;
|
|
46
|
+
pairsProcessed: number;
|
|
46
47
|
}
|
|
47
|
-
export interface
|
|
48
|
+
export interface DeviceResetOptions {
|
|
48
49
|
actorId?: string;
|
|
49
50
|
actorRole?: UserRole | string;
|
|
50
51
|
transaction?: any;
|
|
51
52
|
batchSize?: number;
|
|
52
53
|
maxRetries?: number;
|
|
53
54
|
triggeredBy?: "cronjob" | "manual";
|
|
55
|
+
condition?: {
|
|
56
|
+
status?: string | string[];
|
|
57
|
+
isPermanentlyUnlocked?: boolean;
|
|
58
|
+
pairId?: string | string[];
|
|
59
|
+
productId?: string | string[];
|
|
60
|
+
dedicatedUser?: string | string[];
|
|
61
|
+
createdBefore?: Date;
|
|
62
|
+
createdAfter?: Date;
|
|
63
|
+
excludeStatus?: string | string[];
|
|
64
|
+
excludePairIds?: string | string[];
|
|
65
|
+
};
|
|
66
|
+
update?: {
|
|
67
|
+
status?: string;
|
|
68
|
+
isPermanentlyUnlocked?: boolean;
|
|
69
|
+
dedicatedUser?: string;
|
|
70
|
+
devicePaymentPlanId?: string | null;
|
|
71
|
+
activatedAt?: Date | null;
|
|
72
|
+
};
|
|
54
73
|
}
|