@blackcode_sa/metaestetics-api 1.10.0 → 1.11.1
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 +337 -319
- package/dist/admin/index.d.ts +337 -319
- package/dist/admin/index.js +98 -79
- package/dist/admin/index.mjs +98 -79
- package/dist/backoffice/index.d.mts +284 -67
- package/dist/backoffice/index.d.ts +284 -67
- package/dist/backoffice/index.js +114 -6
- package/dist/backoffice/index.mjs +112 -6
- package/dist/index.d.mts +3145 -3065
- package/dist/index.d.ts +3145 -3065
- package/dist/index.js +460 -141
- package/dist/index.mjs +463 -143
- package/package.json +3 -1
- package/src/admin/booking/booking.admin.ts +2 -0
- package/src/admin/booking/booking.calculator.ts +121 -117
- package/src/admin/booking/booking.types.ts +3 -0
- package/src/backoffice/expo-safe/index.ts +2 -0
- package/src/backoffice/services/README.md +40 -0
- package/src/backoffice/services/constants.service.ts +268 -0
- package/src/backoffice/services/technology.service.ts +122 -10
- package/src/backoffice/types/admin-constants.types.ts +69 -0
- package/src/backoffice/types/index.ts +1 -0
- package/src/backoffice/types/product.types.ts +3 -1
- package/src/backoffice/types/technology.types.ts +4 -4
- package/src/backoffice/validations/schemas.ts +35 -9
- package/src/services/appointment/appointment.service.ts +0 -5
- package/src/services/appointment/utils/appointment.utils.ts +124 -113
- package/src/services/clinic/clinic.service.ts +163 -82
- package/src/services/procedure/procedure.service.ts +435 -234
- package/src/types/appointment/index.ts +9 -3
- package/src/types/clinic/index.ts +3 -6
- package/src/types/patient/medical-info.types.ts +3 -3
- package/src/types/procedure/index.ts +20 -17
- package/src/validations/appointment.schema.ts +2 -0
- package/src/validations/clinic.schema.ts +3 -6
- package/src/validations/patient/medical-info.schema.ts +7 -2
- package/src/validations/procedure.schema.ts +8 -10
- package/src/backoffice/services/__tests__/brand.service.test.ts +0 -196
- package/src/backoffice/services/__tests__/category.service.test.ts +0 -201
- package/src/backoffice/services/__tests__/product.service.test.ts +0 -358
- package/src/backoffice/services/__tests__/requirement.service.test.ts +0 -226
- package/src/backoffice/services/__tests__/subcategory.service.test.ts +0 -181
- package/src/backoffice/services/__tests__/technology.service.test.ts +0 -1097
package/dist/index.mjs
CHANGED
|
@@ -53,13 +53,13 @@ var AppointmentStatus = /* @__PURE__ */ ((AppointmentStatus2) => {
|
|
|
53
53
|
AppointmentStatus2["RESCHEDULED_BY_CLINIC"] = "rescheduled_by_clinic";
|
|
54
54
|
return AppointmentStatus2;
|
|
55
55
|
})(AppointmentStatus || {});
|
|
56
|
-
var PaymentStatus = /* @__PURE__ */ ((
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
return
|
|
56
|
+
var PaymentStatus = /* @__PURE__ */ ((PaymentStatus4) => {
|
|
57
|
+
PaymentStatus4["UNPAID"] = "unpaid";
|
|
58
|
+
PaymentStatus4["PAID"] = "paid";
|
|
59
|
+
PaymentStatus4["PARTIALLY_PAID"] = "partially_paid";
|
|
60
|
+
PaymentStatus4["REFUNDED"] = "refunded";
|
|
61
|
+
PaymentStatus4["NOT_APPLICABLE"] = "not_applicable";
|
|
62
|
+
return PaymentStatus4;
|
|
63
63
|
})(PaymentStatus || {});
|
|
64
64
|
var MediaType = /* @__PURE__ */ ((MediaType2) => {
|
|
65
65
|
MediaType2["BEFORE_PHOTO"] = "before_photo";
|
|
@@ -455,7 +455,8 @@ var createAppointmentSchema = z3.object({
|
|
|
455
455
|
currency: z3.string().min(1, "Currency is required"),
|
|
456
456
|
patientNotes: z3.string().max(MAX_STRING_LENGTH, "Patient notes too long").nullable().optional(),
|
|
457
457
|
initialStatus: appointmentStatusSchema,
|
|
458
|
-
initialPaymentStatus: paymentStatusSchema.optional().default("unpaid" /* UNPAID */)
|
|
458
|
+
initialPaymentStatus: paymentStatusSchema.optional().default("unpaid" /* UNPAID */),
|
|
459
|
+
clinic_tz: z3.string().min(1, "Timezone is required")
|
|
459
460
|
}).refine((data) => data.appointmentEndTime > data.appointmentStartTime, {
|
|
460
461
|
message: "Appointment end time must be after start time",
|
|
461
462
|
path: ["appointmentEndTime"]
|
|
@@ -489,6 +490,7 @@ var updateAppointmentSchema = z3.object({
|
|
|
489
490
|
cost: z3.number().min(0).optional(),
|
|
490
491
|
clinicBranchId: z3.string().min(MIN_STRING_LENGTH).optional(),
|
|
491
492
|
practitionerId: z3.string().min(MIN_STRING_LENGTH).optional(),
|
|
493
|
+
clinic_tz: z3.string().min(MIN_STRING_LENGTH).optional(),
|
|
492
494
|
linkedForms: z3.union([z3.array(linkedFormInfoSchema).max(MAX_ARRAY_LENGTH), z3.any()]).optional(),
|
|
493
495
|
media: z3.union([
|
|
494
496
|
z3.array(appointmentMediaItemSchema).max(MAX_ARRAY_LENGTH),
|
|
@@ -583,7 +585,6 @@ import {
|
|
|
583
585
|
getDocs,
|
|
584
586
|
query,
|
|
585
587
|
where,
|
|
586
|
-
setDoc,
|
|
587
588
|
updateDoc,
|
|
588
589
|
serverTimestamp,
|
|
589
590
|
Timestamp,
|
|
@@ -820,44 +821,48 @@ async function updateAppointmentUtil(db, appointmentId, data) {
|
|
|
820
821
|
const validPreReqIds = currentAppointment.preProcedureRequirements.map(
|
|
821
822
|
(req) => req.id
|
|
822
823
|
);
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
if (invalidPreReqIds.length > 0) {
|
|
827
|
-
throw new Error(
|
|
828
|
-
`Invalid pre-requirement IDs: ${invalidPreReqIds.join(", ")}`
|
|
824
|
+
if (Array.isArray(data.completedPreRequirements)) {
|
|
825
|
+
const invalidPreReqIds = data.completedPreRequirements.filter(
|
|
826
|
+
(id) => !validPreReqIds.includes(id)
|
|
829
827
|
);
|
|
828
|
+
if (invalidPreReqIds.length > 0) {
|
|
829
|
+
throw new Error(
|
|
830
|
+
`Invalid pre-requirement IDs: ${invalidPreReqIds.join(", ")}`
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
completedPreRequirements = [
|
|
834
|
+
.../* @__PURE__ */ new Set([
|
|
835
|
+
...completedPreRequirements,
|
|
836
|
+
...data.completedPreRequirements
|
|
837
|
+
])
|
|
838
|
+
];
|
|
830
839
|
}
|
|
831
|
-
completedPreRequirements = [
|
|
832
|
-
.../* @__PURE__ */ new Set([
|
|
833
|
-
...completedPreRequirements,
|
|
834
|
-
...data.completedPreRequirements
|
|
835
|
-
])
|
|
836
|
-
];
|
|
837
840
|
}
|
|
838
841
|
if (data.completedPostRequirements) {
|
|
839
842
|
const validPostReqIds = currentAppointment.postProcedureRequirements.map(
|
|
840
843
|
(req) => req.id
|
|
841
844
|
);
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
if (invalidPostReqIds.length > 0) {
|
|
846
|
-
throw new Error(
|
|
847
|
-
`Invalid post-requirement IDs: ${invalidPostReqIds.join(", ")}`
|
|
845
|
+
if (Array.isArray(data.completedPostRequirements)) {
|
|
846
|
+
const invalidPostReqIds = data.completedPostRequirements.filter(
|
|
847
|
+
(id) => !validPostReqIds.includes(id)
|
|
848
848
|
);
|
|
849
|
+
if (invalidPostReqIds.length > 0) {
|
|
850
|
+
throw new Error(
|
|
851
|
+
`Invalid post-requirement IDs: ${invalidPostReqIds.join(", ")}`
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
completedPostRequirements = [
|
|
855
|
+
.../* @__PURE__ */ new Set([
|
|
856
|
+
...completedPostRequirements,
|
|
857
|
+
...data.completedPostRequirements
|
|
858
|
+
])
|
|
859
|
+
];
|
|
849
860
|
}
|
|
850
|
-
completedPostRequirements = [
|
|
851
|
-
.../* @__PURE__ */ new Set([
|
|
852
|
-
...completedPostRequirements,
|
|
853
|
-
...data.completedPostRequirements
|
|
854
|
-
])
|
|
855
|
-
];
|
|
856
861
|
}
|
|
857
862
|
const updateData = {
|
|
858
863
|
...data,
|
|
859
|
-
completedPreRequirements,
|
|
860
|
-
completedPostRequirements,
|
|
864
|
+
completedPreRequirements: Array.isArray(data.completedPreRequirements) ? completedPreRequirements : data.completedPreRequirements,
|
|
865
|
+
completedPostRequirements: Array.isArray(data.completedPostRequirements) ? completedPostRequirements : data.completedPostRequirements,
|
|
861
866
|
updatedAt: serverTimestamp()
|
|
862
867
|
};
|
|
863
868
|
Object.keys(updateData).forEach((key) => {
|
|
@@ -907,7 +912,7 @@ async function updateCalendarEventStatus(db, calendarEventId, appointmentStatus)
|
|
|
907
912
|
case "canceled_clinic" /* CANCELED_CLINIC */:
|
|
908
913
|
calendarStatus = "canceled";
|
|
909
914
|
break;
|
|
910
|
-
case
|
|
915
|
+
case "rescheduled_by_clinic" /* RESCHEDULED_BY_CLINIC */:
|
|
911
916
|
calendarStatus = "rescheduled";
|
|
912
917
|
break;
|
|
913
918
|
case "completed" /* COMPLETED */:
|
|
@@ -2800,23 +2805,6 @@ var BlockingCondition = /* @__PURE__ */ ((BlockingCondition2) => {
|
|
|
2800
2805
|
return BlockingCondition2;
|
|
2801
2806
|
})(BlockingCondition || {});
|
|
2802
2807
|
|
|
2803
|
-
// src/backoffice/types/static/contraindication.types.ts
|
|
2804
|
-
var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
|
|
2805
|
-
Contraindication2["SENSITIVE_SKIN"] = "sensitive_skin";
|
|
2806
|
-
Contraindication2["RECENT_TANNING"] = "recent_tanning";
|
|
2807
|
-
Contraindication2["RECENT_BOTOX"] = "recent_botox";
|
|
2808
|
-
Contraindication2["RECENT_FILLERS"] = "recent_fillers";
|
|
2809
|
-
Contraindication2["SKIN_ALLERGIES"] = "skin_allergies";
|
|
2810
|
-
Contraindication2["MEDICATIONS"] = "medications";
|
|
2811
|
-
Contraindication2["RECENT_CHEMICAL_PEEL"] = "recent_chemical_peel";
|
|
2812
|
-
Contraindication2["RECENT_LASER"] = "recent_laser";
|
|
2813
|
-
Contraindication2["SKIN_INFLAMMATION"] = "skin_inflammation";
|
|
2814
|
-
Contraindication2["OPEN_WOUNDS"] = "open_wounds";
|
|
2815
|
-
Contraindication2["HERPES_SIMPLEX"] = "herpes_simplex";
|
|
2816
|
-
Contraindication2["COLD_SORES"] = "cold_sores";
|
|
2817
|
-
return Contraindication2;
|
|
2818
|
-
})(Contraindication || {});
|
|
2819
|
-
|
|
2820
2808
|
// src/validations/common.schema.ts
|
|
2821
2809
|
import { z as z5 } from "zod";
|
|
2822
2810
|
import { Timestamp as Timestamp4 } from "firebase/firestore";
|
|
@@ -2871,8 +2859,13 @@ var blockingConditionSchema = z6.object({
|
|
|
2871
2859
|
notes: z6.string().optional().nullable(),
|
|
2872
2860
|
isActive: z6.boolean()
|
|
2873
2861
|
});
|
|
2862
|
+
var contraindicationDynamicSchema = z6.object({
|
|
2863
|
+
id: z6.string(),
|
|
2864
|
+
name: z6.string(),
|
|
2865
|
+
description: z6.string().optional()
|
|
2866
|
+
});
|
|
2874
2867
|
var contraindicationSchema = z6.object({
|
|
2875
|
-
condition:
|
|
2868
|
+
condition: contraindicationDynamicSchema,
|
|
2876
2869
|
lastOccurrence: timestampSchema,
|
|
2877
2870
|
frequency: z6.enum(["rare", "occasional", "frequent"]),
|
|
2878
2871
|
notes: z6.string().optional().nullable(),
|
|
@@ -3437,7 +3430,8 @@ var clinicLocationSchema = z10.object({
|
|
|
3437
3430
|
postalCode: z10.string(),
|
|
3438
3431
|
latitude: z10.number().min(-90).max(90),
|
|
3439
3432
|
longitude: z10.number().min(-180).max(180),
|
|
3440
|
-
geohash: z10.string().nullable().optional()
|
|
3433
|
+
geohash: z10.string().nullable().optional(),
|
|
3434
|
+
tz: z10.string().nullable().optional()
|
|
3441
3435
|
});
|
|
3442
3436
|
var workingHoursTimeSchema = z10.object({
|
|
3443
3437
|
open: z10.string(),
|
|
@@ -3591,6 +3585,7 @@ var createClinicGroupSchema = z10.object({
|
|
|
3591
3585
|
calendarSyncEnabled: z10.boolean().optional(),
|
|
3592
3586
|
autoConfirmAppointments: z10.boolean().optional(),
|
|
3593
3587
|
businessIdentificationNumber: z10.string().optional().nullable(),
|
|
3588
|
+
tz: z10.string().nullable().optional(),
|
|
3594
3589
|
onboarding: z10.object({
|
|
3595
3590
|
completed: z10.boolean().optional().default(false),
|
|
3596
3591
|
step: z10.number().optional().default(1)
|
|
@@ -8342,7 +8337,10 @@ import {
|
|
|
8342
8337
|
writeBatch as writeBatch4,
|
|
8343
8338
|
arrayUnion as arrayUnion7
|
|
8344
8339
|
} from "firebase/firestore";
|
|
8345
|
-
import {
|
|
8340
|
+
import { getFunctions as getFunctions2, httpsCallable as httpsCallable2 } from "firebase/functions";
|
|
8341
|
+
import {
|
|
8342
|
+
geohashForLocation as geohashForLocation4
|
|
8343
|
+
} from "geofire-common";
|
|
8346
8344
|
import { z as z20 } from "zod";
|
|
8347
8345
|
|
|
8348
8346
|
// src/services/clinic/utils/clinic.utils.ts
|
|
@@ -9123,6 +9121,27 @@ var ClinicService = class extends BaseService {
|
|
|
9123
9121
|
this.clinicAdminService = clinicAdminService;
|
|
9124
9122
|
this.clinicGroupService = clinicGroupService;
|
|
9125
9123
|
this.mediaService = mediaService;
|
|
9124
|
+
this.functions = getFunctions2(app);
|
|
9125
|
+
}
|
|
9126
|
+
/**
|
|
9127
|
+
* Get timezone from coordinates using the callable function
|
|
9128
|
+
* @param lat Latitude
|
|
9129
|
+
* @param lng Longitude
|
|
9130
|
+
* @returns IANA timezone string
|
|
9131
|
+
*/
|
|
9132
|
+
async getTimezone(lat, lng) {
|
|
9133
|
+
try {
|
|
9134
|
+
const getTimezoneFromCoordinates = httpsCallable2(
|
|
9135
|
+
this.functions,
|
|
9136
|
+
"getTimezoneFromCoordinates"
|
|
9137
|
+
);
|
|
9138
|
+
const result = await getTimezoneFromCoordinates({ lat, lng });
|
|
9139
|
+
const data = result.data;
|
|
9140
|
+
return data.timezone;
|
|
9141
|
+
} catch (error) {
|
|
9142
|
+
console.error("Error getting timezone:", error);
|
|
9143
|
+
return null;
|
|
9144
|
+
}
|
|
9126
9145
|
}
|
|
9127
9146
|
/**
|
|
9128
9147
|
* Process media resource (string URL or File object)
|
|
@@ -9137,7 +9156,9 @@ var ClinicService = class extends BaseService {
|
|
|
9137
9156
|
return media;
|
|
9138
9157
|
}
|
|
9139
9158
|
if (media instanceof File || media instanceof Blob) {
|
|
9140
|
-
console.log(
|
|
9159
|
+
console.log(
|
|
9160
|
+
`[ClinicService] Uploading ${collectionName} media for ${ownerId}`
|
|
9161
|
+
);
|
|
9141
9162
|
const metadata = await this.mediaService.uploadMedia(
|
|
9142
9163
|
media,
|
|
9143
9164
|
ownerId,
|
|
@@ -9159,7 +9180,11 @@ var ClinicService = class extends BaseService {
|
|
|
9159
9180
|
if (!mediaArray || mediaArray.length === 0) return [];
|
|
9160
9181
|
const result = [];
|
|
9161
9182
|
for (const media of mediaArray) {
|
|
9162
|
-
const processedUrl = await this.processMedia(
|
|
9183
|
+
const processedUrl = await this.processMedia(
|
|
9184
|
+
media,
|
|
9185
|
+
ownerId,
|
|
9186
|
+
collectionName
|
|
9187
|
+
);
|
|
9163
9188
|
if (processedUrl) {
|
|
9164
9189
|
result.push(processedUrl);
|
|
9165
9190
|
}
|
|
@@ -9177,7 +9202,11 @@ var ClinicService = class extends BaseService {
|
|
|
9177
9202
|
if (!photosWithTags || photosWithTags.length === 0) return [];
|
|
9178
9203
|
const result = [];
|
|
9179
9204
|
for (const item of photosWithTags) {
|
|
9180
|
-
const processedUrl = await this.processMedia(
|
|
9205
|
+
const processedUrl = await this.processMedia(
|
|
9206
|
+
item.url,
|
|
9207
|
+
ownerId,
|
|
9208
|
+
collectionName
|
|
9209
|
+
);
|
|
9181
9210
|
if (processedUrl) {
|
|
9182
9211
|
result.push({
|
|
9183
9212
|
url: processedUrl,
|
|
@@ -9195,11 +9224,19 @@ var ClinicService = class extends BaseService {
|
|
|
9195
9224
|
try {
|
|
9196
9225
|
const clinicId = this.generateId();
|
|
9197
9226
|
const validatedData = createClinicSchema.parse(data);
|
|
9198
|
-
const group = await this.clinicGroupService.getClinicGroup(
|
|
9227
|
+
const group = await this.clinicGroupService.getClinicGroup(
|
|
9228
|
+
validatedData.clinicGroupId
|
|
9229
|
+
);
|
|
9199
9230
|
if (!group) {
|
|
9200
|
-
throw new Error(
|
|
9231
|
+
throw new Error(
|
|
9232
|
+
`Clinic group ${validatedData.clinicGroupId} not found`
|
|
9233
|
+
);
|
|
9201
9234
|
}
|
|
9202
|
-
const logoUrl = await this.processMedia(
|
|
9235
|
+
const logoUrl = await this.processMedia(
|
|
9236
|
+
validatedData.logo,
|
|
9237
|
+
clinicId,
|
|
9238
|
+
"clinic-logos"
|
|
9239
|
+
);
|
|
9203
9240
|
const coverPhotoUrl = await this.processMedia(
|
|
9204
9241
|
validatedData.coverPhoto,
|
|
9205
9242
|
clinicId,
|
|
@@ -9217,6 +9254,7 @@ var ClinicService = class extends BaseService {
|
|
|
9217
9254
|
);
|
|
9218
9255
|
const location = validatedData.location;
|
|
9219
9256
|
const hash = geohashForLocation4([location.latitude, location.longitude]);
|
|
9257
|
+
const tz = await this.getTimezone(location.latitude, location.longitude);
|
|
9220
9258
|
const defaultReviewInfo = {
|
|
9221
9259
|
totalReviews: 0,
|
|
9222
9260
|
averageRating: 0,
|
|
@@ -9234,7 +9272,7 @@ var ClinicService = class extends BaseService {
|
|
|
9234
9272
|
nameLower: validatedData.name.toLowerCase(),
|
|
9235
9273
|
// Add this line
|
|
9236
9274
|
description: validatedData.description,
|
|
9237
|
-
location: { ...location, geohash: hash },
|
|
9275
|
+
location: { ...location, geohash: hash, tz },
|
|
9238
9276
|
contactInfo: validatedData.contactInfo,
|
|
9239
9277
|
workingHours: validatedData.workingHours,
|
|
9240
9278
|
tags: validatedData.tags,
|
|
@@ -9289,7 +9327,11 @@ var ClinicService = class extends BaseService {
|
|
|
9289
9327
|
const validatedData = updateClinicSchema.parse(data);
|
|
9290
9328
|
const updatePayload = {};
|
|
9291
9329
|
if (validatedData.logo !== void 0) {
|
|
9292
|
-
updatePayload.logo = await this.processMedia(
|
|
9330
|
+
updatePayload.logo = await this.processMedia(
|
|
9331
|
+
validatedData.logo,
|
|
9332
|
+
clinicId,
|
|
9333
|
+
"clinic-logos"
|
|
9334
|
+
);
|
|
9293
9335
|
}
|
|
9294
9336
|
if (validatedData.coverPhoto !== void 0) {
|
|
9295
9337
|
updatePayload.coverPhoto = await this.processMedia(
|
|
@@ -9334,9 +9376,11 @@ var ClinicService = class extends BaseService {
|
|
|
9334
9376
|
}
|
|
9335
9377
|
if (validatedData.location) {
|
|
9336
9378
|
const loc = validatedData.location;
|
|
9379
|
+
const tz = await this.getTimezone(loc.latitude, loc.longitude);
|
|
9337
9380
|
updatePayload.location = {
|
|
9338
9381
|
...loc,
|
|
9339
|
-
geohash: geohashForLocation4([loc.latitude, loc.longitude])
|
|
9382
|
+
geohash: geohashForLocation4([loc.latitude, loc.longitude]),
|
|
9383
|
+
tz
|
|
9340
9384
|
};
|
|
9341
9385
|
}
|
|
9342
9386
|
updatePayload.updatedAt = serverTimestamp14();
|
|
@@ -9389,10 +9433,22 @@ var ClinicService = class extends BaseService {
|
|
|
9389
9433
|
* Pretražuje klinike u određenom radijusu
|
|
9390
9434
|
*/
|
|
9391
9435
|
async findClinicsInRadius(center, radiusInKm, filters) {
|
|
9392
|
-
return findClinicsInRadius(
|
|
9436
|
+
return findClinicsInRadius(
|
|
9437
|
+
this.db,
|
|
9438
|
+
center,
|
|
9439
|
+
radiusInKm,
|
|
9440
|
+
filters
|
|
9441
|
+
);
|
|
9393
9442
|
}
|
|
9394
9443
|
async addTags(clinicId, adminId, newTags) {
|
|
9395
|
-
return addTags(
|
|
9444
|
+
return addTags(
|
|
9445
|
+
this.db,
|
|
9446
|
+
clinicId,
|
|
9447
|
+
adminId,
|
|
9448
|
+
newTags,
|
|
9449
|
+
this.clinicAdminService,
|
|
9450
|
+
this.app
|
|
9451
|
+
);
|
|
9396
9452
|
}
|
|
9397
9453
|
async removeTags(clinicId, adminId, tagsToRemove) {
|
|
9398
9454
|
return removeTags(
|
|
@@ -9430,7 +9486,9 @@ var ClinicService = class extends BaseService {
|
|
|
9430
9486
|
clinicGroupId,
|
|
9431
9487
|
adminId
|
|
9432
9488
|
});
|
|
9433
|
-
const clinicGroup = await this.clinicGroupService.getClinicGroup(
|
|
9489
|
+
const clinicGroup = await this.clinicGroupService.getClinicGroup(
|
|
9490
|
+
clinicGroupId
|
|
9491
|
+
);
|
|
9434
9492
|
if (!clinicGroup) {
|
|
9435
9493
|
console.error("[CLINIC_SERVICE] Clinic group not found", {
|
|
9436
9494
|
clinicGroupId
|
|
@@ -9476,7 +9534,13 @@ var ClinicService = class extends BaseService {
|
|
|
9476
9534
|
return getAllClinics(this.db, pagination, lastDoc);
|
|
9477
9535
|
}
|
|
9478
9536
|
async getAllClinicsInRange(center, rangeInKm, pagination, lastDoc) {
|
|
9479
|
-
return getAllClinicsInRange(
|
|
9537
|
+
return getAllClinicsInRange(
|
|
9538
|
+
this.db,
|
|
9539
|
+
center,
|
|
9540
|
+
rangeInKm,
|
|
9541
|
+
pagination,
|
|
9542
|
+
lastDoc
|
|
9543
|
+
);
|
|
9480
9544
|
}
|
|
9481
9545
|
/**
|
|
9482
9546
|
* Get clinics based on multiple filtering criteria
|
|
@@ -10706,7 +10770,7 @@ async function updatePractitionerCalendarEventUtil(db, practitionerId, eventId,
|
|
|
10706
10770
|
}
|
|
10707
10771
|
|
|
10708
10772
|
// src/services/calendar/utils/appointment.utils.ts
|
|
10709
|
-
async function
|
|
10773
|
+
async function createAppointmentUtil(db, clinicId, practitionerId, patientId, eventData, generateId2) {
|
|
10710
10774
|
const eventId = generateId2();
|
|
10711
10775
|
const autoConfirm = await checkAutoConfirmAppointmentsUtil(db, clinicId);
|
|
10712
10776
|
const initialStatus = autoConfirm ? "confirmed" /* CONFIRMED */ : "pending" /* PENDING */;
|
|
@@ -12048,7 +12112,7 @@ var CalendarServiceV2 = class extends BaseService {
|
|
|
12048
12112
|
syncStatus: "internal" /* INTERNAL */,
|
|
12049
12113
|
eventType: "appointment" /* APPOINTMENT */
|
|
12050
12114
|
};
|
|
12051
|
-
const appointment = await
|
|
12115
|
+
const appointment = await createAppointmentUtil(
|
|
12052
12116
|
this.db,
|
|
12053
12117
|
params.clinicId,
|
|
12054
12118
|
params.doctorId,
|
|
@@ -14838,7 +14902,8 @@ import {
|
|
|
14838
14902
|
import { z as z24 } from "zod";
|
|
14839
14903
|
var createProcedureSchema = z24.object({
|
|
14840
14904
|
name: z24.string().min(1).max(200),
|
|
14841
|
-
|
|
14905
|
+
// Optional: service will derive from name if not provided by client
|
|
14906
|
+
nameLower: z24.string().min(1).max(200).optional(),
|
|
14842
14907
|
description: z24.string().min(1).max(2e3),
|
|
14843
14908
|
family: z24.nativeEnum(ProcedureFamily),
|
|
14844
14909
|
categoryId: z24.string().min(1),
|
|
@@ -14931,7 +14996,9 @@ var ProcedureService = class extends BaseService {
|
|
|
14931
14996
|
return media;
|
|
14932
14997
|
}
|
|
14933
14998
|
if (media instanceof File || media instanceof Blob) {
|
|
14934
|
-
console.log(
|
|
14999
|
+
console.log(
|
|
15000
|
+
`[ProcedureService] Uploading ${collectionName} media for ${ownerId}`
|
|
15001
|
+
);
|
|
14935
15002
|
const metadata = await this.mediaService.uploadMedia(
|
|
14936
15003
|
media,
|
|
14937
15004
|
ownerId,
|
|
@@ -14953,7 +15020,11 @@ var ProcedureService = class extends BaseService {
|
|
|
14953
15020
|
if (!mediaArray || mediaArray.length === 0) return [];
|
|
14954
15021
|
const result = [];
|
|
14955
15022
|
for (const media of mediaArray) {
|
|
14956
|
-
const processedUrl = await this.processMedia(
|
|
15023
|
+
const processedUrl = await this.processMedia(
|
|
15024
|
+
media,
|
|
15025
|
+
ownerId,
|
|
15026
|
+
collectionName
|
|
15027
|
+
);
|
|
14957
15028
|
if (processedUrl) {
|
|
14958
15029
|
result.push(processedUrl);
|
|
14959
15030
|
}
|
|
@@ -14966,28 +15037,46 @@ var ProcedureService = class extends BaseService {
|
|
|
14966
15037
|
* @returns The created procedure
|
|
14967
15038
|
*/
|
|
14968
15039
|
async createProcedure(data) {
|
|
14969
|
-
var _a;
|
|
15040
|
+
var _a, _b, _c;
|
|
14970
15041
|
const validatedData = createProcedureSchema.parse(data);
|
|
14971
15042
|
const procedureId = this.generateId();
|
|
14972
15043
|
const [category, subcategory, technology, product] = await Promise.all([
|
|
14973
15044
|
this.categoryService.getById(validatedData.categoryId),
|
|
14974
|
-
this.subcategoryService.getById(
|
|
15045
|
+
this.subcategoryService.getById(
|
|
15046
|
+
validatedData.categoryId,
|
|
15047
|
+
validatedData.subcategoryId
|
|
15048
|
+
),
|
|
14975
15049
|
this.technologyService.getById(validatedData.technologyId),
|
|
14976
|
-
this.productService.getById(
|
|
15050
|
+
this.productService.getById(
|
|
15051
|
+
validatedData.technologyId,
|
|
15052
|
+
validatedData.productId
|
|
15053
|
+
)
|
|
14977
15054
|
]);
|
|
14978
15055
|
if (!category || !subcategory || !technology || !product) {
|
|
14979
15056
|
throw new Error("One or more required base entities not found");
|
|
14980
15057
|
}
|
|
14981
|
-
const clinicRef = doc30(
|
|
15058
|
+
const clinicRef = doc30(
|
|
15059
|
+
this.db,
|
|
15060
|
+
CLINICS_COLLECTION,
|
|
15061
|
+
validatedData.clinicBranchId
|
|
15062
|
+
);
|
|
14982
15063
|
const clinicSnapshot = await getDoc32(clinicRef);
|
|
14983
15064
|
if (!clinicSnapshot.exists()) {
|
|
14984
|
-
throw new Error(
|
|
15065
|
+
throw new Error(
|
|
15066
|
+
`Clinic with ID ${validatedData.clinicBranchId} not found`
|
|
15067
|
+
);
|
|
14985
15068
|
}
|
|
14986
15069
|
const clinic = clinicSnapshot.data();
|
|
14987
|
-
const practitionerRef = doc30(
|
|
15070
|
+
const practitionerRef = doc30(
|
|
15071
|
+
this.db,
|
|
15072
|
+
PRACTITIONERS_COLLECTION,
|
|
15073
|
+
validatedData.practitionerId
|
|
15074
|
+
);
|
|
14988
15075
|
const practitionerSnapshot = await getDoc32(practitionerRef);
|
|
14989
15076
|
if (!practitionerSnapshot.exists()) {
|
|
14990
|
-
throw new Error(
|
|
15077
|
+
throw new Error(
|
|
15078
|
+
`Practitioner with ID ${validatedData.practitionerId} not found`
|
|
15079
|
+
);
|
|
14991
15080
|
}
|
|
14992
15081
|
const practitioner = practitionerSnapshot.data();
|
|
14993
15082
|
let processedPhotos = [];
|
|
@@ -15018,6 +15107,7 @@ var ProcedureService = class extends BaseService {
|
|
|
15018
15107
|
const newProcedure = {
|
|
15019
15108
|
id: procedureId,
|
|
15020
15109
|
...validatedData,
|
|
15110
|
+
// Ensure nameLower is always set even if omitted by client
|
|
15021
15111
|
nameLower: validatedData.nameLower || validatedData.name.toLowerCase(),
|
|
15022
15112
|
photos: processedPhotos,
|
|
15023
15113
|
category,
|
|
@@ -15027,7 +15117,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15027
15117
|
product,
|
|
15028
15118
|
blockingConditions: technology.blockingConditions,
|
|
15029
15119
|
contraindications: technology.contraindications || [],
|
|
15120
|
+
contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
|
|
15030
15121
|
treatmentBenefits: technology.benefits,
|
|
15122
|
+
treatmentBenefitIds: ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [],
|
|
15031
15123
|
preRequirements: technology.requirements.pre,
|
|
15032
15124
|
postRequirements: technology.requirements.post,
|
|
15033
15125
|
certificationRequirement: technology.certificationRequirement,
|
|
@@ -15068,7 +15160,7 @@ var ProcedureService = class extends BaseService {
|
|
|
15068
15160
|
* @returns A promise that resolves to an array of the newly created procedures.
|
|
15069
15161
|
*/
|
|
15070
15162
|
async bulkCreateProcedures(baseData, practitionerIds) {
|
|
15071
|
-
var _a;
|
|
15163
|
+
var _a, _b, _c;
|
|
15072
15164
|
if (!practitionerIds || practitionerIds.length === 0) {
|
|
15073
15165
|
throw new Error("Practitioner IDs array cannot be empty.");
|
|
15074
15166
|
}
|
|
@@ -15076,16 +15168,24 @@ var ProcedureService = class extends BaseService {
|
|
|
15076
15168
|
const validatedData = createProcedureSchema.parse(validationData);
|
|
15077
15169
|
const [category, subcategory, technology, product, clinicSnapshot] = await Promise.all([
|
|
15078
15170
|
this.categoryService.getById(validatedData.categoryId),
|
|
15079
|
-
this.subcategoryService.getById(
|
|
15171
|
+
this.subcategoryService.getById(
|
|
15172
|
+
validatedData.categoryId,
|
|
15173
|
+
validatedData.subcategoryId
|
|
15174
|
+
),
|
|
15080
15175
|
this.technologyService.getById(validatedData.technologyId),
|
|
15081
|
-
this.productService.getById(
|
|
15176
|
+
this.productService.getById(
|
|
15177
|
+
validatedData.technologyId,
|
|
15178
|
+
validatedData.productId
|
|
15179
|
+
),
|
|
15082
15180
|
getDoc32(doc30(this.db, CLINICS_COLLECTION, validatedData.clinicBranchId))
|
|
15083
15181
|
]);
|
|
15084
15182
|
if (!category || !subcategory || !technology || !product) {
|
|
15085
15183
|
throw new Error("One or more required base entities not found");
|
|
15086
15184
|
}
|
|
15087
15185
|
if (!clinicSnapshot.exists()) {
|
|
15088
|
-
throw new Error(
|
|
15186
|
+
throw new Error(
|
|
15187
|
+
`Clinic with ID ${validatedData.clinicBranchId} not found`
|
|
15188
|
+
);
|
|
15089
15189
|
}
|
|
15090
15190
|
const clinic = clinicSnapshot.data();
|
|
15091
15191
|
let processedPhotos = [];
|
|
@@ -15111,8 +15211,12 @@ var ProcedureService = class extends BaseService {
|
|
|
15111
15211
|
}
|
|
15112
15212
|
if (practitionersMap.size !== practitionerIds.length) {
|
|
15113
15213
|
const foundIds = Array.from(practitionersMap.keys());
|
|
15114
|
-
const notFoundIds = practitionerIds.filter(
|
|
15115
|
-
|
|
15214
|
+
const notFoundIds = practitionerIds.filter(
|
|
15215
|
+
(id) => !foundIds.includes(id)
|
|
15216
|
+
);
|
|
15217
|
+
throw new Error(
|
|
15218
|
+
`The following practitioners were not found: ${notFoundIds.join(", ")}`
|
|
15219
|
+
);
|
|
15116
15220
|
}
|
|
15117
15221
|
const batch = writeBatch6(this.db);
|
|
15118
15222
|
const createdProcedureIds = [];
|
|
@@ -15150,7 +15254,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15150
15254
|
product,
|
|
15151
15255
|
blockingConditions: technology.blockingConditions,
|
|
15152
15256
|
contraindications: technology.contraindications || [],
|
|
15257
|
+
contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
|
|
15153
15258
|
treatmentBenefits: technology.benefits,
|
|
15259
|
+
treatmentBenefitIds: ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [],
|
|
15154
15260
|
preRequirements: technology.requirements.pre,
|
|
15155
15261
|
postRequirements: technology.requirements.post,
|
|
15156
15262
|
certificationRequirement: technology.certificationRequirement,
|
|
@@ -15180,7 +15286,10 @@ var ProcedureService = class extends BaseService {
|
|
|
15180
15286
|
const fetchedProcedures = [];
|
|
15181
15287
|
for (let i = 0; i < createdProcedureIds.length; i += 30) {
|
|
15182
15288
|
const chunk = createdProcedureIds.slice(i, i + 30);
|
|
15183
|
-
const q = query29(
|
|
15289
|
+
const q = query29(
|
|
15290
|
+
collection29(this.db, PROCEDURES_COLLECTION),
|
|
15291
|
+
where29(documentId2(), "in", chunk)
|
|
15292
|
+
);
|
|
15184
15293
|
const snapshot = await getDocs29(q);
|
|
15185
15294
|
snapshot.forEach((doc37) => {
|
|
15186
15295
|
fetchedProcedures.push(doc37.data());
|
|
@@ -15250,7 +15359,7 @@ var ProcedureService = class extends BaseService {
|
|
|
15250
15359
|
* @returns The updated procedure
|
|
15251
15360
|
*/
|
|
15252
15361
|
async updateProcedure(id, data) {
|
|
15253
|
-
var _a;
|
|
15362
|
+
var _a, _b, _c;
|
|
15254
15363
|
const validatedData = updateProcedureSchema.parse(data);
|
|
15255
15364
|
const procedureRef = doc30(this.db, PROCEDURES_COLLECTION, id);
|
|
15256
15365
|
const procedureSnapshot = await getDoc32(procedureRef);
|
|
@@ -15281,7 +15390,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15281
15390
|
);
|
|
15282
15391
|
const newPractitionerSnap = await getDoc32(newPractitionerRef);
|
|
15283
15392
|
if (!newPractitionerSnap.exists())
|
|
15284
|
-
throw new Error(
|
|
15393
|
+
throw new Error(
|
|
15394
|
+
`New Practitioner ${validatedData.practitionerId} not found`
|
|
15395
|
+
);
|
|
15285
15396
|
newPractitioner = newPractitionerSnap.data();
|
|
15286
15397
|
updatedProcedureData.doctorInfo = {
|
|
15287
15398
|
id: newPractitioner.id,
|
|
@@ -15295,7 +15406,11 @@ var ProcedureService = class extends BaseService {
|
|
|
15295
15406
|
}
|
|
15296
15407
|
if (validatedData.clinicBranchId && validatedData.clinicBranchId !== oldClinicId) {
|
|
15297
15408
|
clinicChanged = true;
|
|
15298
|
-
const newClinicRef = doc30(
|
|
15409
|
+
const newClinicRef = doc30(
|
|
15410
|
+
this.db,
|
|
15411
|
+
CLINICS_COLLECTION,
|
|
15412
|
+
validatedData.clinicBranchId
|
|
15413
|
+
);
|
|
15299
15414
|
const newClinicSnap = await getDoc32(newClinicRef);
|
|
15300
15415
|
if (!newClinicSnap.exists())
|
|
15301
15416
|
throw new Error(`New Clinic ${validatedData.clinicBranchId} not found`);
|
|
@@ -15314,8 +15429,11 @@ var ProcedureService = class extends BaseService {
|
|
|
15314
15429
|
updatedProcedureData.nameLower = validatedData.name.toLowerCase();
|
|
15315
15430
|
}
|
|
15316
15431
|
if (validatedData.categoryId) {
|
|
15317
|
-
const category = await this.categoryService.getById(
|
|
15318
|
-
|
|
15432
|
+
const category = await this.categoryService.getById(
|
|
15433
|
+
validatedData.categoryId
|
|
15434
|
+
);
|
|
15435
|
+
if (!category)
|
|
15436
|
+
throw new Error(`Category ${validatedData.categoryId} not found`);
|
|
15319
15437
|
updatedProcedureData.category = category;
|
|
15320
15438
|
finalCategoryId = category.id;
|
|
15321
15439
|
}
|
|
@@ -15330,23 +15448,34 @@ var ProcedureService = class extends BaseService {
|
|
|
15330
15448
|
);
|
|
15331
15449
|
updatedProcedureData.subcategory = subcategory;
|
|
15332
15450
|
} else if (validatedData.subcategoryId) {
|
|
15333
|
-
console.warn(
|
|
15451
|
+
console.warn(
|
|
15452
|
+
"Attempted to update subcategory without a valid categoryId"
|
|
15453
|
+
);
|
|
15334
15454
|
}
|
|
15335
15455
|
let finalTechnologyId = existingProcedure.technology.id;
|
|
15336
15456
|
if (validatedData.technologyId) {
|
|
15337
|
-
const technology = await this.technologyService.getById(
|
|
15338
|
-
|
|
15457
|
+
const technology = await this.technologyService.getById(
|
|
15458
|
+
validatedData.technologyId
|
|
15459
|
+
);
|
|
15460
|
+
if (!technology)
|
|
15461
|
+
throw new Error(`Technology ${validatedData.technologyId} not found`);
|
|
15339
15462
|
updatedProcedureData.technology = technology;
|
|
15340
15463
|
finalTechnologyId = technology.id;
|
|
15341
15464
|
updatedProcedureData.blockingConditions = technology.blockingConditions;
|
|
15465
|
+
updatedProcedureData.contraindications = technology.contraindications || [];
|
|
15466
|
+
updatedProcedureData.contraindicationIds = ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [];
|
|
15342
15467
|
updatedProcedureData.treatmentBenefits = technology.benefits;
|
|
15468
|
+
updatedProcedureData.treatmentBenefitIds = ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [];
|
|
15343
15469
|
updatedProcedureData.preRequirements = technology.requirements.pre;
|
|
15344
15470
|
updatedProcedureData.postRequirements = technology.requirements.post;
|
|
15345
15471
|
updatedProcedureData.certificationRequirement = technology.certificationRequirement;
|
|
15346
15472
|
updatedProcedureData.documentationTemplates = technology.documentationTemplates || [];
|
|
15347
15473
|
}
|
|
15348
15474
|
if (validatedData.productId && finalTechnologyId) {
|
|
15349
|
-
const product = await this.productService.getById(
|
|
15475
|
+
const product = await this.productService.getById(
|
|
15476
|
+
finalTechnologyId,
|
|
15477
|
+
validatedData.productId
|
|
15478
|
+
);
|
|
15350
15479
|
if (!product)
|
|
15351
15480
|
throw new Error(
|
|
15352
15481
|
`Product ${validatedData.productId} not found for technology ${finalTechnologyId}`
|
|
@@ -15428,7 +15557,11 @@ var ProcedureService = class extends BaseService {
|
|
|
15428
15557
|
limit16(pagination)
|
|
15429
15558
|
);
|
|
15430
15559
|
} else {
|
|
15431
|
-
proceduresQuery = query29(
|
|
15560
|
+
proceduresQuery = query29(
|
|
15561
|
+
proceduresCollection,
|
|
15562
|
+
orderBy17("name"),
|
|
15563
|
+
limit16(pagination)
|
|
15564
|
+
);
|
|
15432
15565
|
}
|
|
15433
15566
|
} else {
|
|
15434
15567
|
proceduresQuery = query29(proceduresCollection, orderBy17("name"));
|
|
@@ -15459,7 +15592,7 @@ var ProcedureService = class extends BaseService {
|
|
|
15459
15592
|
*
|
|
15460
15593
|
* @param filters - Various filters to apply
|
|
15461
15594
|
* @param filters.nameSearch - Optional search text for procedure name
|
|
15462
|
-
* @param filters.
|
|
15595
|
+
* @param filters.treatmentBenefitIds - Optional array of treatment benefits to filter by
|
|
15463
15596
|
* @param filters.procedureFamily - Optional procedure family to filter by
|
|
15464
15597
|
* @param filters.procedureCategory - Optional procedure category to filter by
|
|
15465
15598
|
* @param filters.procedureSubcategory - Optional procedure subcategory to filter by
|
|
@@ -15477,7 +15610,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15477
15610
|
*/
|
|
15478
15611
|
async getProceduresByFilters(filters) {
|
|
15479
15612
|
try {
|
|
15480
|
-
console.log(
|
|
15613
|
+
console.log(
|
|
15614
|
+
"[PROCEDURE_SERVICE] Starting procedure filtering with multiple strategies"
|
|
15615
|
+
);
|
|
15481
15616
|
if (filters.location && filters.radiusInKm) {
|
|
15482
15617
|
console.log("[PROCEDURE_SERVICE] Executing geo query:", {
|
|
15483
15618
|
location: filters.location,
|
|
@@ -15485,7 +15620,10 @@ var ProcedureService = class extends BaseService {
|
|
|
15485
15620
|
serviceName: "ProcedureService"
|
|
15486
15621
|
});
|
|
15487
15622
|
if (!filters.location.latitude || !filters.location.longitude) {
|
|
15488
|
-
console.warn(
|
|
15623
|
+
console.warn(
|
|
15624
|
+
"[PROCEDURE_SERVICE] Invalid location data:",
|
|
15625
|
+
filters.location
|
|
15626
|
+
);
|
|
15489
15627
|
filters.location = void 0;
|
|
15490
15628
|
filters.radiusInKm = void 0;
|
|
15491
15629
|
}
|
|
@@ -15505,13 +15643,19 @@ var ProcedureService = class extends BaseService {
|
|
|
15505
15643
|
constraints.push(where29("family", "==", filters.procedureFamily));
|
|
15506
15644
|
}
|
|
15507
15645
|
if (filters.procedureCategory) {
|
|
15508
|
-
constraints.push(
|
|
15646
|
+
constraints.push(
|
|
15647
|
+
where29("category.id", "==", filters.procedureCategory)
|
|
15648
|
+
);
|
|
15509
15649
|
}
|
|
15510
15650
|
if (filters.procedureSubcategory) {
|
|
15511
|
-
constraints.push(
|
|
15651
|
+
constraints.push(
|
|
15652
|
+
where29("subcategory.id", "==", filters.procedureSubcategory)
|
|
15653
|
+
);
|
|
15512
15654
|
}
|
|
15513
15655
|
if (filters.procedureTechnology) {
|
|
15514
|
-
constraints.push(
|
|
15656
|
+
constraints.push(
|
|
15657
|
+
where29("technology.id", "==", filters.procedureTechnology)
|
|
15658
|
+
);
|
|
15515
15659
|
}
|
|
15516
15660
|
if (filters.minPrice !== void 0) {
|
|
15517
15661
|
constraints.push(where29("price", ">=", filters.minPrice));
|
|
@@ -15520,20 +15664,32 @@ var ProcedureService = class extends BaseService {
|
|
|
15520
15664
|
constraints.push(where29("price", "<=", filters.maxPrice));
|
|
15521
15665
|
}
|
|
15522
15666
|
if (filters.minRating !== void 0) {
|
|
15523
|
-
constraints.push(
|
|
15667
|
+
constraints.push(
|
|
15668
|
+
where29("reviewInfo.averageRating", ">=", filters.minRating)
|
|
15669
|
+
);
|
|
15524
15670
|
}
|
|
15525
15671
|
if (filters.maxRating !== void 0) {
|
|
15526
|
-
constraints.push(
|
|
15672
|
+
constraints.push(
|
|
15673
|
+
where29("reviewInfo.averageRating", "<=", filters.maxRating)
|
|
15674
|
+
);
|
|
15527
15675
|
}
|
|
15528
15676
|
if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
|
|
15529
|
-
const
|
|
15530
|
-
constraints.push(
|
|
15677
|
+
const benefitIdsToMatch = filters.treatmentBenefits;
|
|
15678
|
+
constraints.push(
|
|
15679
|
+
where29(
|
|
15680
|
+
"treatmentBenefitIds",
|
|
15681
|
+
"array-contains-any",
|
|
15682
|
+
benefitIdsToMatch
|
|
15683
|
+
)
|
|
15684
|
+
);
|
|
15531
15685
|
}
|
|
15532
15686
|
return constraints;
|
|
15533
15687
|
};
|
|
15534
15688
|
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
15535
15689
|
try {
|
|
15536
|
-
console.log(
|
|
15690
|
+
console.log(
|
|
15691
|
+
"[PROCEDURE_SERVICE] Strategy 1: Trying nameLower search"
|
|
15692
|
+
);
|
|
15537
15693
|
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
15538
15694
|
const constraints = getBaseConstraints();
|
|
15539
15695
|
constraints.push(where29("nameLower", ">=", searchTerm));
|
|
@@ -15549,13 +15705,18 @@ var ProcedureService = class extends BaseService {
|
|
|
15549
15705
|
}
|
|
15550
15706
|
}
|
|
15551
15707
|
constraints.push(limit15(filters.pagination || 10));
|
|
15552
|
-
const q = query29(
|
|
15708
|
+
const q = query29(
|
|
15709
|
+
collection29(this.db, PROCEDURES_COLLECTION),
|
|
15710
|
+
...constraints
|
|
15711
|
+
);
|
|
15553
15712
|
const querySnapshot = await getDocs29(q);
|
|
15554
15713
|
const procedures = querySnapshot.docs.map(
|
|
15555
15714
|
(doc37) => ({ ...doc37.data(), id: doc37.id })
|
|
15556
15715
|
);
|
|
15557
15716
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
15558
|
-
console.log(
|
|
15717
|
+
console.log(
|
|
15718
|
+
`[PROCEDURE_SERVICE] Strategy 1 success: ${procedures.length} procedures`
|
|
15719
|
+
);
|
|
15559
15720
|
if (procedures.length < (filters.pagination || 10)) {
|
|
15560
15721
|
return { procedures, lastDoc: null };
|
|
15561
15722
|
}
|
|
@@ -15566,7 +15727,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15566
15727
|
}
|
|
15567
15728
|
if (filters.nameSearch && filters.nameSearch.trim()) {
|
|
15568
15729
|
try {
|
|
15569
|
-
console.log(
|
|
15730
|
+
console.log(
|
|
15731
|
+
"[PROCEDURE_SERVICE] Strategy 2: Trying name field search"
|
|
15732
|
+
);
|
|
15570
15733
|
const searchTerm = filters.nameSearch.trim().toLowerCase();
|
|
15571
15734
|
const constraints = getBaseConstraints();
|
|
15572
15735
|
constraints.push(where29("name", ">=", searchTerm));
|
|
@@ -15582,13 +15745,18 @@ var ProcedureService = class extends BaseService {
|
|
|
15582
15745
|
}
|
|
15583
15746
|
}
|
|
15584
15747
|
constraints.push(limit15(filters.pagination || 10));
|
|
15585
|
-
const q = query29(
|
|
15748
|
+
const q = query29(
|
|
15749
|
+
collection29(this.db, PROCEDURES_COLLECTION),
|
|
15750
|
+
...constraints
|
|
15751
|
+
);
|
|
15586
15752
|
const querySnapshot = await getDocs29(q);
|
|
15587
15753
|
const procedures = querySnapshot.docs.map(
|
|
15588
15754
|
(doc37) => ({ ...doc37.data(), id: doc37.id })
|
|
15589
15755
|
);
|
|
15590
15756
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
15591
|
-
console.log(
|
|
15757
|
+
console.log(
|
|
15758
|
+
`[PROCEDURE_SERVICE] Strategy 2 success: ${procedures.length} procedures`
|
|
15759
|
+
);
|
|
15592
15760
|
if (procedures.length < (filters.pagination || 10)) {
|
|
15593
15761
|
return { procedures, lastDoc: null };
|
|
15594
15762
|
}
|
|
@@ -15613,14 +15781,19 @@ var ProcedureService = class extends BaseService {
|
|
|
15613
15781
|
}
|
|
15614
15782
|
}
|
|
15615
15783
|
constraints.push(limit15(filters.pagination || 10));
|
|
15616
|
-
const q = query29(
|
|
15784
|
+
const q = query29(
|
|
15785
|
+
collection29(this.db, PROCEDURES_COLLECTION),
|
|
15786
|
+
...constraints
|
|
15787
|
+
);
|
|
15617
15788
|
const querySnapshot = await getDocs29(q);
|
|
15618
15789
|
let procedures = querySnapshot.docs.map(
|
|
15619
15790
|
(doc37) => ({ ...doc37.data(), id: doc37.id })
|
|
15620
15791
|
);
|
|
15621
15792
|
procedures = this.applyInMemoryFilters(procedures, filters);
|
|
15622
15793
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
15623
|
-
console.log(
|
|
15794
|
+
console.log(
|
|
15795
|
+
`[PROCEDURE_SERVICE] Strategy 3 success: ${procedures.length} procedures`
|
|
15796
|
+
);
|
|
15624
15797
|
if (procedures.length < (filters.pagination || 10)) {
|
|
15625
15798
|
return { procedures, lastDoc: null };
|
|
15626
15799
|
}
|
|
@@ -15635,14 +15808,19 @@ var ProcedureService = class extends BaseService {
|
|
|
15635
15808
|
orderBy17("createdAt", "desc"),
|
|
15636
15809
|
limit15(filters.pagination || 10)
|
|
15637
15810
|
];
|
|
15638
|
-
const q = query29(
|
|
15811
|
+
const q = query29(
|
|
15812
|
+
collection29(this.db, PROCEDURES_COLLECTION),
|
|
15813
|
+
...constraints
|
|
15814
|
+
);
|
|
15639
15815
|
const querySnapshot = await getDocs29(q);
|
|
15640
15816
|
let procedures = querySnapshot.docs.map(
|
|
15641
15817
|
(doc37) => ({ ...doc37.data(), id: doc37.id })
|
|
15642
15818
|
);
|
|
15643
15819
|
procedures = this.applyInMemoryFilters(procedures, filters);
|
|
15644
15820
|
const lastDoc = querySnapshot.docs.length > 0 ? querySnapshot.docs[querySnapshot.docs.length - 1] : null;
|
|
15645
|
-
console.log(
|
|
15821
|
+
console.log(
|
|
15822
|
+
`[PROCEDURE_SERVICE] Strategy 4 success: ${procedures.length} procedures`
|
|
15823
|
+
);
|
|
15646
15824
|
if (procedures.length < (filters.pagination || 10)) {
|
|
15647
15825
|
return { procedures, lastDoc: null };
|
|
15648
15826
|
}
|
|
@@ -15650,7 +15828,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15650
15828
|
} catch (error) {
|
|
15651
15829
|
console.log("[PROCEDURE_SERVICE] Strategy 4 failed:", error);
|
|
15652
15830
|
}
|
|
15653
|
-
console.log(
|
|
15831
|
+
console.log(
|
|
15832
|
+
"[PROCEDURE_SERVICE] All strategies failed, returning empty result"
|
|
15833
|
+
);
|
|
15654
15834
|
return { procedures: [], lastDoc: null };
|
|
15655
15835
|
} catch (error) {
|
|
15656
15836
|
console.error("[PROCEDURE_SERVICE] Error filtering procedures:", error);
|
|
@@ -15670,13 +15850,17 @@ var ProcedureService = class extends BaseService {
|
|
|
15670
15850
|
const nameLower = procedure.nameLower || "";
|
|
15671
15851
|
return name.includes(searchTerm) || nameLower.includes(searchTerm);
|
|
15672
15852
|
});
|
|
15673
|
-
console.log(
|
|
15853
|
+
console.log(
|
|
15854
|
+
`[PROCEDURE_SERVICE] Applied name filter, results: ${filteredProcedures.length}`
|
|
15855
|
+
);
|
|
15674
15856
|
}
|
|
15675
15857
|
if (filters.minPrice !== void 0 || filters.maxPrice !== void 0) {
|
|
15676
15858
|
filteredProcedures = filteredProcedures.filter((procedure) => {
|
|
15677
15859
|
const price = procedure.price || 0;
|
|
15678
|
-
if (filters.minPrice !== void 0 && price < filters.minPrice)
|
|
15679
|
-
|
|
15860
|
+
if (filters.minPrice !== void 0 && price < filters.minPrice)
|
|
15861
|
+
return false;
|
|
15862
|
+
if (filters.maxPrice !== void 0 && price > filters.maxPrice)
|
|
15863
|
+
return false;
|
|
15680
15864
|
return true;
|
|
15681
15865
|
});
|
|
15682
15866
|
console.log(
|
|
@@ -15687,8 +15871,10 @@ var ProcedureService = class extends BaseService {
|
|
|
15687
15871
|
filteredProcedures = filteredProcedures.filter((procedure) => {
|
|
15688
15872
|
var _a;
|
|
15689
15873
|
const rating = ((_a = procedure.reviewInfo) == null ? void 0 : _a.averageRating) || 0;
|
|
15690
|
-
if (filters.minRating !== void 0 && rating < filters.minRating)
|
|
15691
|
-
|
|
15874
|
+
if (filters.minRating !== void 0 && rating < filters.minRating)
|
|
15875
|
+
return false;
|
|
15876
|
+
if (filters.maxRating !== void 0 && rating > filters.maxRating)
|
|
15877
|
+
return false;
|
|
15692
15878
|
return true;
|
|
15693
15879
|
});
|
|
15694
15880
|
console.log(
|
|
@@ -15696,10 +15882,12 @@ var ProcedureService = class extends BaseService {
|
|
|
15696
15882
|
);
|
|
15697
15883
|
}
|
|
15698
15884
|
if (filters.treatmentBenefits && filters.treatmentBenefits.length > 0) {
|
|
15699
|
-
const
|
|
15885
|
+
const benefitIdsToMatch = filters.treatmentBenefits;
|
|
15700
15886
|
filteredProcedures = filteredProcedures.filter((procedure) => {
|
|
15701
|
-
const
|
|
15702
|
-
return
|
|
15887
|
+
const procedureBenefitIds = procedure.treatmentBenefitIds || [];
|
|
15888
|
+
return benefitIdsToMatch.some(
|
|
15889
|
+
(benefitId) => procedureBenefitIds.includes(benefitId)
|
|
15890
|
+
);
|
|
15703
15891
|
});
|
|
15704
15892
|
console.log(
|
|
15705
15893
|
`[PROCEDURE_SERVICE] Applied benefits filter, results: ${filteredProcedures.length}`
|
|
@@ -15762,8 +15950,12 @@ var ProcedureService = class extends BaseService {
|
|
|
15762
15950
|
procedure.distance = distance;
|
|
15763
15951
|
return distance <= radiusInKm;
|
|
15764
15952
|
});
|
|
15765
|
-
console.log(
|
|
15766
|
-
|
|
15953
|
+
console.log(
|
|
15954
|
+
`[PROCEDURE_SERVICE] Applied geo filter, results: ${filteredProcedures.length}`
|
|
15955
|
+
);
|
|
15956
|
+
filteredProcedures.sort(
|
|
15957
|
+
(a, b) => (a.distance || 0) - (b.distance || 0)
|
|
15958
|
+
);
|
|
15767
15959
|
}
|
|
15768
15960
|
return filteredProcedures;
|
|
15769
15961
|
}
|
|
@@ -15775,19 +15967,30 @@ var ProcedureService = class extends BaseService {
|
|
|
15775
15967
|
if (!location || !radiusInKm) {
|
|
15776
15968
|
return Promise.resolve({ procedures: [], lastDoc: null });
|
|
15777
15969
|
}
|
|
15778
|
-
const bounds = geohashQueryBounds5(
|
|
15970
|
+
const bounds = geohashQueryBounds5(
|
|
15971
|
+
[location.latitude, location.longitude],
|
|
15972
|
+
radiusInKm * 1e3
|
|
15973
|
+
);
|
|
15779
15974
|
const fetches = bounds.map((b) => {
|
|
15780
15975
|
const constraints = [
|
|
15781
15976
|
where29("clinicInfo.location.geohash", ">=", b[0]),
|
|
15782
15977
|
where29("clinicInfo.location.geohash", "<=", b[1]),
|
|
15783
|
-
where29(
|
|
15978
|
+
where29(
|
|
15979
|
+
"isActive",
|
|
15980
|
+
"==",
|
|
15981
|
+
filters.isActive !== void 0 ? filters.isActive : true
|
|
15982
|
+
)
|
|
15784
15983
|
];
|
|
15785
|
-
return getDocs29(
|
|
15984
|
+
return getDocs29(
|
|
15985
|
+
query29(collection29(this.db, PROCEDURES_COLLECTION), ...constraints)
|
|
15986
|
+
);
|
|
15786
15987
|
});
|
|
15787
15988
|
return Promise.all(fetches).then((snaps) => {
|
|
15788
15989
|
const collected = [];
|
|
15789
15990
|
snaps.forEach((snap) => {
|
|
15790
|
-
snap.docs.forEach(
|
|
15991
|
+
snap.docs.forEach(
|
|
15992
|
+
(d) => collected.push({ ...d.data(), id: d.id })
|
|
15993
|
+
);
|
|
15791
15994
|
});
|
|
15792
15995
|
const uniqueMap = /* @__PURE__ */ new Map();
|
|
15793
15996
|
for (const p of collected) {
|
|
@@ -15798,7 +16001,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15798
16001
|
const pageSize = filters.pagination || 10;
|
|
15799
16002
|
let startIndex = 0;
|
|
15800
16003
|
if (filters.lastDoc && typeof filters.lastDoc === "object" && filters.lastDoc.id) {
|
|
15801
|
-
const idx = procedures.findIndex(
|
|
16004
|
+
const idx = procedures.findIndex(
|
|
16005
|
+
(p) => p.id === filters.lastDoc.id
|
|
16006
|
+
);
|
|
15802
16007
|
if (idx >= 0) startIndex = idx + 1;
|
|
15803
16008
|
}
|
|
15804
16009
|
const page = procedures.slice(startIndex, startIndex + pageSize);
|
|
@@ -15823,7 +16028,7 @@ var ProcedureService = class extends BaseService {
|
|
|
15823
16028
|
* @returns The created procedure
|
|
15824
16029
|
*/
|
|
15825
16030
|
async createConsultationProcedure(data) {
|
|
15826
|
-
var _a;
|
|
16031
|
+
var _a, _b, _c;
|
|
15827
16032
|
const procedureId = this.generateId();
|
|
15828
16033
|
const [category, subcategory, technology] = await Promise.all([
|
|
15829
16034
|
this.categoryService.getById(data.categoryId),
|
|
@@ -15839,7 +16044,11 @@ var ProcedureService = class extends BaseService {
|
|
|
15839
16044
|
throw new Error(`Clinic with ID ${data.clinicBranchId} not found`);
|
|
15840
16045
|
}
|
|
15841
16046
|
const clinic = clinicSnapshot.data();
|
|
15842
|
-
const practitionerRef = doc30(
|
|
16047
|
+
const practitionerRef = doc30(
|
|
16048
|
+
this.db,
|
|
16049
|
+
PRACTITIONERS_COLLECTION,
|
|
16050
|
+
data.practitionerId
|
|
16051
|
+
);
|
|
15843
16052
|
const practitionerSnapshot = await getDoc32(practitionerRef);
|
|
15844
16053
|
if (!practitionerSnapshot.exists()) {
|
|
15845
16054
|
throw new Error(`Practitioner with ID ${data.practitionerId} not found`);
|
|
@@ -15847,7 +16056,11 @@ var ProcedureService = class extends BaseService {
|
|
|
15847
16056
|
const practitioner = practitionerSnapshot.data();
|
|
15848
16057
|
let processedPhotos = [];
|
|
15849
16058
|
if (data.photos && data.photos.length > 0) {
|
|
15850
|
-
processedPhotos = await this.processMediaArray(
|
|
16059
|
+
processedPhotos = await this.processMediaArray(
|
|
16060
|
+
data.photos,
|
|
16061
|
+
procedureId,
|
|
16062
|
+
"procedure-photos"
|
|
16063
|
+
);
|
|
15851
16064
|
}
|
|
15852
16065
|
const clinicInfo = {
|
|
15853
16066
|
id: clinicSnapshot.id,
|
|
@@ -15889,7 +16102,9 @@ var ProcedureService = class extends BaseService {
|
|
|
15889
16102
|
// Use placeholder product
|
|
15890
16103
|
blockingConditions: technology.blockingConditions,
|
|
15891
16104
|
contraindications: technology.contraindications || [],
|
|
16105
|
+
contraindicationIds: ((_b = technology.contraindications) == null ? void 0 : _b.map((c) => c.id)) || [],
|
|
15892
16106
|
treatmentBenefits: technology.benefits,
|
|
16107
|
+
treatmentBenefitIds: ((_c = technology.benefits) == null ? void 0 : _c.map((b) => b.id)) || [],
|
|
15893
16108
|
preRequirements: technology.requirements.pre,
|
|
15894
16109
|
postRequirements: technology.requirements.post,
|
|
15895
16110
|
certificationRequirement: technology.certificationRequirement,
|
|
@@ -16161,7 +16376,7 @@ import { getAuth } from "firebase/auth";
|
|
|
16161
16376
|
import { getAnalytics } from "firebase/analytics";
|
|
16162
16377
|
import { Platform } from "react-native";
|
|
16163
16378
|
import { getStorage as getStorage3 } from "firebase/storage";
|
|
16164
|
-
import { getFunctions as
|
|
16379
|
+
import { getFunctions as getFunctions3 } from "firebase/functions";
|
|
16165
16380
|
var firebaseInstance = null;
|
|
16166
16381
|
var initializeFirebase = (config) => {
|
|
16167
16382
|
if (!firebaseInstance) {
|
|
@@ -16169,7 +16384,7 @@ var initializeFirebase = (config) => {
|
|
|
16169
16384
|
const db = getFirestore2(app);
|
|
16170
16385
|
const auth = getAuth(app);
|
|
16171
16386
|
const storage = getStorage3(app);
|
|
16172
|
-
const functions =
|
|
16387
|
+
const functions = getFunctions3(app);
|
|
16173
16388
|
let analytics = null;
|
|
16174
16389
|
if (typeof window !== "undefined" && Platform.OS === "web") {
|
|
16175
16390
|
analytics = getAnalytics(app);
|
|
@@ -16758,8 +16973,16 @@ var TechnologyService = class extends BaseService {
|
|
|
16758
16973
|
*/
|
|
16759
16974
|
async addContraindication(technologyId, contraindication) {
|
|
16760
16975
|
const docRef = doc35(this.getTechnologiesRef(), technologyId);
|
|
16976
|
+
const technology = await this.getById(technologyId);
|
|
16977
|
+
if (!technology) {
|
|
16978
|
+
throw new Error(`Technology with id ${technologyId} not found`);
|
|
16979
|
+
}
|
|
16980
|
+
const existingContraindications = technology.contraindications || [];
|
|
16981
|
+
if (existingContraindications.some((c) => c.id === contraindication.id)) {
|
|
16982
|
+
return technology;
|
|
16983
|
+
}
|
|
16761
16984
|
await updateDoc33(docRef, {
|
|
16762
|
-
contraindications:
|
|
16985
|
+
contraindications: [...existingContraindications, contraindication],
|
|
16763
16986
|
updatedAt: /* @__PURE__ */ new Date()
|
|
16764
16987
|
});
|
|
16765
16988
|
return this.getById(technologyId);
|
|
@@ -16772,8 +16995,44 @@ var TechnologyService = class extends BaseService {
|
|
|
16772
16995
|
*/
|
|
16773
16996
|
async removeContraindication(technologyId, contraindication) {
|
|
16774
16997
|
const docRef = doc35(this.getTechnologiesRef(), technologyId);
|
|
16998
|
+
const technology = await this.getById(technologyId);
|
|
16999
|
+
if (!technology) {
|
|
17000
|
+
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17001
|
+
}
|
|
17002
|
+
const updatedContraindications = (technology.contraindications || []).filter((c) => c.id !== contraindication.id);
|
|
16775
17003
|
await updateDoc33(docRef, {
|
|
16776
|
-
contraindications:
|
|
17004
|
+
contraindications: updatedContraindications,
|
|
17005
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
17006
|
+
});
|
|
17007
|
+
return this.getById(technologyId);
|
|
17008
|
+
}
|
|
17009
|
+
/**
|
|
17010
|
+
* Updates an existing contraindication in a technology's list.
|
|
17011
|
+
* If the contraindication does not exist, it will not be added.
|
|
17012
|
+
* @param technologyId - ID of the technology
|
|
17013
|
+
* @param contraindication - The updated contraindication object
|
|
17014
|
+
* @returns The updated technology
|
|
17015
|
+
*/
|
|
17016
|
+
async updateContraindication(technologyId, contraindication) {
|
|
17017
|
+
const docRef = doc35(this.getTechnologiesRef(), technologyId);
|
|
17018
|
+
const technology = await this.getById(technologyId);
|
|
17019
|
+
if (!technology) {
|
|
17020
|
+
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17021
|
+
}
|
|
17022
|
+
const contraindications = technology.contraindications || [];
|
|
17023
|
+
const index = contraindications.findIndex(
|
|
17024
|
+
(c) => c.id === contraindication.id
|
|
17025
|
+
);
|
|
17026
|
+
if (index === -1) {
|
|
17027
|
+
console.warn(
|
|
17028
|
+
`Contraindication with id ${contraindication.id} not found for technology ${technologyId}. No update performed.`
|
|
17029
|
+
);
|
|
17030
|
+
return technology;
|
|
17031
|
+
}
|
|
17032
|
+
const updatedContraindications = [...contraindications];
|
|
17033
|
+
updatedContraindications[index] = contraindication;
|
|
17034
|
+
await updateDoc33(docRef, {
|
|
17035
|
+
contraindications: updatedContraindications,
|
|
16777
17036
|
updatedAt: /* @__PURE__ */ new Date()
|
|
16778
17037
|
});
|
|
16779
17038
|
return this.getById(technologyId);
|
|
@@ -16786,8 +17045,16 @@ var TechnologyService = class extends BaseService {
|
|
|
16786
17045
|
*/
|
|
16787
17046
|
async addBenefit(technologyId, benefit) {
|
|
16788
17047
|
const docRef = doc35(this.getTechnologiesRef(), technologyId);
|
|
17048
|
+
const technology = await this.getById(technologyId);
|
|
17049
|
+
if (!technology) {
|
|
17050
|
+
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17051
|
+
}
|
|
17052
|
+
const existingBenefits = technology.benefits || [];
|
|
17053
|
+
if (existingBenefits.some((b) => b.id === benefit.id)) {
|
|
17054
|
+
return technology;
|
|
17055
|
+
}
|
|
16789
17056
|
await updateDoc33(docRef, {
|
|
16790
|
-
benefits:
|
|
17057
|
+
benefits: [...existingBenefits, benefit],
|
|
16791
17058
|
updatedAt: /* @__PURE__ */ new Date()
|
|
16792
17059
|
});
|
|
16793
17060
|
return this.getById(technologyId);
|
|
@@ -16800,8 +17067,44 @@ var TechnologyService = class extends BaseService {
|
|
|
16800
17067
|
*/
|
|
16801
17068
|
async removeBenefit(technologyId, benefit) {
|
|
16802
17069
|
const docRef = doc35(this.getTechnologiesRef(), technologyId);
|
|
17070
|
+
const technology = await this.getById(technologyId);
|
|
17071
|
+
if (!technology) {
|
|
17072
|
+
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17073
|
+
}
|
|
17074
|
+
const updatedBenefits = (technology.benefits || []).filter(
|
|
17075
|
+
(b) => b.id !== benefit.id
|
|
17076
|
+
);
|
|
17077
|
+
await updateDoc33(docRef, {
|
|
17078
|
+
benefits: updatedBenefits,
|
|
17079
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
17080
|
+
});
|
|
17081
|
+
return this.getById(technologyId);
|
|
17082
|
+
}
|
|
17083
|
+
/**
|
|
17084
|
+
* Updates an existing benefit in a technology's list.
|
|
17085
|
+
* If the benefit does not exist, it will not be added.
|
|
17086
|
+
* @param technologyId - ID of the technology
|
|
17087
|
+
* @param benefit - The updated benefit object
|
|
17088
|
+
* @returns The updated technology
|
|
17089
|
+
*/
|
|
17090
|
+
async updateBenefit(technologyId, benefit) {
|
|
17091
|
+
const docRef = doc35(this.getTechnologiesRef(), technologyId);
|
|
17092
|
+
const technology = await this.getById(technologyId);
|
|
17093
|
+
if (!technology) {
|
|
17094
|
+
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17095
|
+
}
|
|
17096
|
+
const benefits = technology.benefits || [];
|
|
17097
|
+
const index = benefits.findIndex((b) => b.id === benefit.id);
|
|
17098
|
+
if (index === -1) {
|
|
17099
|
+
console.warn(
|
|
17100
|
+
`Benefit with id ${benefit.id} not found for technology ${technologyId}. No update performed.`
|
|
17101
|
+
);
|
|
17102
|
+
return technology;
|
|
17103
|
+
}
|
|
17104
|
+
const updatedBenefits = [...benefits];
|
|
17105
|
+
updatedBenefits[index] = benefit;
|
|
16803
17106
|
await updateDoc33(docRef, {
|
|
16804
|
-
benefits:
|
|
17107
|
+
benefits: updatedBenefits,
|
|
16805
17108
|
updatedAt: /* @__PURE__ */ new Date()
|
|
16806
17109
|
});
|
|
16807
17110
|
return this.getById(technologyId);
|
|
@@ -17064,6 +17367,23 @@ var ProductService = class extends BaseService {
|
|
|
17064
17367
|
}
|
|
17065
17368
|
};
|
|
17066
17369
|
|
|
17370
|
+
// src/backoffice/types/static/contraindication.types.ts
|
|
17371
|
+
var Contraindication = /* @__PURE__ */ ((Contraindication2) => {
|
|
17372
|
+
Contraindication2["SENSITIVE_SKIN"] = "sensitive_skin";
|
|
17373
|
+
Contraindication2["RECENT_TANNING"] = "recent_tanning";
|
|
17374
|
+
Contraindication2["RECENT_BOTOX"] = "recent_botox";
|
|
17375
|
+
Contraindication2["RECENT_FILLERS"] = "recent_fillers";
|
|
17376
|
+
Contraindication2["SKIN_ALLERGIES"] = "skin_allergies";
|
|
17377
|
+
Contraindication2["MEDICATIONS"] = "medications";
|
|
17378
|
+
Contraindication2["RECENT_CHEMICAL_PEEL"] = "recent_chemical_peel";
|
|
17379
|
+
Contraindication2["RECENT_LASER"] = "recent_laser";
|
|
17380
|
+
Contraindication2["SKIN_INFLAMMATION"] = "skin_inflammation";
|
|
17381
|
+
Contraindication2["OPEN_WOUNDS"] = "open_wounds";
|
|
17382
|
+
Contraindication2["HERPES_SIMPLEX"] = "herpes_simplex";
|
|
17383
|
+
Contraindication2["COLD_SORES"] = "cold_sores";
|
|
17384
|
+
return Contraindication2;
|
|
17385
|
+
})(Contraindication || {});
|
|
17386
|
+
|
|
17067
17387
|
// src/backoffice/types/static/treatment-benefit.types.ts
|
|
17068
17388
|
var TreatmentBenefit = /* @__PURE__ */ ((TreatmentBenefit2) => {
|
|
17069
17389
|
TreatmentBenefit2["WRINKLE_REDUCTION"] = "wrinkle_reduction";
|