@blackcode_sa/metaestetics-api 1.6.18 → 1.6.20
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.
package/dist/admin/index.js
CHANGED
|
@@ -3345,18 +3345,47 @@ var AppointmentAggregationService = class {
|
|
|
3345
3345
|
try {
|
|
3346
3346
|
const batch = this.db.batch();
|
|
3347
3347
|
let instancesCreatedCount = 0;
|
|
3348
|
+
let createdInstances = [];
|
|
3349
|
+
Logger.info(
|
|
3350
|
+
`[AggService] Found ${appointment.preProcedureRequirements.length} pre-requirements to process: ${JSON.stringify(
|
|
3351
|
+
appointment.preProcedureRequirements.map((r) => {
|
|
3352
|
+
var _a2, _b;
|
|
3353
|
+
return {
|
|
3354
|
+
id: r.id,
|
|
3355
|
+
name: r.name,
|
|
3356
|
+
type: r.type,
|
|
3357
|
+
isActive: r.isActive,
|
|
3358
|
+
hasTimeframe: !!r.timeframe,
|
|
3359
|
+
notifyAtLength: ((_b = (_a2 = r.timeframe) == null ? void 0 : _a2.notifyAt) == null ? void 0 : _b.length) || 0
|
|
3360
|
+
};
|
|
3361
|
+
})
|
|
3362
|
+
)}`
|
|
3363
|
+
);
|
|
3348
3364
|
for (const template of appointment.preProcedureRequirements) {
|
|
3349
|
-
if (!template)
|
|
3365
|
+
if (!template) {
|
|
3366
|
+
Logger.warn(
|
|
3367
|
+
`[AggService] Found null/undefined template in preProcedureRequirements array`
|
|
3368
|
+
);
|
|
3369
|
+
continue;
|
|
3370
|
+
}
|
|
3350
3371
|
if (template.type !== "pre" /* PRE */ || !template.isActive) {
|
|
3351
3372
|
Logger.debug(
|
|
3352
3373
|
`[AggService] Skipping template ${template.id} (${template.name}): not an active PRE requirement.`
|
|
3353
3374
|
);
|
|
3354
3375
|
continue;
|
|
3355
3376
|
}
|
|
3377
|
+
if (!template.timeframe || !template.timeframe.notifyAt || template.timeframe.notifyAt.length === 0) {
|
|
3378
|
+
Logger.warn(
|
|
3379
|
+
`[AggService] Template ${template.id} (${template.name}) has no timeframe.notifyAt values. Creating with empty instructions.`
|
|
3380
|
+
);
|
|
3381
|
+
}
|
|
3356
3382
|
Logger.debug(
|
|
3357
3383
|
`[AggService] Processing template ${template.id} (${template.name}) for appt ${appointment.id}`
|
|
3358
3384
|
);
|
|
3359
3385
|
const newInstanceRef = this.db.collection(PATIENTS_COLLECTION).doc(appointment.patientId).collection(PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME).doc();
|
|
3386
|
+
Logger.debug(
|
|
3387
|
+
`[AggService] Created doc reference: ${newInstanceRef.path}`
|
|
3388
|
+
);
|
|
3360
3389
|
const instructions = (((_a = template.timeframe) == null ? void 0 : _a.notifyAt) || []).map((notifyAtValue) => {
|
|
3361
3390
|
let dueTime = appointment.appointmentStartTime;
|
|
3362
3391
|
if (template.timeframe && typeof notifyAtValue === "number") {
|
|
@@ -3403,17 +3432,123 @@ var AppointmentAggregationService = class {
|
|
|
3403
3432
|
createdAt: admin10.firestore.FieldValue.serverTimestamp(),
|
|
3404
3433
|
updatedAt: admin10.firestore.FieldValue.serverTimestamp()
|
|
3405
3434
|
};
|
|
3435
|
+
Logger.debug(
|
|
3436
|
+
`[AggService] Setting data for requirement: ${JSON.stringify({
|
|
3437
|
+
id: newInstanceRef.id,
|
|
3438
|
+
patientId: newInstanceData.patientId,
|
|
3439
|
+
appointmentId: newInstanceData.appointmentId,
|
|
3440
|
+
requirementName: newInstanceData.requirementName,
|
|
3441
|
+
instructionsCount: newInstanceData.instructions.length
|
|
3442
|
+
})}`
|
|
3443
|
+
);
|
|
3406
3444
|
batch.set(newInstanceRef, newInstanceData);
|
|
3445
|
+
createdInstances.push({
|
|
3446
|
+
ref: newInstanceRef,
|
|
3447
|
+
data: newInstanceData
|
|
3448
|
+
});
|
|
3407
3449
|
instancesCreatedCount++;
|
|
3408
3450
|
Logger.debug(
|
|
3409
3451
|
`[AggService] Added PatientRequirementInstance ${newInstanceRef.id} to batch for template ${template.id}.`
|
|
3410
3452
|
);
|
|
3411
3453
|
}
|
|
3412
3454
|
if (instancesCreatedCount > 0) {
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3455
|
+
try {
|
|
3456
|
+
await batch.commit();
|
|
3457
|
+
Logger.info(
|
|
3458
|
+
`[AggService] Successfully created ${instancesCreatedCount} PRE_APPOINTMENT requirement instances for appointment ${appointment.id}.`
|
|
3459
|
+
);
|
|
3460
|
+
try {
|
|
3461
|
+
const verifySnapshot = await this.db.collection(PATIENTS_COLLECTION).doc(appointment.patientId).collection(PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME).where("appointmentId", "==", appointment.id).get();
|
|
3462
|
+
if (verifySnapshot.empty) {
|
|
3463
|
+
Logger.warn(
|
|
3464
|
+
`[AggService] Batch commit reported success but documents not found! Attempting direct creation as fallback...`
|
|
3465
|
+
);
|
|
3466
|
+
const fallbackPromises = createdInstances.map(
|
|
3467
|
+
async ({ ref, data }) => {
|
|
3468
|
+
try {
|
|
3469
|
+
await ref.set(data);
|
|
3470
|
+
Logger.info(
|
|
3471
|
+
`[AggService] Fallback direct creation success for ${ref.id}`
|
|
3472
|
+
);
|
|
3473
|
+
return true;
|
|
3474
|
+
} catch (fallbackError) {
|
|
3475
|
+
Logger.error(
|
|
3476
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
3477
|
+
fallbackError
|
|
3478
|
+
);
|
|
3479
|
+
return false;
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
);
|
|
3483
|
+
const fallbackResults = await Promise.allSettled(
|
|
3484
|
+
fallbackPromises
|
|
3485
|
+
);
|
|
3486
|
+
const successCount = fallbackResults.filter(
|
|
3487
|
+
(r) => r.status === "fulfilled" && r.value === true
|
|
3488
|
+
).length;
|
|
3489
|
+
if (successCount > 0) {
|
|
3490
|
+
Logger.info(
|
|
3491
|
+
`[AggService] Fallback mechanism created ${successCount} out of ${createdInstances.length} requirements`
|
|
3492
|
+
);
|
|
3493
|
+
} else {
|
|
3494
|
+
Logger.error(
|
|
3495
|
+
`[AggService] Both batch and fallback mechanisms failed to create requirements`
|
|
3496
|
+
);
|
|
3497
|
+
throw new Error(
|
|
3498
|
+
"Failed to create patient requirements through both batch and direct methods"
|
|
3499
|
+
);
|
|
3500
|
+
}
|
|
3501
|
+
} else {
|
|
3502
|
+
Logger.info(
|
|
3503
|
+
`[AggService] Verification confirmed ${verifySnapshot.size} requirement documents created`
|
|
3504
|
+
);
|
|
3505
|
+
}
|
|
3506
|
+
} catch (verifyError) {
|
|
3507
|
+
Logger.error(
|
|
3508
|
+
`[AggService] Error during verification of created requirements:`,
|
|
3509
|
+
verifyError
|
|
3510
|
+
);
|
|
3511
|
+
}
|
|
3512
|
+
} catch (commitError) {
|
|
3513
|
+
Logger.error(
|
|
3514
|
+
`[AggService] Error committing batch for PRE_APPOINTMENT requirement instances for appointment ${appointment.id}:`,
|
|
3515
|
+
commitError
|
|
3516
|
+
);
|
|
3517
|
+
Logger.info(`[AggService] Attempting direct creation as fallback...`);
|
|
3518
|
+
const fallbackPromises = createdInstances.map(
|
|
3519
|
+
async ({ ref, data }) => {
|
|
3520
|
+
try {
|
|
3521
|
+
await ref.set(data);
|
|
3522
|
+
Logger.info(
|
|
3523
|
+
`[AggService] Fallback direct creation success for ${ref.id}`
|
|
3524
|
+
);
|
|
3525
|
+
return true;
|
|
3526
|
+
} catch (fallbackError) {
|
|
3527
|
+
Logger.error(
|
|
3528
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
3529
|
+
fallbackError
|
|
3530
|
+
);
|
|
3531
|
+
return false;
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
);
|
|
3535
|
+
const fallbackResults = await Promise.allSettled(fallbackPromises);
|
|
3536
|
+
const successCount = fallbackResults.filter(
|
|
3537
|
+
(r) => r.status === "fulfilled" && r.value === true
|
|
3538
|
+
).length;
|
|
3539
|
+
if (successCount > 0) {
|
|
3540
|
+
Logger.info(
|
|
3541
|
+
`[AggService] Fallback mechanism created ${successCount} out of ${createdInstances.length} requirements`
|
|
3542
|
+
);
|
|
3543
|
+
} else {
|
|
3544
|
+
Logger.error(
|
|
3545
|
+
`[AggService] Both batch and fallback mechanisms failed to create requirements`
|
|
3546
|
+
);
|
|
3547
|
+
throw new Error(
|
|
3548
|
+
"Failed to create patient requirements through both batch and direct methods"
|
|
3549
|
+
);
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3417
3552
|
} else {
|
|
3418
3553
|
Logger.info(
|
|
3419
3554
|
`[AggService] No new PRE_APPOINTMENT requirement instances were prepared for batch commit for appointment ${appointment.id}.`
|
|
@@ -3424,6 +3559,7 @@ var AppointmentAggregationService = class {
|
|
|
3424
3559
|
`[AggService] Error creating PRE_APPOINTMENT requirement instances for appointment ${appointment.id}:`,
|
|
3425
3560
|
error
|
|
3426
3561
|
);
|
|
3562
|
+
throw error;
|
|
3427
3563
|
}
|
|
3428
3564
|
}
|
|
3429
3565
|
/**
|
package/dist/admin/index.mjs
CHANGED
|
@@ -3290,18 +3290,47 @@ var AppointmentAggregationService = class {
|
|
|
3290
3290
|
try {
|
|
3291
3291
|
const batch = this.db.batch();
|
|
3292
3292
|
let instancesCreatedCount = 0;
|
|
3293
|
+
let createdInstances = [];
|
|
3294
|
+
Logger.info(
|
|
3295
|
+
`[AggService] Found ${appointment.preProcedureRequirements.length} pre-requirements to process: ${JSON.stringify(
|
|
3296
|
+
appointment.preProcedureRequirements.map((r) => {
|
|
3297
|
+
var _a2, _b;
|
|
3298
|
+
return {
|
|
3299
|
+
id: r.id,
|
|
3300
|
+
name: r.name,
|
|
3301
|
+
type: r.type,
|
|
3302
|
+
isActive: r.isActive,
|
|
3303
|
+
hasTimeframe: !!r.timeframe,
|
|
3304
|
+
notifyAtLength: ((_b = (_a2 = r.timeframe) == null ? void 0 : _a2.notifyAt) == null ? void 0 : _b.length) || 0
|
|
3305
|
+
};
|
|
3306
|
+
})
|
|
3307
|
+
)}`
|
|
3308
|
+
);
|
|
3293
3309
|
for (const template of appointment.preProcedureRequirements) {
|
|
3294
|
-
if (!template)
|
|
3310
|
+
if (!template) {
|
|
3311
|
+
Logger.warn(
|
|
3312
|
+
`[AggService] Found null/undefined template in preProcedureRequirements array`
|
|
3313
|
+
);
|
|
3314
|
+
continue;
|
|
3315
|
+
}
|
|
3295
3316
|
if (template.type !== "pre" /* PRE */ || !template.isActive) {
|
|
3296
3317
|
Logger.debug(
|
|
3297
3318
|
`[AggService] Skipping template ${template.id} (${template.name}): not an active PRE requirement.`
|
|
3298
3319
|
);
|
|
3299
3320
|
continue;
|
|
3300
3321
|
}
|
|
3322
|
+
if (!template.timeframe || !template.timeframe.notifyAt || template.timeframe.notifyAt.length === 0) {
|
|
3323
|
+
Logger.warn(
|
|
3324
|
+
`[AggService] Template ${template.id} (${template.name}) has no timeframe.notifyAt values. Creating with empty instructions.`
|
|
3325
|
+
);
|
|
3326
|
+
}
|
|
3301
3327
|
Logger.debug(
|
|
3302
3328
|
`[AggService] Processing template ${template.id} (${template.name}) for appt ${appointment.id}`
|
|
3303
3329
|
);
|
|
3304
3330
|
const newInstanceRef = this.db.collection(PATIENTS_COLLECTION).doc(appointment.patientId).collection(PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME).doc();
|
|
3331
|
+
Logger.debug(
|
|
3332
|
+
`[AggService] Created doc reference: ${newInstanceRef.path}`
|
|
3333
|
+
);
|
|
3305
3334
|
const instructions = (((_a = template.timeframe) == null ? void 0 : _a.notifyAt) || []).map((notifyAtValue) => {
|
|
3306
3335
|
let dueTime = appointment.appointmentStartTime;
|
|
3307
3336
|
if (template.timeframe && typeof notifyAtValue === "number") {
|
|
@@ -3348,17 +3377,123 @@ var AppointmentAggregationService = class {
|
|
|
3348
3377
|
createdAt: admin10.firestore.FieldValue.serverTimestamp(),
|
|
3349
3378
|
updatedAt: admin10.firestore.FieldValue.serverTimestamp()
|
|
3350
3379
|
};
|
|
3380
|
+
Logger.debug(
|
|
3381
|
+
`[AggService] Setting data for requirement: ${JSON.stringify({
|
|
3382
|
+
id: newInstanceRef.id,
|
|
3383
|
+
patientId: newInstanceData.patientId,
|
|
3384
|
+
appointmentId: newInstanceData.appointmentId,
|
|
3385
|
+
requirementName: newInstanceData.requirementName,
|
|
3386
|
+
instructionsCount: newInstanceData.instructions.length
|
|
3387
|
+
})}`
|
|
3388
|
+
);
|
|
3351
3389
|
batch.set(newInstanceRef, newInstanceData);
|
|
3390
|
+
createdInstances.push({
|
|
3391
|
+
ref: newInstanceRef,
|
|
3392
|
+
data: newInstanceData
|
|
3393
|
+
});
|
|
3352
3394
|
instancesCreatedCount++;
|
|
3353
3395
|
Logger.debug(
|
|
3354
3396
|
`[AggService] Added PatientRequirementInstance ${newInstanceRef.id} to batch for template ${template.id}.`
|
|
3355
3397
|
);
|
|
3356
3398
|
}
|
|
3357
3399
|
if (instancesCreatedCount > 0) {
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3400
|
+
try {
|
|
3401
|
+
await batch.commit();
|
|
3402
|
+
Logger.info(
|
|
3403
|
+
`[AggService] Successfully created ${instancesCreatedCount} PRE_APPOINTMENT requirement instances for appointment ${appointment.id}.`
|
|
3404
|
+
);
|
|
3405
|
+
try {
|
|
3406
|
+
const verifySnapshot = await this.db.collection(PATIENTS_COLLECTION).doc(appointment.patientId).collection(PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME).where("appointmentId", "==", appointment.id).get();
|
|
3407
|
+
if (verifySnapshot.empty) {
|
|
3408
|
+
Logger.warn(
|
|
3409
|
+
`[AggService] Batch commit reported success but documents not found! Attempting direct creation as fallback...`
|
|
3410
|
+
);
|
|
3411
|
+
const fallbackPromises = createdInstances.map(
|
|
3412
|
+
async ({ ref, data }) => {
|
|
3413
|
+
try {
|
|
3414
|
+
await ref.set(data);
|
|
3415
|
+
Logger.info(
|
|
3416
|
+
`[AggService] Fallback direct creation success for ${ref.id}`
|
|
3417
|
+
);
|
|
3418
|
+
return true;
|
|
3419
|
+
} catch (fallbackError) {
|
|
3420
|
+
Logger.error(
|
|
3421
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
3422
|
+
fallbackError
|
|
3423
|
+
);
|
|
3424
|
+
return false;
|
|
3425
|
+
}
|
|
3426
|
+
}
|
|
3427
|
+
);
|
|
3428
|
+
const fallbackResults = await Promise.allSettled(
|
|
3429
|
+
fallbackPromises
|
|
3430
|
+
);
|
|
3431
|
+
const successCount = fallbackResults.filter(
|
|
3432
|
+
(r) => r.status === "fulfilled" && r.value === true
|
|
3433
|
+
).length;
|
|
3434
|
+
if (successCount > 0) {
|
|
3435
|
+
Logger.info(
|
|
3436
|
+
`[AggService] Fallback mechanism created ${successCount} out of ${createdInstances.length} requirements`
|
|
3437
|
+
);
|
|
3438
|
+
} else {
|
|
3439
|
+
Logger.error(
|
|
3440
|
+
`[AggService] Both batch and fallback mechanisms failed to create requirements`
|
|
3441
|
+
);
|
|
3442
|
+
throw new Error(
|
|
3443
|
+
"Failed to create patient requirements through both batch and direct methods"
|
|
3444
|
+
);
|
|
3445
|
+
}
|
|
3446
|
+
} else {
|
|
3447
|
+
Logger.info(
|
|
3448
|
+
`[AggService] Verification confirmed ${verifySnapshot.size} requirement documents created`
|
|
3449
|
+
);
|
|
3450
|
+
}
|
|
3451
|
+
} catch (verifyError) {
|
|
3452
|
+
Logger.error(
|
|
3453
|
+
`[AggService] Error during verification of created requirements:`,
|
|
3454
|
+
verifyError
|
|
3455
|
+
);
|
|
3456
|
+
}
|
|
3457
|
+
} catch (commitError) {
|
|
3458
|
+
Logger.error(
|
|
3459
|
+
`[AggService] Error committing batch for PRE_APPOINTMENT requirement instances for appointment ${appointment.id}:`,
|
|
3460
|
+
commitError
|
|
3461
|
+
);
|
|
3462
|
+
Logger.info(`[AggService] Attempting direct creation as fallback...`);
|
|
3463
|
+
const fallbackPromises = createdInstances.map(
|
|
3464
|
+
async ({ ref, data }) => {
|
|
3465
|
+
try {
|
|
3466
|
+
await ref.set(data);
|
|
3467
|
+
Logger.info(
|
|
3468
|
+
`[AggService] Fallback direct creation success for ${ref.id}`
|
|
3469
|
+
);
|
|
3470
|
+
return true;
|
|
3471
|
+
} catch (fallbackError) {
|
|
3472
|
+
Logger.error(
|
|
3473
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
3474
|
+
fallbackError
|
|
3475
|
+
);
|
|
3476
|
+
return false;
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
);
|
|
3480
|
+
const fallbackResults = await Promise.allSettled(fallbackPromises);
|
|
3481
|
+
const successCount = fallbackResults.filter(
|
|
3482
|
+
(r) => r.status === "fulfilled" && r.value === true
|
|
3483
|
+
).length;
|
|
3484
|
+
if (successCount > 0) {
|
|
3485
|
+
Logger.info(
|
|
3486
|
+
`[AggService] Fallback mechanism created ${successCount} out of ${createdInstances.length} requirements`
|
|
3487
|
+
);
|
|
3488
|
+
} else {
|
|
3489
|
+
Logger.error(
|
|
3490
|
+
`[AggService] Both batch and fallback mechanisms failed to create requirements`
|
|
3491
|
+
);
|
|
3492
|
+
throw new Error(
|
|
3493
|
+
"Failed to create patient requirements through both batch and direct methods"
|
|
3494
|
+
);
|
|
3495
|
+
}
|
|
3496
|
+
}
|
|
3362
3497
|
} else {
|
|
3363
3498
|
Logger.info(
|
|
3364
3499
|
`[AggService] No new PRE_APPOINTMENT requirement instances were prepared for batch commit for appointment ${appointment.id}.`
|
|
@@ -3369,6 +3504,7 @@ var AppointmentAggregationService = class {
|
|
|
3369
3504
|
`[AggService] Error creating PRE_APPOINTMENT requirement instances for appointment ${appointment.id}:`,
|
|
3370
3505
|
error
|
|
3371
3506
|
);
|
|
3507
|
+
throw error;
|
|
3372
3508
|
}
|
|
3373
3509
|
}
|
|
3374
3510
|
/**
|
package/package.json
CHANGED
|
@@ -507,9 +507,32 @@ export class AppointmentAggregationService {
|
|
|
507
507
|
try {
|
|
508
508
|
const batch = this.db.batch();
|
|
509
509
|
let instancesCreatedCount = 0;
|
|
510
|
+
// Store created instances for fallback direct creation if needed
|
|
511
|
+
let createdInstances = [];
|
|
512
|
+
|
|
513
|
+
// Log more details about the pre-requirements
|
|
514
|
+
Logger.info(
|
|
515
|
+
`[AggService] Found ${
|
|
516
|
+
appointment.preProcedureRequirements.length
|
|
517
|
+
} pre-requirements to process: ${JSON.stringify(
|
|
518
|
+
appointment.preProcedureRequirements.map((r) => ({
|
|
519
|
+
id: r.id,
|
|
520
|
+
name: r.name,
|
|
521
|
+
type: r.type,
|
|
522
|
+
isActive: r.isActive,
|
|
523
|
+
hasTimeframe: !!r.timeframe,
|
|
524
|
+
notifyAtLength: r.timeframe?.notifyAt?.length || 0,
|
|
525
|
+
}))
|
|
526
|
+
)}`
|
|
527
|
+
);
|
|
510
528
|
|
|
511
529
|
for (const template of appointment.preProcedureRequirements) {
|
|
512
|
-
if (!template)
|
|
530
|
+
if (!template) {
|
|
531
|
+
Logger.warn(
|
|
532
|
+
`[AggService] Found null/undefined template in preProcedureRequirements array`
|
|
533
|
+
);
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
513
536
|
|
|
514
537
|
// Ensure it's an active, PRE-type requirement
|
|
515
538
|
if (template.type !== RequirementType.PRE || !template.isActive) {
|
|
@@ -519,6 +542,16 @@ export class AppointmentAggregationService {
|
|
|
519
542
|
continue;
|
|
520
543
|
}
|
|
521
544
|
|
|
545
|
+
if (
|
|
546
|
+
!template.timeframe ||
|
|
547
|
+
!template.timeframe.notifyAt ||
|
|
548
|
+
template.timeframe.notifyAt.length === 0
|
|
549
|
+
) {
|
|
550
|
+
Logger.warn(
|
|
551
|
+
`[AggService] Template ${template.id} (${template.name}) has no timeframe.notifyAt values. Creating with empty instructions.`
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
|
|
522
555
|
Logger.debug(
|
|
523
556
|
`[AggService] Processing template ${template.id} (${template.name}) for appt ${appointment.id}`
|
|
524
557
|
);
|
|
@@ -529,6 +562,11 @@ export class AppointmentAggregationService {
|
|
|
529
562
|
.collection(PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME)
|
|
530
563
|
.doc(); // Auto-generate ID for the new instance
|
|
531
564
|
|
|
565
|
+
// Log the path for debugging
|
|
566
|
+
Logger.debug(
|
|
567
|
+
`[AggService] Created doc reference: ${newInstanceRef.path}`
|
|
568
|
+
);
|
|
569
|
+
|
|
532
570
|
const instructions: PatientRequirementInstruction[] = (
|
|
533
571
|
template.timeframe?.notifyAt || []
|
|
534
572
|
).map((notifyAtValue) => {
|
|
@@ -585,7 +623,24 @@ export class AppointmentAggregationService {
|
|
|
585
623
|
updatedAt: admin.firestore.FieldValue.serverTimestamp() as any,
|
|
586
624
|
};
|
|
587
625
|
|
|
626
|
+
// Log the data being set
|
|
627
|
+
Logger.debug(
|
|
628
|
+
`[AggService] Setting data for requirement: ${JSON.stringify({
|
|
629
|
+
id: newInstanceRef.id,
|
|
630
|
+
patientId: newInstanceData.patientId,
|
|
631
|
+
appointmentId: newInstanceData.appointmentId,
|
|
632
|
+
requirementName: newInstanceData.requirementName,
|
|
633
|
+
instructionsCount: newInstanceData.instructions.length,
|
|
634
|
+
})}`
|
|
635
|
+
);
|
|
636
|
+
|
|
588
637
|
batch.set(newInstanceRef, newInstanceData);
|
|
638
|
+
// Store for potential fallback
|
|
639
|
+
createdInstances.push({
|
|
640
|
+
ref: newInstanceRef,
|
|
641
|
+
data: newInstanceData,
|
|
642
|
+
});
|
|
643
|
+
|
|
589
644
|
instancesCreatedCount++;
|
|
590
645
|
Logger.debug(
|
|
591
646
|
`[AggService] Added PatientRequirementInstance ${newInstanceRef.id} to batch for template ${template.id}.`
|
|
@@ -593,10 +648,119 @@ export class AppointmentAggregationService {
|
|
|
593
648
|
}
|
|
594
649
|
|
|
595
650
|
if (instancesCreatedCount > 0) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
651
|
+
try {
|
|
652
|
+
await batch.commit();
|
|
653
|
+
Logger.info(
|
|
654
|
+
`[AggService] Successfully created ${instancesCreatedCount} PRE_APPOINTMENT requirement instances for appointment ${appointment.id}.`
|
|
655
|
+
);
|
|
656
|
+
|
|
657
|
+
// Verify creation success
|
|
658
|
+
try {
|
|
659
|
+
const verifySnapshot = await this.db
|
|
660
|
+
.collection(PATIENTS_COLLECTION)
|
|
661
|
+
.doc(appointment.patientId)
|
|
662
|
+
.collection(PATIENT_REQUIREMENTS_SUBCOLLECTION_NAME)
|
|
663
|
+
.where("appointmentId", "==", appointment.id)
|
|
664
|
+
.get();
|
|
665
|
+
|
|
666
|
+
if (verifySnapshot.empty) {
|
|
667
|
+
Logger.warn(
|
|
668
|
+
`[AggService] Batch commit reported success but documents not found! Attempting direct creation as fallback...`
|
|
669
|
+
);
|
|
670
|
+
|
|
671
|
+
// Fallback to direct creation if batch worked but docs aren't there
|
|
672
|
+
const fallbackPromises = createdInstances.map(
|
|
673
|
+
async ({ ref, data }) => {
|
|
674
|
+
try {
|
|
675
|
+
await ref.set(data);
|
|
676
|
+
Logger.info(
|
|
677
|
+
`[AggService] Fallback direct creation success for ${ref.id}`
|
|
678
|
+
);
|
|
679
|
+
return true;
|
|
680
|
+
} catch (fallbackError) {
|
|
681
|
+
Logger.error(
|
|
682
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
683
|
+
fallbackError
|
|
684
|
+
);
|
|
685
|
+
return false;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
);
|
|
689
|
+
|
|
690
|
+
const fallbackResults = await Promise.allSettled(
|
|
691
|
+
fallbackPromises
|
|
692
|
+
);
|
|
693
|
+
const successCount = fallbackResults.filter(
|
|
694
|
+
(r) => r.status === "fulfilled" && r.value === true
|
|
695
|
+
).length;
|
|
696
|
+
|
|
697
|
+
if (successCount > 0) {
|
|
698
|
+
Logger.info(
|
|
699
|
+
`[AggService] Fallback mechanism created ${successCount} out of ${createdInstances.length} requirements`
|
|
700
|
+
);
|
|
701
|
+
} else {
|
|
702
|
+
Logger.error(
|
|
703
|
+
`[AggService] Both batch and fallback mechanisms failed to create requirements`
|
|
704
|
+
);
|
|
705
|
+
throw new Error(
|
|
706
|
+
"Failed to create patient requirements through both batch and direct methods"
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
} else {
|
|
710
|
+
Logger.info(
|
|
711
|
+
`[AggService] Verification confirmed ${verifySnapshot.size} requirement documents created`
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
} catch (verifyError) {
|
|
715
|
+
Logger.error(
|
|
716
|
+
`[AggService] Error during verification of created requirements:`,
|
|
717
|
+
verifyError
|
|
718
|
+
);
|
|
719
|
+
}
|
|
720
|
+
} catch (commitError) {
|
|
721
|
+
Logger.error(
|
|
722
|
+
`[AggService] Error committing batch for PRE_APPOINTMENT requirement instances for appointment ${appointment.id}:`,
|
|
723
|
+
commitError
|
|
724
|
+
);
|
|
725
|
+
|
|
726
|
+
// Try direct creation as fallback
|
|
727
|
+
Logger.info(`[AggService] Attempting direct creation as fallback...`);
|
|
728
|
+
const fallbackPromises = createdInstances.map(
|
|
729
|
+
async ({ ref, data }) => {
|
|
730
|
+
try {
|
|
731
|
+
await ref.set(data);
|
|
732
|
+
Logger.info(
|
|
733
|
+
`[AggService] Fallback direct creation success for ${ref.id}`
|
|
734
|
+
);
|
|
735
|
+
return true;
|
|
736
|
+
} catch (fallbackError) {
|
|
737
|
+
Logger.error(
|
|
738
|
+
`[AggService] Fallback direct creation failed for ${ref.id}:`,
|
|
739
|
+
fallbackError
|
|
740
|
+
);
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
);
|
|
745
|
+
|
|
746
|
+
const fallbackResults = await Promise.allSettled(fallbackPromises);
|
|
747
|
+
const successCount = fallbackResults.filter(
|
|
748
|
+
(r) => r.status === "fulfilled" && r.value === true
|
|
749
|
+
).length;
|
|
750
|
+
|
|
751
|
+
if (successCount > 0) {
|
|
752
|
+
Logger.info(
|
|
753
|
+
`[AggService] Fallback mechanism created ${successCount} out of ${createdInstances.length} requirements`
|
|
754
|
+
);
|
|
755
|
+
} else {
|
|
756
|
+
Logger.error(
|
|
757
|
+
`[AggService] Both batch and fallback mechanisms failed to create requirements`
|
|
758
|
+
);
|
|
759
|
+
throw new Error(
|
|
760
|
+
"Failed to create patient requirements through both batch and direct methods"
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
600
764
|
} else {
|
|
601
765
|
Logger.info(
|
|
602
766
|
`[AggService] No new PRE_APPOINTMENT requirement instances were prepared for batch commit for appointment ${appointment.id}.`
|
|
@@ -607,8 +771,7 @@ export class AppointmentAggregationService {
|
|
|
607
771
|
`[AggService] Error creating PRE_APPOINTMENT requirement instances for appointment ${appointment.id}:`,
|
|
608
772
|
error
|
|
609
773
|
);
|
|
610
|
-
|
|
611
|
-
// For now, just logging.
|
|
774
|
+
throw error; // Re-throw to ensure the caller knows there was a problem
|
|
612
775
|
}
|
|
613
776
|
}
|
|
614
777
|
|