@blackcode_sa/metaestetics-api 1.5.29 → 1.5.31

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.
Files changed (30) hide show
  1. package/dist/admin/index.d.mts +126 -1
  2. package/dist/admin/index.d.ts +126 -1
  3. package/dist/admin/index.js +347 -10
  4. package/dist/admin/index.mjs +345 -10
  5. package/dist/index.d.mts +64 -71
  6. package/dist/index.d.ts +64 -71
  7. package/dist/index.js +327 -710
  8. package/dist/index.mjs +363 -750
  9. package/package.json +2 -1
  10. package/src/admin/aggregation/README.md +79 -0
  11. package/src/admin/aggregation/clinic/README.md +52 -0
  12. package/src/admin/aggregation/patient/README.md +27 -0
  13. package/src/admin/aggregation/practitioner/README.md +42 -0
  14. package/src/admin/aggregation/procedure/README.md +43 -0
  15. package/src/admin/index.ts +17 -2
  16. package/src/admin/mailing/README.md +95 -0
  17. package/src/admin/mailing/base.mailing.service.ts +131 -0
  18. package/src/admin/mailing/index.ts +2 -0
  19. package/src/admin/mailing/practitionerInvite/index.ts +1 -0
  20. package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +256 -0
  21. package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -0
  22. package/src/services/README.md +106 -0
  23. package/src/services/calendar/utils/appointment.utils.ts +42 -91
  24. package/src/services/clinic/README.md +87 -0
  25. package/src/services/clinic/clinic.service.ts +3 -126
  26. package/src/services/clinic/utils/clinic.utils.ts +2 -2
  27. package/src/services/practitioner/README.md +145 -0
  28. package/src/services/practitioner/practitioner.service.ts +119 -395
  29. package/src/services/procedure/README.md +88 -0
  30. package/src/services/procedure/procedure.service.ts +332 -369
