@blackcode_sa/metaestetics-api 1.5.25 → 1.5.28
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/index.d.mts +87 -0
- package/dist/index.d.ts +87 -0
- package/dist/index.js +461 -0
- package/dist/index.mjs +470 -1
- package/package.json +1 -1
- package/src/services/calendar/calendar-refactored.service.ts +2 -0
- package/src/services/clinic/clinic.service.ts +54 -0
- package/src/services/clinic/utils/clinic.utils.ts +230 -0
- package/src/services/procedure/procedure.service.ts +380 -1
- package/src/types/procedure/index.ts +7 -0
- package/src/validations/procedure.schema.ts +3 -0
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/config/firebase.ts
|
|
2
9
|
import { initializeApp } from "firebase/app";
|
|
3
10
|
import { getFirestore } from "firebase/firestore";
|
|
@@ -5270,6 +5277,143 @@ async function getActiveClinicsByAdmin(db, adminId, clinicAdminService, clinicGr
|
|
|
5270
5277
|
clinicGroupService
|
|
5271
5278
|
);
|
|
5272
5279
|
}
|
|
5280
|
+
async function getClinicById(db, clinicId) {
|
|
5281
|
+
try {
|
|
5282
|
+
const clinicRef = doc9(db, CLINICS_COLLECTION, clinicId);
|
|
5283
|
+
const clinicSnapshot = await getDoc12(clinicRef);
|
|
5284
|
+
if (!clinicSnapshot.exists()) {
|
|
5285
|
+
return null;
|
|
5286
|
+
}
|
|
5287
|
+
const clinicData = clinicSnapshot.data();
|
|
5288
|
+
return {
|
|
5289
|
+
...clinicData,
|
|
5290
|
+
id: clinicSnapshot.id
|
|
5291
|
+
};
|
|
5292
|
+
} catch (error) {
|
|
5293
|
+
console.error("[CLINIC_UTILS] Error getting clinic by ID:", error);
|
|
5294
|
+
throw error;
|
|
5295
|
+
}
|
|
5296
|
+
}
|
|
5297
|
+
async function getAllClinics(db, pagination, lastDoc) {
|
|
5298
|
+
try {
|
|
5299
|
+
const clinicsCollection = collection7(db, CLINICS_COLLECTION);
|
|
5300
|
+
let clinicsQuery = query7(clinicsCollection);
|
|
5301
|
+
if (pagination && pagination > 0) {
|
|
5302
|
+
const { limit: limit4, startAfter: startAfter4 } = __require("firebase/firestore");
|
|
5303
|
+
if (lastDoc) {
|
|
5304
|
+
clinicsQuery = query7(
|
|
5305
|
+
clinicsCollection,
|
|
5306
|
+
startAfter4(lastDoc),
|
|
5307
|
+
limit4(pagination)
|
|
5308
|
+
);
|
|
5309
|
+
} else {
|
|
5310
|
+
clinicsQuery = query7(clinicsCollection, limit4(pagination));
|
|
5311
|
+
}
|
|
5312
|
+
}
|
|
5313
|
+
const clinicsSnapshot = await getDocs7(clinicsQuery);
|
|
5314
|
+
const lastVisible = clinicsSnapshot.docs[clinicsSnapshot.docs.length - 1];
|
|
5315
|
+
const clinics = clinicsSnapshot.docs.map((doc28) => {
|
|
5316
|
+
const data = doc28.data();
|
|
5317
|
+
return {
|
|
5318
|
+
...data,
|
|
5319
|
+
id: doc28.id
|
|
5320
|
+
};
|
|
5321
|
+
});
|
|
5322
|
+
return {
|
|
5323
|
+
clinics,
|
|
5324
|
+
lastDoc: lastVisible
|
|
5325
|
+
};
|
|
5326
|
+
} catch (error) {
|
|
5327
|
+
console.error("[CLINIC_UTILS] Error getting all clinics:", error);
|
|
5328
|
+
throw error;
|
|
5329
|
+
}
|
|
5330
|
+
}
|
|
5331
|
+
async function getAllClinicsInRange(db, center, rangeInKm, pagination, lastDoc, filters) {
|
|
5332
|
+
try {
|
|
5333
|
+
const { distanceBetween: distanceBetween2 } = __require("geofire-common");
|
|
5334
|
+
const centerLat = center.latitude;
|
|
5335
|
+
const centerLng = center.longitude;
|
|
5336
|
+
const clinicsCollection = collection7(db, CLINICS_COLLECTION);
|
|
5337
|
+
let clinicsQuery = query7(clinicsCollection);
|
|
5338
|
+
if ((filters == null ? void 0 : filters.isActive) !== void 0) {
|
|
5339
|
+
clinicsQuery = query7(
|
|
5340
|
+
clinicsCollection,
|
|
5341
|
+
where7("isActive", "==", filters.isActive)
|
|
5342
|
+
);
|
|
5343
|
+
}
|
|
5344
|
+
const querySnapshot = await getDocs7(clinicsQuery);
|
|
5345
|
+
console.log(
|
|
5346
|
+
`[CLINIC_UTILS] Found ${querySnapshot.docs.length} total clinics to filter by distance`
|
|
5347
|
+
);
|
|
5348
|
+
const filteredDocs = [];
|
|
5349
|
+
for (const doc28 of querySnapshot.docs) {
|
|
5350
|
+
const clinic = doc28.data();
|
|
5351
|
+
if (!clinic.location || !clinic.location.latitude || !clinic.location.longitude) {
|
|
5352
|
+
continue;
|
|
5353
|
+
}
|
|
5354
|
+
const distanceInM = distanceBetween2(
|
|
5355
|
+
[centerLat, centerLng],
|
|
5356
|
+
[clinic.location.latitude, clinic.location.longitude]
|
|
5357
|
+
);
|
|
5358
|
+
const distanceInKm = distanceInM / 1e3;
|
|
5359
|
+
if (distanceInKm <= rangeInKm) {
|
|
5360
|
+
if ((filters == null ? void 0 : filters.tags) && filters.tags.length > 0) {
|
|
5361
|
+
const hasAllTags = filters.tags.every(
|
|
5362
|
+
(filterTag) => clinic.tags.some(
|
|
5363
|
+
(clinicTag) => filterTag.id === clinicTag.id || filterTag.name === clinicTag.name
|
|
5364
|
+
)
|
|
5365
|
+
);
|
|
5366
|
+
if (hasAllTags) {
|
|
5367
|
+
filteredDocs.push({
|
|
5368
|
+
doc: doc28,
|
|
5369
|
+
distance: distanceInKm
|
|
5370
|
+
});
|
|
5371
|
+
}
|
|
5372
|
+
} else {
|
|
5373
|
+
filteredDocs.push({
|
|
5374
|
+
doc: doc28,
|
|
5375
|
+
distance: distanceInKm
|
|
5376
|
+
});
|
|
5377
|
+
}
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5380
|
+
console.log(
|
|
5381
|
+
`[CLINIC_UTILS] Filtered to ${filteredDocs.length} clinics within ${rangeInKm}km`
|
|
5382
|
+
);
|
|
5383
|
+
filteredDocs.sort((a, b) => a.distance - b.distance);
|
|
5384
|
+
let paginatedDocs = filteredDocs;
|
|
5385
|
+
let lastVisible = null;
|
|
5386
|
+
if (pagination && pagination > 0) {
|
|
5387
|
+
let startIndex = 0;
|
|
5388
|
+
if (lastDoc) {
|
|
5389
|
+
const lastDocIndex = filteredDocs.findIndex(
|
|
5390
|
+
(item) => item.doc.id === lastDoc.id
|
|
5391
|
+
);
|
|
5392
|
+
if (lastDocIndex !== -1) {
|
|
5393
|
+
startIndex = lastDocIndex + 1;
|
|
5394
|
+
}
|
|
5395
|
+
}
|
|
5396
|
+
paginatedDocs = filteredDocs.slice(startIndex, startIndex + pagination);
|
|
5397
|
+
lastVisible = paginatedDocs.length > 0 ? paginatedDocs[paginatedDocs.length - 1].doc : null;
|
|
5398
|
+
}
|
|
5399
|
+
const clinics = paginatedDocs.map((item) => {
|
|
5400
|
+
const data = item.doc.data();
|
|
5401
|
+
return {
|
|
5402
|
+
...data,
|
|
5403
|
+
id: item.doc.id,
|
|
5404
|
+
distance: item.distance
|
|
5405
|
+
// Include distance in response
|
|
5406
|
+
};
|
|
5407
|
+
});
|
|
5408
|
+
return {
|
|
5409
|
+
clinics,
|
|
5410
|
+
lastDoc: lastVisible
|
|
5411
|
+
};
|
|
5412
|
+
} catch (error) {
|
|
5413
|
+
console.error("[CLINIC_UTILS] Error getting clinics in range:", error);
|
|
5414
|
+
throw error;
|
|
5415
|
+
}
|
|
5416
|
+
}
|
|
5273
5417
|
|
|
5274
5418
|
// src/services/clinic/utils/review.utils.ts
|
|
5275
5419
|
import {
|
|
@@ -5614,6 +5758,45 @@ var ClinicService = class extends BaseService {
|
|
|
5614
5758
|
});
|
|
5615
5759
|
return clinic;
|
|
5616
5760
|
}
|
|
5761
|
+
/**
|
|
5762
|
+
* Retrieves a clinic by its ID
|
|
5763
|
+
*
|
|
5764
|
+
* @param clinicId - ID of the clinic to retrieve
|
|
5765
|
+
* @returns The clinic if found, null otherwise
|
|
5766
|
+
*/
|
|
5767
|
+
async getClinicById(clinicId) {
|
|
5768
|
+
return getClinicById(this.db, clinicId);
|
|
5769
|
+
}
|
|
5770
|
+
/**
|
|
5771
|
+
* Retrieves all clinics with optional pagination
|
|
5772
|
+
*
|
|
5773
|
+
* @param pagination - Optional number of clinics per page (0 or undefined returns all)
|
|
5774
|
+
* @param lastDoc - Optional last document for pagination (if continuing from a previous page)
|
|
5775
|
+
* @returns Array of clinics and the last document for pagination
|
|
5776
|
+
*/
|
|
5777
|
+
async getAllClinics(pagination, lastDoc) {
|
|
5778
|
+
return getAllClinics(this.db, pagination, lastDoc);
|
|
5779
|
+
}
|
|
5780
|
+
/**
|
|
5781
|
+
* Retrieves all clinics within a specified range from a location with optional pagination
|
|
5782
|
+
*
|
|
5783
|
+
* @param center - The center location coordinates {latitude, longitude}
|
|
5784
|
+
* @param rangeInKm - The range in kilometers to search within
|
|
5785
|
+
* @param pagination - Optional number of clinics per page (0 or undefined returns all)
|
|
5786
|
+
* @param lastDoc - Optional last document for pagination (if continuing from a previous page)
|
|
5787
|
+
* @param filters - Optional filters to apply to the search (isActive, tags, etc.)
|
|
5788
|
+
* @returns Array of clinics with distance information and the last document for pagination
|
|
5789
|
+
*/
|
|
5790
|
+
async getAllClinicsInRange(center, rangeInKm, pagination, lastDoc, filters) {
|
|
5791
|
+
return getAllClinicsInRange(
|
|
5792
|
+
this.db,
|
|
5793
|
+
center,
|
|
5794
|
+
rangeInKm,
|
|
5795
|
+
pagination,
|
|
5796
|
+
lastDoc,
|
|
5797
|
+
filters
|
|
5798
|
+
);
|
|
5799
|
+
}
|
|
5617
5800
|
};
|
|
5618
5801
|
|
|
5619
5802
|
// src/services/auth.service.ts
|
|
@@ -6480,7 +6663,8 @@ import {
|
|
|
6480
6663
|
where as where11,
|
|
6481
6664
|
updateDoc as updateDoc14,
|
|
6482
6665
|
setDoc as setDoc13,
|
|
6483
|
-
serverTimestamp as serverTimestamp13
|
|
6666
|
+
serverTimestamp as serverTimestamp13,
|
|
6667
|
+
writeBatch as writeBatch4
|
|
6484
6668
|
} from "firebase/firestore";
|
|
6485
6669
|
|
|
6486
6670
|
// src/types/procedure/index.ts
|
|
@@ -6536,6 +6720,10 @@ var procedureSchema = createProcedureSchema.extend({
|
|
|
6536
6720
|
// We'll validate certification requirement separately
|
|
6537
6721
|
documentationTemplates: z16.array(z16.any()),
|
|
6538
6722
|
// We'll validate documentation templates separately
|
|
6723
|
+
clinicInfo: clinicInfoSchema,
|
|
6724
|
+
// Clinic info validation
|
|
6725
|
+
doctorInfo: doctorInfoSchema,
|
|
6726
|
+
// Doctor info validation
|
|
6539
6727
|
isActive: z16.boolean(),
|
|
6540
6728
|
createdAt: z16.date(),
|
|
6541
6729
|
updatedAt: z16.date()
|
|
@@ -6556,6 +6744,7 @@ var ProcedureService = class extends BaseService {
|
|
|
6556
6744
|
* @returns The created procedure
|
|
6557
6745
|
*/
|
|
6558
6746
|
async createProcedure(data) {
|
|
6747
|
+
var _a;
|
|
6559
6748
|
const validatedData = createProcedureSchema.parse(data);
|
|
6560
6749
|
const [category, subcategory, technology, product] = await Promise.all([
|
|
6561
6750
|
this.categoryService.getById(validatedData.categoryId),
|
|
@@ -6572,6 +6761,51 @@ var ProcedureService = class extends BaseService {
|
|
|
6572
6761
|
if (!category || !subcategory || !technology || !product) {
|
|
6573
6762
|
throw new Error("One or more required entities not found");
|
|
6574
6763
|
}
|
|
6764
|
+
const clinicRef = doc13(
|
|
6765
|
+
this.db,
|
|
6766
|
+
CLINICS_COLLECTION,
|
|
6767
|
+
validatedData.clinicBranchId
|
|
6768
|
+
);
|
|
6769
|
+
const clinicSnapshot = await getDoc16(clinicRef);
|
|
6770
|
+
if (!clinicSnapshot.exists()) {
|
|
6771
|
+
throw new Error(
|
|
6772
|
+
`Clinic with ID ${validatedData.clinicBranchId} not found`
|
|
6773
|
+
);
|
|
6774
|
+
}
|
|
6775
|
+
const clinic = clinicSnapshot.data();
|
|
6776
|
+
const clinicInfo = {
|
|
6777
|
+
id: clinicSnapshot.id,
|
|
6778
|
+
name: clinic.name,
|
|
6779
|
+
description: clinic.description || "",
|
|
6780
|
+
featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
|
|
6781
|
+
location: clinic.location,
|
|
6782
|
+
contactInfo: clinic.contactInfo
|
|
6783
|
+
};
|
|
6784
|
+
const practitionerRef = doc13(
|
|
6785
|
+
this.db,
|
|
6786
|
+
PRACTITIONERS_COLLECTION,
|
|
6787
|
+
validatedData.practitionerId
|
|
6788
|
+
);
|
|
6789
|
+
const practitionerSnapshot = await getDoc16(practitionerRef);
|
|
6790
|
+
if (!practitionerSnapshot.exists()) {
|
|
6791
|
+
throw new Error(
|
|
6792
|
+
`Practitioner with ID ${validatedData.practitionerId} not found`
|
|
6793
|
+
);
|
|
6794
|
+
}
|
|
6795
|
+
const practitioner = practitionerSnapshot.data();
|
|
6796
|
+
let doctorInfo = (_a = clinic.doctorsInfo) == null ? void 0 : _a.find(
|
|
6797
|
+
(doctor) => doctor.id === validatedData.practitionerId
|
|
6798
|
+
);
|
|
6799
|
+
if (!doctorInfo) {
|
|
6800
|
+
doctorInfo = {
|
|
6801
|
+
id: practitionerSnapshot.id,
|
|
6802
|
+
name: `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`,
|
|
6803
|
+
description: practitioner.basicInfo.bio || "",
|
|
6804
|
+
photo: practitioner.basicInfo.profileImageUrl || "",
|
|
6805
|
+
rating: 0,
|
|
6806
|
+
services: []
|
|
6807
|
+
};
|
|
6808
|
+
}
|
|
6575
6809
|
const procedure = {
|
|
6576
6810
|
...validatedData,
|
|
6577
6811
|
category,
|
|
@@ -6584,6 +6818,8 @@ var ProcedureService = class extends BaseService {
|
|
|
6584
6818
|
postRequirements: technology.requirements.post,
|
|
6585
6819
|
certificationRequirement: technology.certificationRequirement,
|
|
6586
6820
|
documentationTemplates: technology.documentationTemplates || [],
|
|
6821
|
+
clinicInfo,
|
|
6822
|
+
doctorInfo,
|
|
6587
6823
|
isActive: true,
|
|
6588
6824
|
createdAt: /* @__PURE__ */ new Date(),
|
|
6589
6825
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -6703,6 +6939,237 @@ var ProcedureService = class extends BaseService {
|
|
|
6703
6939
|
subcategories
|
|
6704
6940
|
};
|
|
6705
6941
|
}
|
|
6942
|
+
/**
|
|
6943
|
+
* Gets all procedures with optional pagination
|
|
6944
|
+
*
|
|
6945
|
+
* @param pagination - Optional number of procedures per page (0 or undefined returns all)
|
|
6946
|
+
* @param lastDoc - Optional last document for pagination (if continuing from a previous page)
|
|
6947
|
+
* @returns Object containing procedures array and the last document for pagination
|
|
6948
|
+
*/
|
|
6949
|
+
async getAllProcedures(pagination, lastDoc) {
|
|
6950
|
+
try {
|
|
6951
|
+
const proceduresCollection = collection12(this.db, PROCEDURES_COLLECTION);
|
|
6952
|
+
let proceduresQuery = query11(proceduresCollection);
|
|
6953
|
+
if (pagination && pagination > 0) {
|
|
6954
|
+
const { limit: limit4, startAfter: startAfter4 } = __require("firebase/firestore");
|
|
6955
|
+
if (lastDoc) {
|
|
6956
|
+
proceduresQuery = query11(
|
|
6957
|
+
proceduresCollection,
|
|
6958
|
+
startAfter4(lastDoc),
|
|
6959
|
+
limit4(pagination)
|
|
6960
|
+
);
|
|
6961
|
+
} else {
|
|
6962
|
+
proceduresQuery = query11(proceduresCollection, limit4(pagination));
|
|
6963
|
+
}
|
|
6964
|
+
}
|
|
6965
|
+
const proceduresSnapshot = await getDocs11(proceduresQuery);
|
|
6966
|
+
const lastVisible = proceduresSnapshot.docs[proceduresSnapshot.docs.length - 1];
|
|
6967
|
+
const procedures = proceduresSnapshot.docs.map((doc28) => {
|
|
6968
|
+
const data = doc28.data();
|
|
6969
|
+
if (!data.clinicInfo || !data.doctorInfo) {
|
|
6970
|
+
console.warn(
|
|
6971
|
+
`Procedure ${data.id} is missing clinicInfo or doctorInfo fields. These should be updated.`
|
|
6972
|
+
);
|
|
6973
|
+
}
|
|
6974
|
+
return {
|
|
6975
|
+
...data,
|
|
6976
|
+
id: doc28.id
|
|
6977
|
+
};
|
|
6978
|
+
});
|
|
6979
|
+
return {
|
|
6980
|
+
procedures,
|
|
6981
|
+
lastDoc: lastVisible
|
|
6982
|
+
};
|
|
6983
|
+
} catch (error) {
|
|
6984
|
+
console.error("[PROCEDURE_SERVICE] Error getting all procedures:", error);
|
|
6985
|
+
throw error;
|
|
6986
|
+
}
|
|
6987
|
+
}
|
|
6988
|
+
/**
|
|
6989
|
+
* Updates the clinicInfo and doctorInfo fields in procedures when the source data changes
|
|
6990
|
+
*
|
|
6991
|
+
* @param entityType - The type of entity that changed ("clinic" or "doctor")
|
|
6992
|
+
* @param entityId - The ID of the entity that changed
|
|
6993
|
+
* @param updatedData - The updated data for the entity
|
|
6994
|
+
* @returns Number of procedures updated
|
|
6995
|
+
*/
|
|
6996
|
+
async updateProcedureAggregateData(entityType, entityId, updatedData) {
|
|
6997
|
+
let proceduresQuery;
|
|
6998
|
+
const updatedField = entityType === "clinic" ? "clinicInfo" : "doctorInfo";
|
|
6999
|
+
if (entityType === "clinic") {
|
|
7000
|
+
proceduresQuery = query11(
|
|
7001
|
+
collection12(this.db, PROCEDURES_COLLECTION),
|
|
7002
|
+
where11("clinicBranchId", "==", entityId)
|
|
7003
|
+
);
|
|
7004
|
+
} else {
|
|
7005
|
+
proceduresQuery = query11(
|
|
7006
|
+
collection12(this.db, PROCEDURES_COLLECTION),
|
|
7007
|
+
where11("practitionerId", "==", entityId)
|
|
7008
|
+
);
|
|
7009
|
+
}
|
|
7010
|
+
const snapshot = await getDocs11(proceduresQuery);
|
|
7011
|
+
if (snapshot.empty) {
|
|
7012
|
+
return 0;
|
|
7013
|
+
}
|
|
7014
|
+
let updatedFieldData;
|
|
7015
|
+
if (entityType === "clinic") {
|
|
7016
|
+
updatedFieldData = {
|
|
7017
|
+
id: entityId,
|
|
7018
|
+
name: updatedData.name,
|
|
7019
|
+
description: updatedData.description || "",
|
|
7020
|
+
featuredPhoto: updatedData.featuredPhotos && updatedData.featuredPhotos.length > 0 ? updatedData.featuredPhotos[0] : updatedData.coverPhoto || "",
|
|
7021
|
+
location: updatedData.location,
|
|
7022
|
+
contactInfo: updatedData.contactInfo
|
|
7023
|
+
};
|
|
7024
|
+
} else {
|
|
7025
|
+
if (updatedData.basicInfo) {
|
|
7026
|
+
updatedFieldData = {
|
|
7027
|
+
id: entityId,
|
|
7028
|
+
name: `${updatedData.basicInfo.firstName} ${updatedData.basicInfo.lastName}`,
|
|
7029
|
+
description: updatedData.basicInfo.bio || "",
|
|
7030
|
+
photo: updatedData.basicInfo.profileImageUrl || "",
|
|
7031
|
+
rating: 0,
|
|
7032
|
+
// This would need to be calculated or passed in
|
|
7033
|
+
services: []
|
|
7034
|
+
// This would need to be determined or passed in
|
|
7035
|
+
};
|
|
7036
|
+
} else {
|
|
7037
|
+
updatedFieldData = {
|
|
7038
|
+
id: entityId,
|
|
7039
|
+
name: updatedData.name,
|
|
7040
|
+
description: updatedData.description || "",
|
|
7041
|
+
photo: updatedData.photo || "",
|
|
7042
|
+
rating: updatedData.rating || 0,
|
|
7043
|
+
services: updatedData.services || []
|
|
7044
|
+
};
|
|
7045
|
+
}
|
|
7046
|
+
}
|
|
7047
|
+
const batch = writeBatch4(this.db);
|
|
7048
|
+
snapshot.docs.forEach((doc28) => {
|
|
7049
|
+
batch.update(doc28.ref, {
|
|
7050
|
+
[updatedField]: updatedFieldData,
|
|
7051
|
+
updatedAt: serverTimestamp13()
|
|
7052
|
+
});
|
|
7053
|
+
});
|
|
7054
|
+
await batch.commit();
|
|
7055
|
+
return snapshot.size;
|
|
7056
|
+
}
|
|
7057
|
+
/**
|
|
7058
|
+
* Updates the clinicInfo for all procedures associated with a specific clinic
|
|
7059
|
+
*
|
|
7060
|
+
* @param clinicId - The ID of the clinic that was updated
|
|
7061
|
+
* @param clinicData - The updated clinic data
|
|
7062
|
+
* @returns Number of procedures updated
|
|
7063
|
+
*/
|
|
7064
|
+
async updateClinicInfoInProcedures(clinicId, clinicData) {
|
|
7065
|
+
return this.updateProcedureAggregateData("clinic", clinicId, clinicData);
|
|
7066
|
+
}
|
|
7067
|
+
/**
|
|
7068
|
+
* Updates the doctorInfo for all procedures associated with a specific practitioner
|
|
7069
|
+
*
|
|
7070
|
+
* @param practitionerId - The ID of the practitioner that was updated
|
|
7071
|
+
* @param practitionerData - The updated practitioner data
|
|
7072
|
+
* @returns Number of procedures updated
|
|
7073
|
+
*/
|
|
7074
|
+
async updateDoctorInfoInProcedures(practitionerId, practitionerData) {
|
|
7075
|
+
return this.updateProcedureAggregateData(
|
|
7076
|
+
"doctor",
|
|
7077
|
+
practitionerId,
|
|
7078
|
+
practitionerData
|
|
7079
|
+
);
|
|
7080
|
+
}
|
|
7081
|
+
/**
|
|
7082
|
+
* Updates all existing procedures to include clinicInfo and doctorInfo
|
|
7083
|
+
* This is a migration helper method that can be used to update existing procedures
|
|
7084
|
+
*
|
|
7085
|
+
* @returns Number of procedures updated
|
|
7086
|
+
*/
|
|
7087
|
+
async migrateAllProceduresWithAggregateData() {
|
|
7088
|
+
var _a;
|
|
7089
|
+
const proceduresQuery = query11(collection12(this.db, PROCEDURES_COLLECTION));
|
|
7090
|
+
const proceduresSnapshot = await getDocs11(proceduresQuery);
|
|
7091
|
+
if (proceduresSnapshot.empty) {
|
|
7092
|
+
return 0;
|
|
7093
|
+
}
|
|
7094
|
+
let updatedCount = 0;
|
|
7095
|
+
const batch = writeBatch4(this.db);
|
|
7096
|
+
const batchLimit = 500;
|
|
7097
|
+
let batchCount = 0;
|
|
7098
|
+
for (const procedureDoc of proceduresSnapshot.docs) {
|
|
7099
|
+
const procedure = procedureDoc.data();
|
|
7100
|
+
if (procedure.clinicInfo && procedure.doctorInfo) {
|
|
7101
|
+
continue;
|
|
7102
|
+
}
|
|
7103
|
+
try {
|
|
7104
|
+
const clinicRef = doc13(
|
|
7105
|
+
this.db,
|
|
7106
|
+
CLINICS_COLLECTION,
|
|
7107
|
+
procedure.clinicBranchId
|
|
7108
|
+
);
|
|
7109
|
+
const clinicSnapshot = await getDoc16(clinicRef);
|
|
7110
|
+
if (!clinicSnapshot.exists()) {
|
|
7111
|
+
console.warn(
|
|
7112
|
+
`Clinic ${procedure.clinicBranchId} not found for procedure ${procedure.id}`
|
|
7113
|
+
);
|
|
7114
|
+
continue;
|
|
7115
|
+
}
|
|
7116
|
+
const clinic = clinicSnapshot.data();
|
|
7117
|
+
const clinicInfo = {
|
|
7118
|
+
id: clinicSnapshot.id,
|
|
7119
|
+
name: clinic.name,
|
|
7120
|
+
description: clinic.description || "",
|
|
7121
|
+
featuredPhoto: clinic.featuredPhotos && clinic.featuredPhotos.length > 0 ? clinic.featuredPhotos[0] : clinic.coverPhoto || "",
|
|
7122
|
+
location: clinic.location,
|
|
7123
|
+
contactInfo: clinic.contactInfo
|
|
7124
|
+
};
|
|
7125
|
+
const practitionerRef = doc13(
|
|
7126
|
+
this.db,
|
|
7127
|
+
PRACTITIONERS_COLLECTION,
|
|
7128
|
+
procedure.practitionerId
|
|
7129
|
+
);
|
|
7130
|
+
const practitionerSnapshot = await getDoc16(practitionerRef);
|
|
7131
|
+
if (!practitionerSnapshot.exists()) {
|
|
7132
|
+
console.warn(
|
|
7133
|
+
`Practitioner ${procedure.practitionerId} not found for procedure ${procedure.id}`
|
|
7134
|
+
);
|
|
7135
|
+
continue;
|
|
7136
|
+
}
|
|
7137
|
+
const practitioner = practitionerSnapshot.data();
|
|
7138
|
+
let doctorInfo = (_a = clinic.doctorsInfo) == null ? void 0 : _a.find(
|
|
7139
|
+
(doctor) => doctor.id === procedure.practitionerId
|
|
7140
|
+
);
|
|
7141
|
+
if (!doctorInfo) {
|
|
7142
|
+
doctorInfo = {
|
|
7143
|
+
id: practitionerSnapshot.id,
|
|
7144
|
+
name: `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`,
|
|
7145
|
+
description: practitioner.basicInfo.bio || "",
|
|
7146
|
+
photo: practitioner.basicInfo.profileImageUrl || "",
|
|
7147
|
+
rating: 0,
|
|
7148
|
+
services: []
|
|
7149
|
+
};
|
|
7150
|
+
}
|
|
7151
|
+
batch.update(procedureDoc.ref, {
|
|
7152
|
+
clinicInfo,
|
|
7153
|
+
doctorInfo,
|
|
7154
|
+
updatedAt: serverTimestamp13()
|
|
7155
|
+
});
|
|
7156
|
+
batchCount++;
|
|
7157
|
+
updatedCount++;
|
|
7158
|
+
if (batchCount >= batchLimit) {
|
|
7159
|
+
await batch.commit();
|
|
7160
|
+
console.log(`Committed batch of ${batchCount} procedure updates`);
|
|
7161
|
+
batchCount = 0;
|
|
7162
|
+
}
|
|
7163
|
+
} catch (error) {
|
|
7164
|
+
console.error(`Error updating procedure ${procedure.id}:`, error);
|
|
7165
|
+
}
|
|
7166
|
+
}
|
|
7167
|
+
if (batchCount > 0) {
|
|
7168
|
+
await batch.commit();
|
|
7169
|
+
console.log(`Committed final batch of ${batchCount} procedure updates`);
|
|
7170
|
+
}
|
|
7171
|
+
return updatedCount;
|
|
7172
|
+
}
|
|
6706
7173
|
};
|
|
6707
7174
|
|
|
6708
7175
|
// src/services/documentation-templates/documentation-template.service.ts
|
|
@@ -9566,6 +10033,8 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
9566
10033
|
const updateParams = {
|
|
9567
10034
|
appointmentId,
|
|
9568
10035
|
clinicId,
|
|
10036
|
+
eventTime: appointment.eventTime,
|
|
10037
|
+
description: appointment.description || "",
|
|
9569
10038
|
doctorId: appointment.practitionerProfileId || "",
|
|
9570
10039
|
patientId: appointment.patientProfileId || "",
|
|
9571
10040
|
status
|
package/package.json
CHANGED
|
@@ -1106,6 +1106,8 @@ export class CalendarServiceV2 extends BaseService {
|
|
|
1106
1106
|
const updateParams: UpdateAppointmentParams = {
|
|
1107
1107
|
appointmentId,
|
|
1108
1108
|
clinicId,
|
|
1109
|
+
eventTime: appointment.eventTime,
|
|
1110
|
+
description: appointment.description || "",
|
|
1109
1111
|
doctorId: appointment.practitionerProfileId || "",
|
|
1110
1112
|
patientId: appointment.patientProfileId || "",
|
|
1111
1113
|
status,
|
|
@@ -301,4 +301,58 @@ export class ClinicService extends BaseService {
|
|
|
301
301
|
// Note: The createClinic method already adds the clinic to the admin's managed clinics
|
|
302
302
|
return clinic;
|
|
303
303
|
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Retrieves a clinic by its ID
|
|
307
|
+
*
|
|
308
|
+
* @param clinicId - ID of the clinic to retrieve
|
|
309
|
+
* @returns The clinic if found, null otherwise
|
|
310
|
+
*/
|
|
311
|
+
async getClinicById(clinicId: string): Promise<Clinic | null> {
|
|
312
|
+
return ClinicUtils.getClinicById(this.db, clinicId);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Retrieves all clinics with optional pagination
|
|
317
|
+
*
|
|
318
|
+
* @param pagination - Optional number of clinics per page (0 or undefined returns all)
|
|
319
|
+
* @param lastDoc - Optional last document for pagination (if continuing from a previous page)
|
|
320
|
+
* @returns Array of clinics and the last document for pagination
|
|
321
|
+
*/
|
|
322
|
+
async getAllClinics(
|
|
323
|
+
pagination?: number,
|
|
324
|
+
lastDoc?: any
|
|
325
|
+
): Promise<{ clinics: Clinic[]; lastDoc: any }> {
|
|
326
|
+
return ClinicUtils.getAllClinics(this.db, pagination, lastDoc);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Retrieves all clinics within a specified range from a location with optional pagination
|
|
331
|
+
*
|
|
332
|
+
* @param center - The center location coordinates {latitude, longitude}
|
|
333
|
+
* @param rangeInKm - The range in kilometers to search within
|
|
334
|
+
* @param pagination - Optional number of clinics per page (0 or undefined returns all)
|
|
335
|
+
* @param lastDoc - Optional last document for pagination (if continuing from a previous page)
|
|
336
|
+
* @param filters - Optional filters to apply to the search (isActive, tags, etc.)
|
|
337
|
+
* @returns Array of clinics with distance information and the last document for pagination
|
|
338
|
+
*/
|
|
339
|
+
async getAllClinicsInRange(
|
|
340
|
+
center: { latitude: number; longitude: number },
|
|
341
|
+
rangeInKm: number,
|
|
342
|
+
pagination?: number,
|
|
343
|
+
lastDoc?: any,
|
|
344
|
+
filters?: {
|
|
345
|
+
isActive?: boolean;
|
|
346
|
+
tags?: ClinicTag[];
|
|
347
|
+
}
|
|
348
|
+
): Promise<{ clinics: (Clinic & { distance: number })[]; lastDoc: any }> {
|
|
349
|
+
return ClinicUtils.getAllClinicsInRange(
|
|
350
|
+
this.db,
|
|
351
|
+
center,
|
|
352
|
+
rangeInKm,
|
|
353
|
+
pagination,
|
|
354
|
+
lastDoc,
|
|
355
|
+
filters
|
|
356
|
+
);
|
|
357
|
+
}
|
|
304
358
|
}
|