vr-commons 1.0.158 → 1.0.159
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.
|
@@ -121,9 +121,9 @@ export declare const stockUtil: {
|
|
|
121
121
|
devices: Device[];
|
|
122
122
|
}>;
|
|
123
123
|
/**
|
|
124
|
-
* Lock ALL
|
|
124
|
+
* Lock ALL device pairs regardless of payment plan status
|
|
125
|
+
* Locks both RIDER and PASSENGER devices in each pair together
|
|
125
126
|
* Uses batch processing for large datasets
|
|
126
|
-
* If no transaction is provided, runs without transaction
|
|
127
127
|
*/
|
|
128
128
|
lockAllDevices(options?: LockDevicesOptions): Promise<LockAllDevicesResult>;
|
|
129
129
|
};
|
|
@@ -453,33 +453,33 @@ exports.stockUtil = {
|
|
|
453
453
|
};
|
|
454
454
|
},
|
|
455
455
|
/**
|
|
456
|
-
* Lock ALL
|
|
456
|
+
* Lock ALL device pairs regardless of payment plan status
|
|
457
|
+
* Locks both RIDER and PASSENGER devices in each pair together
|
|
457
458
|
* Uses batch processing for large datasets
|
|
458
|
-
* If no transaction is provided, runs without transaction
|
|
459
459
|
*/
|
|
460
460
|
async lockAllDevices(options = {}) {
|
|
461
461
|
const { actorId = "SYSTEM", actorRole = "SYSTEM", transaction, batchSize = 100, maxRetries = 3, triggeredBy = "manual", } = options;
|
|
462
462
|
const isSystem = actorRole === "SYSTEM" || triggeredBy === "cronjob";
|
|
463
|
-
const isAdmin = !isSystem;
|
|
464
463
|
try {
|
|
465
|
-
const
|
|
466
|
-
const
|
|
464
|
+
const lockedPairIds = [];
|
|
465
|
+
const failedPairIds = [];
|
|
467
466
|
const errors = [];
|
|
468
|
-
let
|
|
469
|
-
let
|
|
467
|
+
let totalLockedDevices = 0;
|
|
468
|
+
let totalProcessedPairs = 0;
|
|
470
469
|
let batchNumber = 0;
|
|
471
470
|
let hasMore = true;
|
|
472
|
-
|
|
471
|
+
let offset = 0;
|
|
472
|
+
console.log(`🔒 Locking ALL device pairs at ${new Date().toISOString()}`);
|
|
473
473
|
// Log start of job
|
|
474
474
|
if (isSystem) {
|
|
475
|
-
await (0, systemLog_utils_1.logInfo)(`Lock all
|
|
475
|
+
await (0, systemLog_utils_1.logInfo)(`Lock all device pairs job started`, {
|
|
476
476
|
category: "CRONJOB",
|
|
477
477
|
source: "device-lock.cronjob",
|
|
478
478
|
details: { triggeredBy, batchSize, maxRetries },
|
|
479
479
|
});
|
|
480
480
|
}
|
|
481
481
|
else {
|
|
482
|
-
await (0, systemLog_utils_1.logInfo)(`Lock all
|
|
482
|
+
await (0, systemLog_utils_1.logInfo)(`Lock all device pairs triggered by ${actorRole}`, {
|
|
483
483
|
category: "DEVICE",
|
|
484
484
|
userId: actorId || undefined,
|
|
485
485
|
userRole: actorRole,
|
|
@@ -487,132 +487,170 @@ exports.stockUtil = {
|
|
|
487
487
|
details: { triggeredBy, batchSize, maxRetries },
|
|
488
488
|
});
|
|
489
489
|
}
|
|
490
|
+
// ✅ Get the sequelize instance from the model
|
|
491
|
+
const sequelizeInstance = vr_models_1.Device.sequelize;
|
|
492
|
+
if (!sequelizeInstance) {
|
|
493
|
+
throw new Error("Sequelize instance not available");
|
|
494
|
+
}
|
|
490
495
|
// Process in batches
|
|
491
496
|
while (hasMore) {
|
|
492
497
|
batchNumber++;
|
|
493
|
-
|
|
494
|
-
//
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
498
|
+
offset = (batchNumber - 1) * batchSize;
|
|
499
|
+
// ✅ Use raw query to get distinct pairIds with both devices
|
|
500
|
+
const [pairIdsResult] = await sequelizeInstance.query(`
|
|
501
|
+
SELECT "pairId"
|
|
502
|
+
FROM "devices"
|
|
503
|
+
WHERE "status" != 'disabled'
|
|
504
|
+
AND "deletedAt" IS NULL
|
|
505
|
+
GROUP BY "pairId"
|
|
506
|
+
HAVING COUNT(*) = 2
|
|
507
|
+
ORDER BY "pairId" ASC
|
|
508
|
+
LIMIT :limit
|
|
509
|
+
OFFSET :offset
|
|
510
|
+
`, {
|
|
511
|
+
replacements: {
|
|
512
|
+
limit: batchSize,
|
|
513
|
+
offset: offset,
|
|
499
514
|
},
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
transaction: transaction, // Use transaction if provided, otherwise undefined
|
|
515
|
+
type: "SELECT",
|
|
516
|
+
transaction: transaction,
|
|
503
517
|
});
|
|
504
|
-
|
|
518
|
+
const pairIds = pairIdsResult.map((p) => p.pairId);
|
|
519
|
+
if (pairIds.length === 0) {
|
|
505
520
|
hasMore = false;
|
|
506
521
|
break;
|
|
507
522
|
}
|
|
508
|
-
|
|
509
|
-
console.log(`📦 Batch ${batchNumber}: Processing ${
|
|
510
|
-
// Process each
|
|
511
|
-
for (const
|
|
523
|
+
totalProcessedPairs += pairIds.length;
|
|
524
|
+
console.log(`📦 Batch ${batchNumber}: Processing ${pairIds.length} pairs (Total: ${totalProcessedPairs})`);
|
|
525
|
+
// Process each pair
|
|
526
|
+
for (const pairId of pairIds) {
|
|
512
527
|
let retries = 0;
|
|
513
|
-
let
|
|
514
|
-
while (!
|
|
528
|
+
let pairLocked = false;
|
|
529
|
+
while (!pairLocked && retries < maxRetries) {
|
|
515
530
|
try {
|
|
516
|
-
//
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
531
|
+
// Get both devices in the pair
|
|
532
|
+
const devices = await vr_models_1.Device.findAll({
|
|
533
|
+
where: {
|
|
534
|
+
pairId: pairId,
|
|
535
|
+
status: { [sequelize_1.Op.ne]: "disabled" },
|
|
536
|
+
deletedAt: null,
|
|
537
|
+
},
|
|
538
|
+
transaction: transaction,
|
|
539
|
+
});
|
|
540
|
+
if (devices.length !== 2) {
|
|
541
|
+
throw new Error(`Incomplete pair ${pairId}: expected 2 devices, found ${devices.length}`);
|
|
542
|
+
}
|
|
543
|
+
// Check if both devices are already locked
|
|
544
|
+
const allLocked = devices.every((d) => d.status === "locked");
|
|
545
|
+
if (allLocked) {
|
|
546
|
+
console.log(`🔒 Pair ${pairId} already fully locked`);
|
|
547
|
+
pairLocked = true;
|
|
520
548
|
break;
|
|
521
549
|
}
|
|
522
|
-
// Lock
|
|
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,
|
|
550
|
+
// Lock both devices
|
|
551
|
+
const deviceIds = devices.map((d) => d.id);
|
|
552
|
+
await vr_models_1.Device.update({ status: "locked" }, {
|
|
553
|
+
where: {
|
|
554
|
+
id: { [sequelize_1.Op.in]: deviceIds },
|
|
545
555
|
},
|
|
546
|
-
deviceSession: null,
|
|
547
556
|
transaction: transaction,
|
|
548
557
|
});
|
|
558
|
+
lockedPairIds.push(pairId);
|
|
559
|
+
totalLockedDevices += devices.length;
|
|
560
|
+
pairLocked = true;
|
|
561
|
+
console.log(`🔒 Locked pair ${pairId} (${devices.length} devices)`);
|
|
562
|
+
// Log event for each device in the pair
|
|
563
|
+
for (const device of devices) {
|
|
564
|
+
await (0, eventLog_utils_1.logEvent)({
|
|
565
|
+
actorId: isSystem ? null : actorId,
|
|
566
|
+
actorType: isSystem ? "ADMIN" : actorRole,
|
|
567
|
+
action: "DEVICES_LOCKED",
|
|
568
|
+
entity: "Device",
|
|
569
|
+
entityId: device.id,
|
|
570
|
+
metadata: {
|
|
571
|
+
serialNumber: device.serialNumber,
|
|
572
|
+
pairId: device.pairId,
|
|
573
|
+
dedicatedUser: device.dedicatedUser,
|
|
574
|
+
productId: device.productId,
|
|
575
|
+
lockedAt: new Date().toISOString(),
|
|
576
|
+
reason: "Scheduled lock all devices",
|
|
577
|
+
triggeredBy: triggeredBy,
|
|
578
|
+
batchNumber,
|
|
579
|
+
previousStatus: device.status,
|
|
580
|
+
isPartOfPair: true,
|
|
581
|
+
},
|
|
582
|
+
deviceSession: null,
|
|
583
|
+
transaction: transaction,
|
|
584
|
+
});
|
|
585
|
+
}
|
|
549
586
|
}
|
|
550
587
|
catch (err) {
|
|
551
588
|
retries++;
|
|
552
|
-
console.error(`❌ Failed to lock
|
|
589
|
+
console.error(`❌ Failed to lock pair ${pairId} (attempt ${retries}/${maxRetries}):`, err instanceof Error ? err.message : "Unknown error");
|
|
553
590
|
if (retries >= maxRetries) {
|
|
554
|
-
|
|
555
|
-
errors.push(`
|
|
591
|
+
failedPairIds.push(pairId);
|
|
592
|
+
errors.push(`Pair ${pairId}: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
556
593
|
}
|
|
557
594
|
else {
|
|
558
|
-
// Wait before retry (exponential backoff)
|
|
559
595
|
await new Promise((resolve) => setTimeout(resolve, retries * 1000));
|
|
560
596
|
}
|
|
561
597
|
}
|
|
562
598
|
}
|
|
563
599
|
}
|
|
564
|
-
|
|
565
|
-
if (devices.length < batchSize) {
|
|
600
|
+
if (pairIds.length < batchSize) {
|
|
566
601
|
hasMore = false;
|
|
567
602
|
}
|
|
568
603
|
}
|
|
569
604
|
const result = {
|
|
570
605
|
success: true,
|
|
571
|
-
lockedCount:
|
|
572
|
-
failedCount:
|
|
573
|
-
|
|
606
|
+
lockedCount: totalLockedDevices,
|
|
607
|
+
failedCount: failedPairIds.length,
|
|
608
|
+
failedPairIds,
|
|
574
609
|
errors,
|
|
575
|
-
totalProcessed,
|
|
576
|
-
|
|
610
|
+
totalProcessed: totalProcessedPairs,
|
|
611
|
+
pairsProcessed: totalProcessedPairs,
|
|
612
|
+
message: `Successfully locked ${totalLockedDevices} devices (${lockedPairIds.length} pairs) out of ${totalProcessedPairs} pairs processed${failedPairIds.length > 0
|
|
613
|
+
? `, ${failedPairIds.length} pairs failed`
|
|
614
|
+
: ""}`,
|
|
577
615
|
};
|
|
578
|
-
console.log(`✅ Lock all
|
|
616
|
+
console.log(`✅ Lock all device pairs completed:`, result);
|
|
579
617
|
// Log completion
|
|
580
618
|
if (isSystem) {
|
|
581
|
-
await (0, systemLog_utils_1.logInfo)(`Lock all
|
|
619
|
+
await (0, systemLog_utils_1.logInfo)(`Lock all device pairs job completed`, {
|
|
582
620
|
category: "CRONJOB",
|
|
583
621
|
source: "device-lock.cronjob",
|
|
584
622
|
details: {
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
623
|
+
lockedDevices: result.lockedCount,
|
|
624
|
+
lockedPairs: lockedPairIds.length,
|
|
625
|
+
failedPairs: result.failedCount,
|
|
626
|
+
totalPairs: result.pairsProcessed,
|
|
588
627
|
hasErrors: result.errors.length > 0,
|
|
589
628
|
},
|
|
590
629
|
});
|
|
591
630
|
}
|
|
592
631
|
else {
|
|
593
|
-
await (0, systemLog_utils_1.logInfo)(`Lock all
|
|
632
|
+
await (0, systemLog_utils_1.logInfo)(`Lock all device pairs completed by ${actorRole}`, {
|
|
594
633
|
category: "DEVICE",
|
|
595
634
|
userId: actorId || undefined,
|
|
596
635
|
userRole: actorRole,
|
|
597
636
|
source: "device-lock.manual",
|
|
598
637
|
details: {
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
638
|
+
lockedDevices: result.lockedCount,
|
|
639
|
+
lockedPairs: lockedPairIds.length,
|
|
640
|
+
failedPairs: result.failedCount,
|
|
641
|
+
totalPairs: result.pairsProcessed,
|
|
602
642
|
hasErrors: result.errors.length > 0,
|
|
603
643
|
},
|
|
604
644
|
});
|
|
605
645
|
}
|
|
606
|
-
// Log errors if any
|
|
607
646
|
if (result.errors.length > 0) {
|
|
608
|
-
await (0, systemLog_utils_1.logError)(`Lock all
|
|
647
|
+
await (0, systemLog_utils_1.logError)(`Lock all device pairs had ${result.errors.length} failures`, {
|
|
609
648
|
category: isSystem ? "CRONJOB" : "DEVICE",
|
|
610
649
|
source: isSystem ? "device-lock.cronjob" : "device-lock.manual",
|
|
611
650
|
userId: isSystem ? null : actorId || undefined,
|
|
612
651
|
userRole: isSystem ? null : actorRole,
|
|
613
652
|
details: {
|
|
614
|
-
|
|
615
|
-
failedDeviceIds: result.failedDeviceIds,
|
|
653
|
+
failedPairs: result.failedPairIds,
|
|
616
654
|
errors: result.errors,
|
|
617
655
|
},
|
|
618
656
|
});
|
|
@@ -620,27 +658,27 @@ exports.stockUtil = {
|
|
|
620
658
|
return result;
|
|
621
659
|
}
|
|
622
660
|
catch (err) {
|
|
623
|
-
console.error("❌ Lock all
|
|
661
|
+
console.error("❌ Lock all device pairs failed:", err);
|
|
624
662
|
const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
|
|
625
663
|
const result = {
|
|
626
664
|
success: false,
|
|
627
665
|
lockedCount: 0,
|
|
628
666
|
failedCount: 0,
|
|
629
|
-
|
|
667
|
+
failedPairIds: [],
|
|
630
668
|
errors: [errorMessage],
|
|
631
669
|
totalProcessed: 0,
|
|
632
|
-
|
|
670
|
+
pairsProcessed: 0,
|
|
671
|
+
message: `Lock all device pairs job failed: ${errorMessage}`,
|
|
633
672
|
};
|
|
634
|
-
// Log failure
|
|
635
673
|
if (isSystem) {
|
|
636
|
-
await (0, systemLog_utils_1.logError)(`Lock all
|
|
674
|
+
await (0, systemLog_utils_1.logError)(`Lock all device pairs job failed`, {
|
|
637
675
|
category: "CRONJOB",
|
|
638
676
|
source: "device-lock.cronjob",
|
|
639
677
|
details: { error: errorMessage },
|
|
640
678
|
});
|
|
641
679
|
}
|
|
642
680
|
else {
|
|
643
|
-
await (0, systemLog_utils_1.logError)(`Lock all
|
|
681
|
+
await (0, systemLog_utils_1.logError)(`Lock all device pairs failed`, {
|
|
644
682
|
category: "DEVICE",
|
|
645
683
|
userId: actorId || undefined,
|
|
646
684
|
userRole: actorRole,
|
package/dist/utils/types.d.ts
CHANGED
|
@@ -39,10 +39,11 @@ export interface LockAllDevicesResult {
|
|
|
39
39
|
success: boolean;
|
|
40
40
|
lockedCount: 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
48
|
export interface LockDevicesOptions {
|
|
48
49
|
actorId?: string;
|