@@ -66,120 +66,27 @@ export class PractitionerService extends BaseService {
66
66
 
67
67
  private getClinicService(): ClinicService {
68
68
  if (!this.clinicService) {
69
- throw new Error("ClinicService nije inicijalizovan");
69
+ throw new Error("Clinic service not initialized!");
70
70
  }
71
71
  return this.clinicService;
72
72
  }
73
73
 
74
- /**
75
- * Postavlja referencu na ClinicService nakon inicijalizacije
76
- */
77
74
  setClinicService(clinicService: ClinicService): void {
78
75
  this.clinicService = clinicService;
79
76
  }
80
77
 
81
78
  /**
82
- * Aggregates clinic information for a practitioner
83
- * @param clinicIds Array of clinic IDs the practitioner works at
84
- * @returns Array of ClinicInfo objects
85
- */
86
- private async aggregateClinicInfo(
87
- clinicIds: string[]
88
- ): Promise<ClinicInfo[]> {
89
- const clinicsInfo: ClinicInfo[] = [];
90
-
91
- for (const clinicId of clinicIds) {
92
- const clinic = await this.getClinicService().getClinic(clinicId);
93
- if (!clinic) continue;
94
-
95
- clinicsInfo.push({
96
- id: clinic.id,
97
- featuredPhoto:
98
- clinic.featuredPhotos && clinic.featuredPhotos.length > 0
99
- ? clinic.featuredPhotos[0]
100
- : clinic.coverPhoto || "",
101
- name: clinic.name,
102
- description: clinic.description || "",
103
- location: clinic.location,
104
- contactInfo: clinic.contactInfo,
105
- });
106
- }
107
-
108
- return clinicsInfo;
109
- }
110
-
111
- /**
112
- * @deprecated Aggregation of procedure info is now handled by ProcedureService.
113
- */
114
- private async aggregateProcedureInfo(
115
- clinicIds: string[],
116
- practitionerId: string
117
- ): Promise<ProcedureSummaryInfo[]> {
118
- console.warn("PractitionerService.aggregateProcedureInfo is deprecated.");
119
- return [];
120
- }
121
-
122
- /**
123
- * Updates aggregated data (clinics and procedures) for a practitioner
124
- * @param practitionerId ID of the practitioner to update
125
- * @returns Updated practitioner
126
- */
127
- async updateAggregatedData(
128
- practitionerId: string
129
- ): Promise<Practitioner | null> {
130
- const practitioner = await this.getPractitioner(practitionerId);
131
- if (!practitioner) {
132
- return null;
133
- }
134
-
135
- // Aggregate clinic info
136
- const clinicsInfo = await this.aggregateClinicInfo(practitioner.clinics);
137
-
138
- // Aggregate procedure info
139
- const proceduresInfo = await this.aggregateProcedureInfo(
140
- practitioner.clinics,
141
- practitionerId
142
- );
143
-
144
- // Update the practitioner with aggregated data
145
- const updatedPractitioner = await this.updatePractitioner(practitionerId, {
146
- clinicsInfo: clinicsInfo,
147
- proceduresInfo: proceduresInfo,
148
- });
149
-
150
- return updatedPractitioner;
151
- }
152
-
153
- /**
154
- * Kreira novog zdravstvenog radnika
79
+ * Creates a new practitioner
155
80
  */
156
81
  async createPractitioner(
157
82
  data: CreatePractitionerData
158
83
  ): Promise<Practitioner> {
159
84
  try {
160
- // Validacija ulaznih podataka
161
- const validatedData = createPractitionerSchema.parse(data);
162
-
163
- // Provera da li već postoji profil za ovog korisnika
164
- const existingPractitioner = await this.getPractitionerByUserRef(
165
- validatedData.userRef
166
- );
167
- if (existingPractitioner) {
168
- throw new Error("User already has a practitioner profile");
169
- }
170
-
171
- // Provera da li sve klinike postoje
172
- if (validatedData.clinics) {
173
- for (const clinicId of validatedData.clinics) {
174
- const clinic = await this.getClinicService().getClinic(clinicId);
175
- if (!clinic) {
176
- throw new Error(`Clinic ${clinicId} not found`);
177
- }
178
- }
179
- }
85
+ const validData = createPractitionerSchema.parse(data);
86
+ const practitionerId = this.generateId();
180
87
 
181
- // Initialize default review info for new practitioners
182
- const defaultReviewInfo: PractitionerReviewInfo = {
88
+ // Default review info
89
+ const reviewInfo: PractitionerReviewInfo = {
183
90
  totalReviews: 0,
184
91
  averageRating: 0,
185
92
  knowledgeAndExpertise: 0,
@@ -190,80 +97,58 @@ export class PractitionerService extends BaseService {
190
97
  recommendationPercentage: 0,
191
98
  };
192
99
 
193
- // Generate ID for the new practitioner
194
- const practitionerId = this.generateId();
195
-
196
- // Aggregate clinic info if not provided
197
- let clinicsInfo = validatedData.clinicsInfo || [];
198
- if (
199
- clinicsInfo.length === 0 &&
200
- validatedData.clinics &&
201
- validatedData.clinics.length > 0
202
- ) {
203
- clinicsInfo = await this.aggregateClinicInfo(validatedData.clinics);
204
- }
205
-
206
- // Can't aggregate procedures at creation time since the practitioner ID doesn't exist yet
207
- // We'll initialize with an empty array and update after creation if needed
208
- const proceduresInfo: ProcedureSummaryInfo[] = [];
209
-
210
- const practitionerData: Omit<Practitioner, "createdAt" | "updatedAt"> & {
211
- createdAt: ReturnType<typeof serverTimestamp>;
212
- updatedAt: ReturnType<typeof serverTimestamp>;
100
+ // Create practitioner object
101
+ const practitioner: Omit<Practitioner, "createdAt" | "updatedAt"> & {
102
+ createdAt: FieldValue;
103
+ updatedAt: FieldValue;
213
104
  } = {
214
105
  id: practitionerId,
215
- userRef: validatedData.userRef,
216
- basicInfo: validatedData.basicInfo,
217
- certification: validatedData.certification,
218
- clinics: validatedData.clinics || [],
219
- clinicWorkingHours: validatedData.clinicWorkingHours || [],
220
- clinicsInfo: clinicsInfo,
106
+ userRef: validData.userRef,
107
+ basicInfo: validData.basicInfo,
108
+ certification: validData.certification,
109
+ clinics: validData.clinics || [],
110
+ clinicWorkingHours: validData.clinicWorkingHours || [],
111
+ clinicsInfo: [],
221
112
  procedures: [],
222
- proceduresInfo: proceduresInfo,
223
- reviewInfo: defaultReviewInfo,
224
- isActive: validatedData.isActive,
225
- isVerified: validatedData.isVerified,
226
- status: validatedData.status || PractitionerStatus.ACTIVE,
113
+ proceduresInfo: [],
114
+ reviewInfo,
115
+ isActive: validData.isActive !== undefined ? validData.isActive : true,
116
+ isVerified:
117
+ validData.isVerified !== undefined ? validData.isVerified : false,
118
+ status: validData.status || PractitionerStatus.ACTIVE,
227
119
  createdAt: serverTimestamp(),
228
120
  updatedAt: serverTimestamp(),
229
121
  };
230
122
 
231
- // Validacija kompletnog objekta
123
+ // Validate the entire object
232
124
  practitionerSchema.parse({
233
- ...practitionerData,
125
+ ...practitioner,
234
126
  createdAt: Timestamp.now(),
235
127
  updatedAt: Timestamp.now(),
236
128
  });
237
129
 
238
- // Čuvamo u Firestore
239
- await setDoc(
240
- doc(this.db, PRACTITIONERS_COLLECTION, practitionerData.id),
241
- practitionerData
130
+ // Create practitioner document
131
+ const practitionerRef = doc(
132
+ this.db,
133
+ PRACTITIONERS_COLLECTION,
134
+ practitionerId
242
135
  );
243
136
 
244
- // Get the saved practitioner
245
- let savedPractitioner = await this.getPractitioner(practitionerData.id);
246
- if (!savedPractitioner) {
247
- throw new Error("Failed to create practitioner profile");
248
- }
137
+ await setDoc(practitionerRef, practitioner);
249
138
 
250
- // If procedures weren't provided and the practitioner is associated with clinics,
251
- // update the aggregated procedure info
252
- if (
253
- proceduresInfo.length === 0 &&
254
- validatedData.clinics &&
255
- validatedData.clinics.length > 0
256
- ) {
257
- savedPractitioner =
258
- (await this.updateAggregatedData(savedPractitioner.id)) ||
259
- savedPractitioner;
139
+ // Return the created practitioner
140
+ const createdPractitioner = await this.getPractitioner(practitionerId);
141
+ if (!createdPractitioner) {
142
+ throw new Error(
143
+ `Failed to retrieve created practitioner ${practitionerId}`
144
+ );
260
145
  }
261
-
262
- return savedPractitioner;
146
+ return createdPractitioner;
263
147
  } catch (error) {
264
148
  if (error instanceof z.ZodError) {
265
- throw new Error("Invalid practitioner data: " + error.message);
149
+ throw new Error(`Invalid practitioner data: ${error.message}`);
266
150
  }
151
+ console.error("Error creating practitioner:", error);
267
152
  throw error;
268
153
  }
269
154
  }
@@ -321,13 +206,7 @@ export class PractitionerService extends BaseService {
321
206
  // Generate ID for the new practitioner
322
207
  const practitionerId = this.generateId();
323
208
 
324
- // Aggregate clinic info if not provided
325
- let clinicsInfo = validatedData.clinicsInfo || [];
326
- if (clinicsInfo.length === 0 && clinics.length > 0) {
327
- clinicsInfo = await this.aggregateClinicInfo(clinics);
328
- }
329
-
330
- // Can't aggregate procedures for draft practitioners yet
209
+ const clinicsInfo = validatedData.clinicsInfo || [];
331
210
  const proceduresInfo: ProcedureSummaryInfo[] = [];
332
211
 
333
212
  const practitionerData: Omit<Practitioner, "createdAt" | "updatedAt"> & {
@@ -647,156 +526,126 @@ export class PractitionerService extends BaseService {
647
526
  }
648
527
 
649
528
  /**
650
- * Ažurira profil zdravstvenog radnika
529
+ * Updates a practitioner
651
530
  */
652
531
  async updatePractitioner(
653
532
  practitionerId: string,
654
533
  data: UpdatePractitionerData
655
534
  ): Promise<Practitioner> {
656
- const practitionerRef = doc(
657
- this.db,
658
- PRACTITIONERS_COLLECTION,
659
- practitionerId
660
- );
661
- const practitionerDoc = await getDoc(practitionerRef);
662
-
663
- if (!practitionerDoc.exists()) {
664
- throw new Error("Practitioner not found");
665
- }
666
-
667
535
  try {
668
- const currentPractitioner = practitionerDoc.data() as Practitioner;
536
+ // Validate update data
537
+ const validData = data; // Using the passed data directly as it's already validated by the schema type
669
538
 
670
- // Ako se ažurira lista klinika, proveravamo da li sve postoje
671
- // i agregiramo informacije o klinikama
672
- if (data.clinics) {
673
- for (const clinicId of data.clinics) {
674
- const clinic = await this.getClinicService().getClinic(clinicId);
675
- if (!clinic) {
676
- throw new Error(`Clinic ${clinicId} not found`);
677
- }
678
- }
679
-
680
- // If clinics changed and clinicsInfo wasn't explicitly provided, update clinicsInfo
681
- if (!data.clinicsInfo) {
682
- data.clinicsInfo = await this.aggregateClinicInfo(data.clinics);
683
- }
539
+ // Get current practitioner data
540
+ const practitionerRef = doc(
541
+ this.db,
542
+ PRACTITIONERS_COLLECTION,
543
+ practitionerId
544
+ );
545
+ const practitionerDoc = await getDoc(practitionerRef);
684
546
 
685
- // If clinics changed, update procedures info
686
- if (!data.proceduresInfo) {
687
- data.proceduresInfo = await this.aggregateProcedureInfo(
688
- data.clinics,
689
- practitionerId
690
- );
691
- }
547
+ if (!practitionerDoc.exists()) {
548
+ throw new Error(`Practitioner ${practitionerId} not found`);
692
549
  }
693
550
 
551
+ const currentPractitioner = practitionerDoc.data() as Practitioner;
552
+
553
+ // Prepare update data
694
554
  const updateData = {
695
- ...data,
555
+ ...validData,
696
556
  updatedAt: serverTimestamp(),
697
557
  };
698
558
 
699
- // Validiramo kompletan objekat
700
- practitionerSchema.parse({
701
- ...currentPractitioner,
702
- ...data,
703
- updatedAt: Timestamp.now(),
704
- });
705
-
559
+ // Update practitioner
706
560
  await updateDoc(practitionerRef, updateData);
707
561
 
562
+ // Return updated practitioner
708
563
  const updatedPractitioner = await this.getPractitioner(practitionerId);
709
564
  if (!updatedPractitioner) {
710
- throw new Error("Failed to retrieve updated practitioner profile");
565
+ throw new Error(
566
+ `Failed to retrieve updated practitioner ${practitionerId}`
567
+ );
711
568
  }
712
-
713
569
  return updatedPractitioner;
714
570
  } catch (error) {
715
571
  if (error instanceof z.ZodError) {
716
- throw new Error("Invalid practitioner data: " + error.message);
572
+ throw new Error(`Invalid practitioner update data: ${error.message}`);
717
573
  }
574
+ console.error(`Error updating practitioner ${practitionerId}:`, error);
718
575
  throw error;
719
576
  }
720
577
  }
721
578
 
722
579
  /**
723
- * Dodaje kliniku zdravstvenom radniku
580
+ * Adds a clinic to a practitioner
724
581
  */
725
582
  async addClinic(practitionerId: string, clinicId: string): Promise<void> {
726
- const practitioner = await this.getPractitioner(practitionerId);
727
- if (!practitioner) {
728
- throw new Error("Practitioner not found");
729
- }
583
+ try {
584
+ // Get practitioner
585
+ const practitionerRef = doc(
586
+ this.db,
587
+ PRACTITIONERS_COLLECTION,
588
+ practitionerId
589
+ );
590
+ const practitionerDoc = await getDoc(practitionerRef);
730
591
 
731
- const clinic = await this.getClinicService().getClinic(clinicId);
732
- if (!clinic) {
733
- throw new Error("Clinic not found");
734
- }
592
+ if (!practitionerDoc.exists()) {
593
+ throw new Error(`Practitioner ${practitionerId} not found`);
594
+ }
735
595
 
736
- if (practitioner.clinics.includes(clinicId)) {
737
- throw new Error("Practitioner is already associated with this clinic");
738
- }
596
+ const practitioner = practitionerDoc.data() as Practitioner;
739
597
 
740
- // Add clinic to the list
741
- const updatedClinics = [...practitioner.clinics, clinicId];
742
-
743
- // Update clinicsInfo array
744
- const clinicInfo: ClinicInfo = {
745
- id: clinic.id,
746
- name: clinic.name,
747
- description: clinic.description || "",
748
- featuredPhoto:
749
- clinic.featuredPhotos && clinic.featuredPhotos.length > 0
750
- ? clinic.featuredPhotos[0]
751
- : clinic.coverPhoto || "",
752
- location: clinic.location,
753
- contactInfo: clinic.contactInfo,
754
- };
755
-
756
- const updatedClinicsInfo = [...practitioner.clinicsInfo, clinicInfo];
757
-
758
- // Update practitioner with new clinic information
759
- await this.updatePractitioner(practitionerId, {
760
- clinics: updatedClinics,
761
- clinicsInfo: updatedClinicsInfo,
762
- });
598
+ // Check if clinic already added
599
+ if (practitioner.clinics?.includes(clinicId)) {
600
+ console.log(
601
+ `Clinic ${clinicId} already added to practitioner ${practitionerId}`
602
+ );
603
+ return;
604
+ }
763
605
 
764
- // After adding clinic, update aggregated procedure info
765
- await this.updateAggregatedData(practitionerId);
606
+ // Add clinic to clinics array
607
+ await updateDoc(practitionerRef, {
608
+ clinics: arrayUnion(clinicId),
609
+ updatedAt: serverTimestamp(),
610
+ });
611
+ } catch (error) {
612
+ console.error(
613
+ `Error adding clinic ${clinicId} to practitioner ${practitionerId}:`,
614
+ error
615
+ );
616
+ throw error;
617
+ }
766
618
  }
767
619
 
768
620
  /**
769
- * Uklanja kliniku iz liste klinika zdravstvenog radnika
621
+ * Removes a clinic from a practitioner
770
622
  */
771
623
  async removeClinic(practitionerId: string, clinicId: string): Promise<void> {
772
- const practitioner = await this.getPractitioner(practitionerId);
773
- if (!practitioner) {
774
- throw new Error("Practitioner not found");
775
- }
776
-
777
- if (!practitioner.clinics.includes(clinicId)) {
778
- throw new Error("Practitioner is not associated with this clinic");
779
- }
780
-
781
- // Remove clinic from the list
782
- const updatedClinics = practitioner.clinics.filter((id) => id !== clinicId);
783
-
784
- // Update clinicsInfo array
785
- const updatedClinicsInfo = practitioner.clinicsInfo.filter(
786
- (clinic) => clinic.id !== clinicId
787
- );
624
+ try {
625
+ // Get practitioner
626
+ const practitionerRef = doc(
627
+ this.db,
628
+ PRACTITIONERS_COLLECTION,
629
+ practitionerId
630
+ );
631
+ const practitionerDoc = await getDoc(practitionerRef);
788
632
 
789
- // Update proceduresInfo array - remove procedures from this clinic
790
- const updatedProceduresInfo = practitioner.proceduresInfo.filter(
791
- (procedure) => procedure.clinicId !== clinicId
792
- );
633
+ if (!practitionerDoc.exists()) {
634
+ throw new Error(`Practitioner ${practitionerId} not found`);
635
+ }
793
636
 
794
- // Update practitioner with updated information
795
- await this.updatePractitioner(practitionerId, {
796
- clinics: updatedClinics,
797
- clinicsInfo: updatedClinicsInfo,
798
- proceduresInfo: updatedProceduresInfo,
799
- });
637
+ // Remove clinic from clinics array
638
+ await updateDoc(practitionerRef, {
639
+ clinics: arrayRemove(clinicId),
640
+ updatedAt: serverTimestamp(),
641
+ });
642
+ } catch (error) {
643
+ console.error(
644
+ `Error removing clinic ${clinicId} from practitioner ${practitionerId}:`,
645
+ error
646
+ );
647
+ throw error;
648
+ }
800
649
  }
801
650
 
802
651
  /**
@@ -1147,129 +996,4 @@ export class PractitionerService extends BaseService {
1147
996
  throw error;
1148
997
  }
1149
998
  }
1150
-
1151
- // --- Helper Functions ---
1152
-
1153
- /**
1154
- * Aggregates essential clinic information for embedding in Practitioner.
1155
- * @param clinicIds Array of clinic IDs the practitioner works at
1156
- * @returns Array of ClinicInfo objects
1157
- */
1158
- private async _aggregateClinicInfoForPractitioner(
1159
- clinicIds: string[]
1160
- ): Promise<ClinicInfo[]> {
1161
- const clinicsInfo: ClinicInfo[] = [];
1162
- const clinicService = this.getClinicService(); // Get service instance
1163
-
1164
- for (const clinicId of clinicIds) {
1165
- try {
1166
- const clinic = await clinicService.getClinic(clinicId);
1167
- if (!clinic) {
1168
- console.warn(
1169
- `Clinic ${clinicId} not found during practitioner aggregation.`
1170
- );
1171
- continue;
1172
- }
1173
-
1174
- clinicsInfo.push({
1175
- id: clinic.id,
1176
- featuredPhoto:
1177
- clinic.featuredPhotos && clinic.featuredPhotos.length > 0
1178
- ? clinic.featuredPhotos[0]
1179
- : clinic.coverPhoto || "",
1180
- name: clinic.name,
1181
- description: clinic.description || "",
1182
- location: clinic.location,
1183
- contactInfo: clinic.contactInfo,
1184
- });
1185
- } catch (error) {
1186
- console.error(
1187
- `Error fetching clinic ${clinicId} for practitioner aggregation:`,
1188
- error
1189
- );
1190
- }
1191
- }
1192
- return clinicsInfo;
1193
- }
1194
-
1195
- /**
1196
- * Creates an aggregated DoctorInfo object from Practitioner data.
1197
- * @param practitioner The practitioner object
1198
- * @returns DoctorInfo object
1199
- */
1200
- private _createDoctorInfoForClinic(practitioner: Practitioner): DoctorInfo {
1201
- return {
1202
- id: practitioner.id,
1203
- name: `${practitioner.basicInfo.firstName} ${practitioner.basicInfo.lastName}`,
1204
- description: practitioner.basicInfo.bio || "",
1205
- photo: practitioner.basicInfo.profileImageUrl || "",
1206
- rating: practitioner.reviewInfo?.averageRating || 0,
1207
- services: practitioner.procedures || [], // List of procedure IDs
1208
- };
1209
- }
1210
-
1211
- /**
1212
- * Updates the DoctorInfo within the doctorsInfo array for multiple clinics.
1213
- * @param clinicIds IDs of clinics to update
1214
- * @param doctorInfo The updated DoctorInfo object
1215
- */
1216
- private async _updateDoctorInfoInClinics(
1217
- clinicIds: string[],
1218
- doctorInfo: DoctorInfo
1219
- ): Promise<void> {
1220
- const batch = writeBatch(this.db);
1221
- const practitionerId = doctorInfo.id;
1222
-
1223
- for (const clinicId of clinicIds) {
1224
- const clinicRef = doc(this.db, CLINICS_COLLECTION, clinicId);
1225
- // First, remove the old doctor info based on ID
1226
- batch.update(clinicRef, {
1227
- doctorsInfo: arrayRemove(...[{ id: practitionerId }]),
1228
- updatedAt: serverTimestamp(),
1229
- });
1230
- // Then, add the updated doctor info
1231
- batch.update(clinicRef, {
1232
- doctorsInfo: arrayUnion(doctorInfo),
1233
- updatedAt: serverTimestamp(),
1234
- });
1235
- }
1236
- try {
1237
- await batch.commit();
1238
- } catch (error) {
1239
- console.error(
1240
- `Error updating doctor info in clinics for practitioner ${practitionerId}:`,
1241
- error
1242
- );
1243
- // Decide on error handling: throw, retry, log?
1244
- }
1245
- }
1246
-
1247
- /**
1248
- * Removes DoctorInfo from the doctorsInfo array for multiple clinics.
1249
- * @param clinicIds IDs of clinics to update
1250
- * @param practitionerId ID of the practitioner whose info should be removed
1251
- */
1252
- private async _removeDoctorInfoFromClinics(
1253
- clinicIds: string[],
1254
- practitionerId: string
1255
- ): Promise<void> {
1256
- const batch = writeBatch(this.db);
1257
-
1258
- for (const clinicId of clinicIds) {
1259
- const clinicRef = doc(this.db, CLINICS_COLLECTION, clinicId);
1260
- batch.update(clinicRef, {
1261
- doctors: arrayRemove(practitionerId), // Also remove from simple ID list
1262
- doctorsInfo: arrayRemove(...[{ id: practitionerId }]), // Remove by ID matcher
1263
- updatedAt: serverTimestamp(),
1264
- });
1265
- }
1266
- try {
1267
- await batch.commit();
1268
- } catch (error) {
1269
- console.error(
1270
- `Error removing doctor info from clinics for practitioner ${practitionerId}:`,
1271
- error
1272
- );
1273
- }
1274
- }
1275
999
  }