@blackcode_sa/metaestetics-api 1.14.56 → 1.14.58
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.d.mts +9 -2
- package/dist/admin/index.d.ts +9 -2
- package/dist/admin/index.js +366 -2
- package/dist/admin/index.mjs +366 -2
- package/dist/index.d.mts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +195 -42
- package/dist/index.mjs +324 -168
- package/package.json +1 -1
- package/src/admin/mailing/appointment/appointment.mailing.service.ts +383 -2
- package/src/services/appointment/appointment.service.ts +41 -9
- package/src/services/appointment/utils/extended-procedure.utils.ts +1 -0
- package/src/services/appointment/utils/form-initialization.utils.ts +2 -0
- package/src/services/appointment/utils/zone-management.utils.ts +50 -3
- package/src/services/appointment/utils/zone-photo.utils.ts +39 -1
- package/src/services/procedure/procedure.service.ts +137 -40
- package/src/types/appointment/index.ts +4 -2
- package/src/validations/appointment.schema.ts +2 -1
package/dist/index.js
CHANGED
|
@@ -3970,7 +3970,10 @@ var zoneItemDataSchema = import_zod3.z.object({
|
|
|
3970
3970
|
notes: import_zod3.z.string().max(MAX_STRING_LENGTH_LONG, "Notes too long").optional(),
|
|
3971
3971
|
notesVisibleToPatient: import_zod3.z.boolean().optional().default(false),
|
|
3972
3972
|
subtotal: import_zod3.z.number().min(0, "Subtotal must be non-negative").optional(),
|
|
3973
|
-
ionNumber: import_zod3.z.string().optional(),
|
|
3973
|
+
ionNumber: import_zod3.z.string().nullable().optional(),
|
|
3974
|
+
// Batch/Lot number - can be null to clear/delete
|
|
3975
|
+
expiryDate: import_zod3.z.string().nullable().optional(),
|
|
3976
|
+
// ISO date string (YYYY-MM-DD) - can be null to clear/delete
|
|
3974
3977
|
createdAt: import_zod3.z.string().optional(),
|
|
3975
3978
|
updatedAt: import_zod3.z.string().optional()
|
|
3976
3979
|
}).refine(
|
|
@@ -4900,6 +4903,7 @@ async function removeItemFromZoneUtil(db, appointmentId, zoneId, itemIndex) {
|
|
|
4900
4903
|
return getAppointmentOrThrow(db, appointmentId);
|
|
4901
4904
|
}
|
|
4902
4905
|
async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates) {
|
|
4906
|
+
var _a, _b, _c, _d;
|
|
4903
4907
|
validateZoneKeyFormat(zoneId);
|
|
4904
4908
|
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
4905
4909
|
const metadata = initializeMetadata(appointment);
|
|
@@ -4910,17 +4914,37 @@ async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates)
|
|
|
4910
4914
|
if (itemIndex < 0 || itemIndex >= items.length) {
|
|
4911
4915
|
throw new Error(`Invalid item index ${itemIndex} for zone ${zoneId}`);
|
|
4912
4916
|
}
|
|
4917
|
+
const cleanUpdates = Object.fromEntries(
|
|
4918
|
+
Object.entries(updates).filter(([_, value]) => value !== void 0).map(([key, value]) => [
|
|
4919
|
+
key,
|
|
4920
|
+
value === "" ? null : value
|
|
4921
|
+
// Convert empty strings to null
|
|
4922
|
+
])
|
|
4923
|
+
);
|
|
4924
|
+
console.log(`[updateZoneItemUtil] Updates received:`, {
|
|
4925
|
+
itemIndex,
|
|
4926
|
+
zoneId,
|
|
4927
|
+
rawUpdates: updates,
|
|
4928
|
+
cleanUpdates,
|
|
4929
|
+
hasIonNumber: "ionNumber" in cleanUpdates,
|
|
4930
|
+
hasExpiryDate: "expiryDate" in cleanUpdates,
|
|
4931
|
+
ionNumberValue: cleanUpdates.ionNumber,
|
|
4932
|
+
expiryDateValue: cleanUpdates.expiryDate
|
|
4933
|
+
});
|
|
4913
4934
|
items[itemIndex] = {
|
|
4914
4935
|
...items[itemIndex],
|
|
4915
|
-
...
|
|
4936
|
+
...cleanUpdates,
|
|
4916
4937
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4917
4938
|
};
|
|
4918
|
-
console.log(`[updateZoneItemUtil]
|
|
4939
|
+
console.log(`[updateZoneItemUtil] Item after update:`, {
|
|
4919
4940
|
itemIndex,
|
|
4941
|
+
ionNumber: items[itemIndex].ionNumber,
|
|
4942
|
+
expiryDate: items[itemIndex].expiryDate,
|
|
4920
4943
|
quantity: items[itemIndex].quantity,
|
|
4921
4944
|
priceOverrideAmount: items[itemIndex].priceOverrideAmount,
|
|
4922
4945
|
price: items[itemIndex].price,
|
|
4923
|
-
oldSubtotal: items[itemIndex].subtotal
|
|
4946
|
+
oldSubtotal: items[itemIndex].subtotal,
|
|
4947
|
+
allItemKeys: Object.keys(items[itemIndex])
|
|
4924
4948
|
});
|
|
4925
4949
|
items[itemIndex].subtotal = calculateItemSubtotal(items[itemIndex]);
|
|
4926
4950
|
console.log(`[updateZoneItemUtil] AFTER recalculation:`, {
|
|
@@ -4928,13 +4952,30 @@ async function updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, updates)
|
|
|
4928
4952
|
newSubtotal: items[itemIndex].subtotal
|
|
4929
4953
|
});
|
|
4930
4954
|
const finalbilling = calculateFinalBilling(metadata.zonesData, 0.081);
|
|
4955
|
+
console.log(`[updateZoneItemUtil] Saving to Firestore:`, {
|
|
4956
|
+
appointmentId,
|
|
4957
|
+
zoneId,
|
|
4958
|
+
itemIndex,
|
|
4959
|
+
itemToSave: items[itemIndex],
|
|
4960
|
+
itemIonNumber: items[itemIndex].ionNumber,
|
|
4961
|
+
itemExpiryDate: items[itemIndex].expiryDate,
|
|
4962
|
+
zonesDataKeys: Object.keys(metadata.zonesData),
|
|
4963
|
+
zoneItemsCount: (_a = metadata.zonesData[zoneId]) == null ? void 0 : _a.length
|
|
4964
|
+
});
|
|
4931
4965
|
const appointmentRef = (0, import_firestore8.doc)(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
4932
4966
|
await (0, import_firestore7.updateDoc)(appointmentRef, {
|
|
4933
4967
|
"metadata.zonesData": metadata.zonesData,
|
|
4934
4968
|
"metadata.finalbilling": finalbilling,
|
|
4935
4969
|
updatedAt: (0, import_firestore7.serverTimestamp)()
|
|
4936
4970
|
});
|
|
4937
|
-
|
|
4971
|
+
const savedAppointment = await getAppointmentOrThrow(db, appointmentId);
|
|
4972
|
+
const savedItem = (_d = (_c = (_b = savedAppointment.metadata) == null ? void 0 : _b.zonesData) == null ? void 0 : _c[zoneId]) == null ? void 0 : _d[itemIndex];
|
|
4973
|
+
console.log(`[updateZoneItemUtil] Verification after save:`, {
|
|
4974
|
+
savedItemIonNumber: savedItem == null ? void 0 : savedItem.ionNumber,
|
|
4975
|
+
savedItemExpiryDate: savedItem == null ? void 0 : savedItem.expiryDate,
|
|
4976
|
+
savedItemKeys: savedItem ? Object.keys(savedItem) : []
|
|
4977
|
+
});
|
|
4978
|
+
return savedAppointment;
|
|
4938
4979
|
}
|
|
4939
4980
|
async function overridePriceForZoneItemUtil(db, appointmentId, zoneId, itemIndex, newPrice) {
|
|
4940
4981
|
return updateZoneItemUtil(db, appointmentId, zoneId, itemIndex, {
|
|
@@ -5064,7 +5105,9 @@ async function initializeFormsForExtendedProcedure(db, appointmentId, procedureI
|
|
|
5064
5105
|
isRequired,
|
|
5065
5106
|
sortingOrder: templateRef.sortingOrder,
|
|
5066
5107
|
status: existingForm.status || "pending" /* PENDING */,
|
|
5067
|
-
path: `${APPOINTMENTS_COLLECTION}/${appointmentId}/${formSubcollectionPath}/${existingForm.id}
|
|
5108
|
+
path: `${APPOINTMENTS_COLLECTION}/${appointmentId}/${formSubcollectionPath}/${existingForm.id}`,
|
|
5109
|
+
procedureId
|
|
5110
|
+
// Track which procedure this form belongs to
|
|
5068
5111
|
};
|
|
5069
5112
|
initializedFormsInfo.push(linkedForm);
|
|
5070
5113
|
if (!allLinkedFormIds.includes(existingForm.id)) {
|
|
@@ -5118,7 +5161,9 @@ async function initializeFormsForExtendedProcedure(db, appointmentId, procedureI
|
|
|
5118
5161
|
isRequired,
|
|
5119
5162
|
sortingOrder: templateRef.sortingOrder,
|
|
5120
5163
|
status: "pending" /* PENDING */,
|
|
5121
|
-
path: docRef.path
|
|
5164
|
+
path: docRef.path,
|
|
5165
|
+
procedureId
|
|
5166
|
+
// Track which procedure this form belongs to
|
|
5122
5167
|
};
|
|
5123
5168
|
initializedFormsInfo.push(linkedForm);
|
|
5124
5169
|
const formType = isProcedureSpecific ? "procedure-specific" : "general/shared";
|
|
@@ -5311,6 +5356,7 @@ async function createExtendedProcedureInfo(db, procedureId) {
|
|
|
5311
5356
|
procedureId,
|
|
5312
5357
|
procedureName: data.name,
|
|
5313
5358
|
procedureDescription: data.description || "",
|
|
5359
|
+
procedurePrice: data.price || 0,
|
|
5314
5360
|
procedureFamily: data.family,
|
|
5315
5361
|
// Use embedded family object
|
|
5316
5362
|
procedureCategoryId: data.category.id,
|
|
@@ -5638,16 +5684,37 @@ async function getZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex) {
|
|
|
5638
5684
|
return zoneArray[photoIndex];
|
|
5639
5685
|
}
|
|
5640
5686
|
async function updateZonePhotoVisibilityUtil(db, appointmentId, zoneId, photoIndex, showToPatient, doctorId) {
|
|
5687
|
+
const updates = { showToPatient };
|
|
5688
|
+
if (!showToPatient) {
|
|
5689
|
+
updates.beforeNoteVisibleToPatient = false;
|
|
5690
|
+
updates.afterNoteVisibleToPatient = false;
|
|
5691
|
+
}
|
|
5641
5692
|
return updateZonePhotoEntryUtil(
|
|
5642
5693
|
db,
|
|
5643
5694
|
appointmentId,
|
|
5644
5695
|
zoneId,
|
|
5645
5696
|
photoIndex,
|
|
5646
|
-
|
|
5697
|
+
updates,
|
|
5647
5698
|
doctorId
|
|
5648
5699
|
);
|
|
5649
5700
|
}
|
|
5650
5701
|
async function updateZonePhotoNoteVisibilityUtil(db, appointmentId, zoneId, photoIndex, noteType, visibleToPatient, doctorId) {
|
|
5702
|
+
var _a;
|
|
5703
|
+
const appointment = await getAppointmentOrThrow(db, appointmentId);
|
|
5704
|
+
const zonePhotos = (_a = appointment.metadata) == null ? void 0 : _a.zonePhotos;
|
|
5705
|
+
if (!zonePhotos || !zonePhotos[zoneId] || !Array.isArray(zonePhotos[zoneId])) {
|
|
5706
|
+
throw new Error(`No photos found for zone ${zoneId} in appointment ${appointmentId}`);
|
|
5707
|
+
}
|
|
5708
|
+
const zoneArray = zonePhotos[zoneId];
|
|
5709
|
+
if (photoIndex < 0 || photoIndex >= zoneArray.length) {
|
|
5710
|
+
throw new Error(`Invalid photo index ${photoIndex} for zone ${zoneId}. Must be between 0 and ${zoneArray.length - 1}`);
|
|
5711
|
+
}
|
|
5712
|
+
const photoEntry = zoneArray[photoIndex];
|
|
5713
|
+
if (visibleToPatient && !photoEntry.showToPatient) {
|
|
5714
|
+
throw new Error(
|
|
5715
|
+
'Cannot make note visible to patient: The photo pair must be visible to the patient first. Please enable "Show to Patient" for the photo pair before making notes visible.'
|
|
5716
|
+
);
|
|
5717
|
+
}
|
|
5651
5718
|
const updates = noteType === "before" ? { beforeNoteVisibleToPatient: visibleToPatient } : { afterNoteVisibleToPatient: visibleToPatient };
|
|
5652
5719
|
return updateZonePhotoEntryUtil(db, appointmentId, zoneId, photoIndex, updates, doctorId);
|
|
5653
5720
|
}
|
|
@@ -7291,6 +7358,8 @@ var AppointmentService = class extends BaseService {
|
|
|
7291
7358
|
finalizationNotesInternal: currentMetadata.finalizationNotesInternal,
|
|
7292
7359
|
finalizationNotes: currentMetadata.finalizationNotes
|
|
7293
7360
|
});
|
|
7361
|
+
const normalizedSharedNotes = sharedNotes !== void 0 ? sharedNotes === "" || sharedNotes === null ? null : sharedNotes : currentMetadata.finalizationNotesShared;
|
|
7362
|
+
const normalizedInternalNotes = internalNotes !== void 0 ? internalNotes === "" || internalNotes === null ? null : internalNotes : currentMetadata.finalizationNotesInternal;
|
|
7294
7363
|
const metadataUpdate = {
|
|
7295
7364
|
selectedZones: currentMetadata.selectedZones,
|
|
7296
7365
|
zonePhotos: currentMetadata.zonePhotos,
|
|
@@ -7299,21 +7368,38 @@ var AppointmentService = class extends BaseService {
|
|
|
7299
7368
|
extendedProcedures: currentMetadata.extendedProcedures || [],
|
|
7300
7369
|
recommendedProcedures: currentMetadata.recommendedProcedures || [],
|
|
7301
7370
|
finalbilling: currentMetadata.finalbilling,
|
|
7302
|
-
finalizationNotesShared:
|
|
7303
|
-
finalizationNotesInternal:
|
|
7371
|
+
finalizationNotesShared: normalizedSharedNotes,
|
|
7372
|
+
finalizationNotesInternal: normalizedInternalNotes,
|
|
7304
7373
|
// Keep deprecated field for backward compatibility during migration
|
|
7305
|
-
finalizationNotes:
|
|
7374
|
+
finalizationNotes: normalizedSharedNotes !== null && normalizedSharedNotes !== void 0 ? normalizedSharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared
|
|
7306
7375
|
};
|
|
7307
7376
|
console.log("\u{1F50D} [APPOINTMENT_SERVICE] Update data metadata:", {
|
|
7308
7377
|
finalizationNotesShared: metadataUpdate.finalizationNotesShared,
|
|
7309
7378
|
finalizationNotesInternal: metadataUpdate.finalizationNotesInternal,
|
|
7310
|
-
finalizationNotes: metadataUpdate.finalizationNotes
|
|
7379
|
+
finalizationNotes: metadataUpdate.finalizationNotes,
|
|
7380
|
+
normalizedSharedNotes,
|
|
7381
|
+
normalizedInternalNotes
|
|
7311
7382
|
});
|
|
7312
|
-
const
|
|
7313
|
-
|
|
7383
|
+
const appointmentRef = (0, import_firestore14.doc)(this.db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
7384
|
+
const updateFields = {
|
|
7385
|
+
"metadata.finalizationNotesShared": normalizedSharedNotes,
|
|
7386
|
+
"metadata.finalizationNotesInternal": normalizedInternalNotes,
|
|
7387
|
+
"metadata.finalizationNotes": normalizedSharedNotes !== null && normalizedSharedNotes !== void 0 ? normalizedSharedNotes : currentMetadata.finalizationNotes || currentMetadata.finalizationNotesShared,
|
|
7314
7388
|
updatedAt: (0, import_firestore14.serverTimestamp)()
|
|
7315
7389
|
};
|
|
7316
|
-
|
|
7390
|
+
console.log("\u{1F50D} [APPOINTMENT_SERVICE] Direct Firestore update with dot notation:", {
|
|
7391
|
+
appointmentId,
|
|
7392
|
+
updateFields: {
|
|
7393
|
+
"metadata.finalizationNotesShared": updateFields["metadata.finalizationNotesShared"],
|
|
7394
|
+
"metadata.finalizationNotesInternal": updateFields["metadata.finalizationNotesInternal"],
|
|
7395
|
+
"metadata.finalizationNotes": updateFields["metadata.finalizationNotes"]
|
|
7396
|
+
}
|
|
7397
|
+
});
|
|
7398
|
+
await (0, import_firestore14.updateDoc)(appointmentRef, updateFields);
|
|
7399
|
+
const result = await this.getAppointmentById(appointmentId);
|
|
7400
|
+
if (!result) {
|
|
7401
|
+
throw new Error(`Failed to retrieve updated appointment ${appointmentId}`);
|
|
7402
|
+
}
|
|
7317
7403
|
console.log("\u{1F50D} [APPOINTMENT_SERVICE] After update, result metadata:", {
|
|
7318
7404
|
finalizationNotesShared: (_a = result.metadata) == null ? void 0 : _a.finalizationNotesShared,
|
|
7319
7405
|
finalizationNotesInternal: (_b = result.metadata) == null ? void 0 : _b.finalizationNotesInternal,
|
|
@@ -22515,10 +22601,72 @@ var ProcedureService = class extends BaseService {
|
|
|
22515
22601
|
throw error;
|
|
22516
22602
|
}
|
|
22517
22603
|
}
|
|
22604
|
+
/**
|
|
22605
|
+
* Creates a serializable cursor from a DocumentSnapshot or returns the cursor values.
|
|
22606
|
+
* This format can be passed through React Native state/Redux without losing data.
|
|
22607
|
+
*
|
|
22608
|
+
* @param doc - The Firestore DocumentSnapshot
|
|
22609
|
+
* @param orderByField - The field used in orderBy clause
|
|
22610
|
+
* @returns Serializable cursor object with values needed for startAfter
|
|
22611
|
+
*/
|
|
22612
|
+
createSerializableCursor(doc47, orderByField = "createdAt") {
|
|
22613
|
+
if (!doc47) return null;
|
|
22614
|
+
const data = typeof doc47.data === "function" ? doc47.data() : doc47;
|
|
22615
|
+
const docId = doc47.id || (data == null ? void 0 : data.id);
|
|
22616
|
+
if (!docId) return null;
|
|
22617
|
+
let orderByValue = data == null ? void 0 : data[orderByField];
|
|
22618
|
+
if (orderByValue && typeof orderByValue.toDate === "function") {
|
|
22619
|
+
orderByValue = orderByValue.toMillis();
|
|
22620
|
+
} else if (orderByValue && orderByValue.seconds) {
|
|
22621
|
+
orderByValue = orderByValue.seconds * 1e3 + (orderByValue.nanoseconds || 0) / 1e6;
|
|
22622
|
+
}
|
|
22623
|
+
return {
|
|
22624
|
+
__cursor: true,
|
|
22625
|
+
values: [orderByValue],
|
|
22626
|
+
id: docId,
|
|
22627
|
+
orderByField
|
|
22628
|
+
};
|
|
22629
|
+
}
|
|
22630
|
+
/**
|
|
22631
|
+
* Converts a serializable cursor back to values for startAfter.
|
|
22632
|
+
* Handles both native DocumentSnapshots and serialized cursor objects.
|
|
22633
|
+
*
|
|
22634
|
+
* @param lastDoc - Either a DocumentSnapshot or a serializable cursor object
|
|
22635
|
+
* @param orderByField - The field used in orderBy clause (for validation)
|
|
22636
|
+
* @returns Values to spread into startAfter, or null if invalid
|
|
22637
|
+
*/
|
|
22638
|
+
getCursorValuesForStartAfter(lastDoc, orderByField = "createdAt") {
|
|
22639
|
+
if (!lastDoc) return null;
|
|
22640
|
+
if (typeof lastDoc.data === "function") {
|
|
22641
|
+
return [lastDoc];
|
|
22642
|
+
}
|
|
22643
|
+
if (lastDoc.__cursor && Array.isArray(lastDoc.values)) {
|
|
22644
|
+
if (orderByField === "createdAt" && typeof lastDoc.values[0] === "number") {
|
|
22645
|
+
const timestamp = import_firestore58.Timestamp.fromMillis(lastDoc.values[0]);
|
|
22646
|
+
return [timestamp];
|
|
22647
|
+
}
|
|
22648
|
+
return lastDoc.values;
|
|
22649
|
+
}
|
|
22650
|
+
if (Array.isArray(lastDoc)) {
|
|
22651
|
+
return lastDoc;
|
|
22652
|
+
}
|
|
22653
|
+
if (lastDoc[orderByField]) {
|
|
22654
|
+
let value = lastDoc[orderByField];
|
|
22655
|
+
if (typeof value === "number" && orderByField === "createdAt") {
|
|
22656
|
+
value = import_firestore58.Timestamp.fromMillis(value);
|
|
22657
|
+
} else if (value.seconds && orderByField === "createdAt") {
|
|
22658
|
+
value = new import_firestore58.Timestamp(value.seconds, value.nanoseconds || 0);
|
|
22659
|
+
}
|
|
22660
|
+
return [value];
|
|
22661
|
+
}
|
|
22662
|
+
console.warn("[PROCEDURE_SERVICE] Could not parse lastDoc cursor:", typeof lastDoc);
|
|
22663
|
+
return null;
|
|
22664
|
+
}
|
|
22518
22665
|
/**
|
|
22519
22666
|
* Searches and filters procedures based on multiple criteria
|
|
22520
22667
|
*
|
|
22521
|
-
* @note Frontend
|
|
22668
|
+
* @note Frontend can now send either a DocumentSnapshot or a serializable cursor object.
|
|
22669
|
+
* The serializable cursor format is: { __cursor: true, values: [...], id: string, orderByField: string }
|
|
22522
22670
|
*
|
|
22523
22671
|
* @param filters - Various filters to apply
|
|
22524
22672
|
* @param filters.nameSearch - Optional search text for procedure name
|
|
@@ -22614,12 +22762,10 @@ var ProcedureService = class extends BaseService {
|
|
|
22614
22762
|
constraints.push((0, import_firestore58.where)("nameLower", "<=", searchTerm + "\uF8FF"));
|
|
22615
22763
|
constraints.push((0, import_firestore58.orderBy)("nameLower"));
|
|
22616
22764
|
if (filters.lastDoc) {
|
|
22617
|
-
|
|
22618
|
-
|
|
22619
|
-
|
|
22620
|
-
|
|
22621
|
-
} else {
|
|
22622
|
-
constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
|
|
22765
|
+
const cursorValues = this.getCursorValuesForStartAfter(filters.lastDoc, "nameLower");
|
|
22766
|
+
if (cursorValues) {
|
|
22767
|
+
constraints.push((0, import_firestore58.startAfter)(...cursorValues));
|
|
22768
|
+
console.log("[PROCEDURE_SERVICE] Strategy 1: Using cursor for pagination");
|
|
22623
22769
|
}
|
|
22624
22770
|
}
|
|
22625
22771
|
constraints.push((0, import_firestore58.limit)(filters.pagination || 10));
|
|
@@ -22638,8 +22784,9 @@ var ProcedureService = class extends BaseService {
|
|
|
22638
22784
|
if (querySnapshot.docs.length < (filters.pagination || 10)) {
|
|
22639
22785
|
return { procedures, lastDoc: null };
|
|
22640
22786
|
}
|
|
22641
|
-
const
|
|
22642
|
-
|
|
22787
|
+
const lastDocSnapshot = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
22788
|
+
const serializableCursor = this.createSerializableCursor(lastDocSnapshot, "nameLower");
|
|
22789
|
+
return { procedures, lastDoc: serializableCursor };
|
|
22643
22790
|
} catch (error) {
|
|
22644
22791
|
console.log("[PROCEDURE_SERVICE] Strategy 1 failed:", error);
|
|
22645
22792
|
}
|
|
@@ -22657,12 +22804,10 @@ var ProcedureService = class extends BaseService {
|
|
|
22657
22804
|
constraints.push((0, import_firestore58.where)("name", "<=", searchTerm + "\uF8FF"));
|
|
22658
22805
|
constraints.push((0, import_firestore58.orderBy)("name"));
|
|
22659
22806
|
if (filters.lastDoc) {
|
|
22660
|
-
|
|
22661
|
-
|
|
22662
|
-
|
|
22663
|
-
|
|
22664
|
-
} else {
|
|
22665
|
-
constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
|
|
22807
|
+
const cursorValues = this.getCursorValuesForStartAfter(filters.lastDoc, "name");
|
|
22808
|
+
if (cursorValues) {
|
|
22809
|
+
constraints.push((0, import_firestore58.startAfter)(...cursorValues));
|
|
22810
|
+
console.log("[PROCEDURE_SERVICE] Strategy 2: Using cursor for pagination");
|
|
22666
22811
|
}
|
|
22667
22812
|
}
|
|
22668
22813
|
constraints.push((0, import_firestore58.limit)(filters.pagination || 10));
|
|
@@ -22681,8 +22826,9 @@ var ProcedureService = class extends BaseService {
|
|
|
22681
22826
|
if (querySnapshot.docs.length < (filters.pagination || 10)) {
|
|
22682
22827
|
return { procedures, lastDoc: null };
|
|
22683
22828
|
}
|
|
22684
|
-
const
|
|
22685
|
-
|
|
22829
|
+
const lastDocSnapshot = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
22830
|
+
const serializableCursor = this.createSerializableCursor(lastDocSnapshot, "name");
|
|
22831
|
+
return { procedures, lastDoc: serializableCursor };
|
|
22686
22832
|
} catch (error) {
|
|
22687
22833
|
console.log("[PROCEDURE_SERVICE] Strategy 2 failed:", error);
|
|
22688
22834
|
}
|
|
@@ -22732,12 +22878,10 @@ var ProcedureService = class extends BaseService {
|
|
|
22732
22878
|
);
|
|
22733
22879
|
constraints.push((0, import_firestore58.orderBy)("createdAt", "desc"));
|
|
22734
22880
|
if (filters.lastDoc) {
|
|
22735
|
-
|
|
22736
|
-
|
|
22737
|
-
|
|
22738
|
-
|
|
22739
|
-
} else {
|
|
22740
|
-
constraints.push((0, import_firestore58.startAfter)(filters.lastDoc));
|
|
22881
|
+
const cursorValues = this.getCursorValuesForStartAfter(filters.lastDoc, "createdAt");
|
|
22882
|
+
if (cursorValues) {
|
|
22883
|
+
constraints.push((0, import_firestore58.startAfter)(...cursorValues));
|
|
22884
|
+
console.log("[PROCEDURE_SERVICE] Strategy 3: Using cursor for pagination");
|
|
22741
22885
|
}
|
|
22742
22886
|
}
|
|
22743
22887
|
constraints.push((0, import_firestore58.limit)(filters.pagination || 10));
|
|
@@ -22768,8 +22912,9 @@ var ProcedureService = class extends BaseService {
|
|
|
22768
22912
|
if (querySnapshot.docs.length < (filters.pagination || 10)) {
|
|
22769
22913
|
return { procedures, lastDoc: null };
|
|
22770
22914
|
}
|
|
22771
|
-
const
|
|
22772
|
-
|
|
22915
|
+
const lastDocSnapshot = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
22916
|
+
const serializableCursor = this.createSerializableCursor(lastDocSnapshot, "createdAt");
|
|
22917
|
+
return { procedures, lastDoc: serializableCursor };
|
|
22773
22918
|
} catch (error) {
|
|
22774
22919
|
console.log("[PROCEDURE_SERVICE] Strategy 3 failed:", error);
|
|
22775
22920
|
}
|
|
@@ -22785,6 +22930,13 @@ var ProcedureService = class extends BaseService {
|
|
|
22785
22930
|
if (filters.clinicId) {
|
|
22786
22931
|
constraints.push((0, import_firestore58.where)("clinicBranchId", "==", filters.clinicId));
|
|
22787
22932
|
}
|
|
22933
|
+
if (filters.lastDoc) {
|
|
22934
|
+
const cursorValues = this.getCursorValuesForStartAfter(filters.lastDoc, "createdAt");
|
|
22935
|
+
if (cursorValues) {
|
|
22936
|
+
constraints.push((0, import_firestore58.startAfter)(...cursorValues));
|
|
22937
|
+
console.log("[PROCEDURE_SERVICE] Strategy 4: Using cursor for pagination");
|
|
22938
|
+
}
|
|
22939
|
+
}
|
|
22788
22940
|
constraints.push((0, import_firestore58.limit)(filters.pagination || 10));
|
|
22789
22941
|
const q = (0, import_firestore58.query)((0, import_firestore58.collection)(this.db, PROCEDURES_COLLECTION), ...constraints);
|
|
22790
22942
|
const querySnapshot = await (0, import_firestore58.getDocs)(q);
|
|
@@ -22799,8 +22951,9 @@ var ProcedureService = class extends BaseService {
|
|
|
22799
22951
|
if (querySnapshot.docs.length < (filters.pagination || 10)) {
|
|
22800
22952
|
return { procedures, lastDoc: null };
|
|
22801
22953
|
}
|
|
22802
|
-
const
|
|
22803
|
-
|
|
22954
|
+
const lastDocSnapshot = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
22955
|
+
const serializableCursor = this.createSerializableCursor(lastDocSnapshot, "createdAt");
|
|
22956
|
+
return { procedures, lastDoc: serializableCursor };
|
|
22804
22957
|
} catch (error) {
|
|
22805
22958
|
console.log("[PROCEDURE_SERVICE] Strategy 4 failed:", error);
|
|
22806
22959
|
}
|