@blackcode_sa/metaestetics-api 1.6.0 → 1.6.2

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blackcode_sa/metaestetics-api",
3
3
  "private": false,
4
- "version": "1.6.0",
4
+ "version": "1.6.2",
5
5
  "description": "Firebase authentication service with anonymous upgrade support",
6
6
  "main": "./dist/index.js",
7
7
  "module": "./dist/index.mjs",
@@ -176,21 +176,28 @@ export class PractitionerService extends BaseService {
176
176
  throw new Error(`Clinic ${clinicId} not found`);
177
177
  }
178
178
 
179
- // Priprema podataka za kreiranje profila
180
- const clinics = data.clinics || [clinicId];
179
+ // Make sure the primary clinic (clinicId) is always included
180
+ // Merge the clinics array with the primary clinicId, avoiding duplicates
181
+ const clinicsToAdd = new Set<string>([clinicId]);
181
182
 
182
- // Provera da li sve dodatno navedene klinike postoje
183
- if (data.clinics) {
183
+ // Add additional clinics if provided
184
+ if (data.clinics && data.clinics.length > 0) {
184
185
  for (const cId of data.clinics) {
186
+ // Verify each additional clinic exists
185
187
  if (cId !== clinicId) {
188
+ // Skip checking the primary clinic again
186
189
  const otherClinic = await this.getClinicService().getClinic(cId);
187
190
  if (!otherClinic) {
188
191
  throw new Error(`Clinic ${cId} not found`);
189
192
  }
190
193
  }
194
+ clinicsToAdd.add(cId);
191
195
  }
192
196
  }
193
197
 
198
+ // Convert Set to Array
199
+ const clinics = Array.from(clinicsToAdd);
200
+
194
201
  // Initialize default review info for new practitioners
195
202
  const defaultReviewInfo: PractitionerReviewInfo = {
196
203
  totalReviews: 0,
@@ -206,7 +213,35 @@ export class PractitionerService extends BaseService {
206
213
  // Generate ID for the new practitioner
207
214
  const practitionerId = this.generateId();
208
215
 
209
- const clinicsInfo = validatedData.clinicsInfo || [];
216
+ // Create clinicsInfo from the merged clinics array
217
+ const clinicsInfo: ClinicInfo[] = [];
218
+
219
+ // Populate clinicsInfo for each clinic
220
+ for (const cId of clinics) {
221
+ const clinicData = await this.getClinicService().getClinic(cId);
222
+ if (clinicData) {
223
+ // Ensure we're creating a ClinicInfo object that matches the interface structure
224
+ clinicsInfo.push({
225
+ id: clinicData.id,
226
+ name: clinicData.name,
227
+ location: clinicData.location,
228
+ contactInfo: clinicData.contactInfo,
229
+ // Make sure we're using the right property for featuredPhoto
230
+ featuredPhoto:
231
+ clinicData.featuredPhotos && clinicData.featuredPhotos.length > 0
232
+ ? clinicData.featuredPhotos[0]
233
+ : clinicData.coverPhoto || "",
234
+ description: clinicData.description || null,
235
+ });
236
+ }
237
+ }
238
+
239
+ // Use provided clinicsInfo if available, otherwise use the ones we just created
240
+ const finalClinicsInfo =
241
+ validatedData.clinicsInfo && validatedData.clinicsInfo.length > 0
242
+ ? validatedData.clinicsInfo
243
+ : clinicsInfo;
244
+
210
245
  const proceduresInfo: ProcedureSummaryInfo[] = [];
211
246
 
212
247
  const practitionerData: Omit<Practitioner, "createdAt" | "updatedAt"> & {
@@ -219,7 +254,7 @@ export class PractitionerService extends BaseService {
219
254
  certification: validatedData.certification,
220
255
  clinics: clinics,
221
256
  clinicWorkingHours: validatedData.clinicWorkingHours || [],
222
- clinicsInfo: clinicsInfo,
257
+ clinicsInfo: finalClinicsInfo,
223
258
  procedures: [],
224
259
  proceduresInfo: proceduresInfo,
225
260
  reviewInfo: defaultReviewInfo,
@@ -13,8 +13,12 @@ import {
13
13
  Currency,
14
14
  PricingMeasure,
15
15
  } from "../backoffice/types/static/pricing.types";
16
- import { procedureSummaryInfoSchema } from "./practitioner.schema";
17
16
  import { clinicReviewInfoSchema } from "./reviews.schema";
17
+ import {
18
+ procedureSummaryInfoSchema,
19
+ clinicInfoSchema,
20
+ doctorInfoSchema,
21
+ } from "./shared.schema";
18
22
 
19
23
  /**
20
24
  * Validaciona šema za kontakt informacije
@@ -92,30 +96,6 @@ export const adminInfoSchema = z.object({
92
96
  email: z.string().email(),
93
97
  });
94
98
 
95
- /**
96
- * Validaciona šema za osnovne informacije o klinici (for aggregation)
97
- */
98
- export const clinicInfoSchema = z.object({
99
- id: z.string(),
100
- featuredPhoto: z.string(),
101
- name: z.string(),
102
- description: z.string().nullable().optional(),
103
- location: clinicLocationSchema,
104
- contactInfo: clinicContactInfoSchema,
105
- });
106
-
107
- /**
108
- * Validaciona šema za informacije o doktoru (for aggregation in Clinic)
109
- */
110
- export const doctorInfoSchema = z.object({
111
- id: z.string(),
112
- name: z.string(),
113
- description: z.string().nullable().optional(),
114
- photo: z.string(),
115
- rating: z.number().min(0).max(5),
116
- services: z.array(z.string()), // List of procedure IDs practitioner offers
117
- });
118
-
119
99
  /**
120
100
  * @deprecated Replaced by procedureSummaryInfoSchema.
121
101
  * Validaciona šema za informacije o usluzi (Old aggregation schema)
@@ -9,12 +9,12 @@ import {
9
9
  PractitionerTokenStatus,
10
10
  } from "../types/practitioner";
11
11
  import { practitionerReviewInfoSchema } from "./reviews.schema";
12
- import { clinicInfoSchema } from "./clinic.schema";
13
12
  import { ProcedureFamily } from "../backoffice/types/static/procedure-family.types";
14
13
  import {
15
14
  Currency,
16
15
  PricingMeasure,
17
16
  } from "../backoffice/types/static/pricing.types";
17
+ import { clinicInfoSchema, procedureSummaryInfoSchema } from "./shared.schema";
18
18
 
19
19
  /**
20
20
  * Šema za validaciju osnovnih informacija o zdravstvenom radniku
@@ -93,7 +93,7 @@ export const practitionerClinicWorkingHoursSchema = z.object({
93
93
  /**
94
94
  * Schema matching ProcedureSummaryInfo interface
95
95
  */
96
- export const procedureSummaryInfoSchema = z.object({
96
+ /* export const procedureSummaryInfoSchema = z.object({
97
97
  id: z.string().min(1),
98
98
  name: z.string().min(1),
99
99
  description: z.string().optional(),
@@ -110,7 +110,7 @@ export const procedureSummaryInfoSchema = z.object({
110
110
  clinicName: z.string().min(1),
111
111
  practitionerId: z.string().min(1),
112
112
  practitionerName: z.string().min(1),
113
- });
113
+ }); */
114
114
 
115
115
  /**
116
116
  * Šema za validaciju kompletnog profila zdravstvenog radnika
@@ -4,7 +4,7 @@ import {
4
4
  Currency,
5
5
  PricingMeasure,
6
6
  } from "../backoffice/types/static/pricing.types";
7
- import { clinicInfoSchema, doctorInfoSchema } from "./clinic.schema";
7
+ import { clinicInfoSchema, doctorInfoSchema } from "./shared.schema";
8
8
  import { procedureReviewInfoSchema } from "./reviews.schema";
9
9
 
10
10
  /**
@@ -0,0 +1,78 @@
1
+ import { z } from "zod";
2
+ import { Timestamp } from "firebase/firestore";
3
+ import { ProcedureFamily } from "../backoffice/types/static/procedure-family.types";
4
+ import {
5
+ Currency,
6
+ PricingMeasure,
7
+ } from "../backoffice/types/static/pricing.types";
8
+ // Remove import from clinic schema to avoid circular dependency
9
+ // import { clinicLocationSchema, clinicContactInfoSchema } from "./clinic.schema";
10
+
11
+ /**
12
+ * Validation schema for clinic contact information
13
+ */
14
+ export const sharedClinicContactInfoSchema = z.object({
15
+ email: z.string().email(),
16
+ phoneNumber: z.string(),
17
+ alternativePhoneNumber: z.string().nullable().optional(),
18
+ website: z.string().nullable().optional(),
19
+ });
20
+
21
+ /**
22
+ * Validation schema for clinic location
23
+ */
24
+ export const sharedClinicLocationSchema = z.object({
25
+ address: z.string(),
26
+ city: z.string(),
27
+ country: z.string(),
28
+ postalCode: z.string(),
29
+ latitude: z.number().min(-90).max(90),
30
+ longitude: z.number().min(-180).max(180),
31
+ geohash: z.string().nullable().optional(),
32
+ });
33
+
34
+ /**
35
+ * Schema for procedure summary info - shared between practitioner and clinic schemas
36
+ */
37
+ export const procedureSummaryInfoSchema = z.object({
38
+ id: z.string().min(1),
39
+ name: z.string().min(1),
40
+ description: z.string().optional(),
41
+ photo: z.string().optional(),
42
+ family: z.nativeEnum(ProcedureFamily),
43
+ categoryName: z.string(),
44
+ subcategoryName: z.string(),
45
+ technologyName: z.string(),
46
+ price: z.number().nonnegative(),
47
+ pricingMeasure: z.nativeEnum(PricingMeasure),
48
+ currency: z.nativeEnum(Currency),
49
+ duration: z.number().int().positive(),
50
+ clinicId: z.string().min(1),
51
+ clinicName: z.string().min(1),
52
+ practitionerId: z.string().min(1),
53
+ practitionerName: z.string().min(1),
54
+ });
55
+
56
+ /**
57
+ * Schema for clinic info - shared between practitioner and clinic schemas
58
+ */
59
+ export const clinicInfoSchema = z.object({
60
+ id: z.string(),
61
+ featuredPhoto: z.string(),
62
+ name: z.string(),
63
+ description: z.string().nullable().optional(),
64
+ location: sharedClinicLocationSchema,
65
+ contactInfo: sharedClinicContactInfoSchema,
66
+ });
67
+
68
+ /**
69
+ * Schema for doctor info - shared between procedure and clinic schemas
70
+ */
71
+ export const doctorInfoSchema = z.object({
72
+ id: z.string(),
73
+ name: z.string(),
74
+ description: z.string().nullable().optional(),
75
+ photo: z.string(),
76
+ rating: z.number().min(0).max(5),
77
+ services: z.array(z.string()), // List of procedure IDs practitioner offers
78
+ });