@blackcode_sa/metaestetics-api 1.12.33 → 1.12.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1741 -1578
- package/dist/index.mjs +1509 -1346
- package/package.json +1 -1
- package/src/services/appointment/utils/extended-procedure.utils.ts +53 -0
- package/src/services/appointment/utils/form-initialization.utils.ts +225 -0
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
} from '../../../types/appointment';
|
|
8
8
|
import { getAppointmentOrThrow, initializeMetadata } from './zone-management.utils';
|
|
9
9
|
import { PROCEDURES_COLLECTION } from '../../../types/procedure';
|
|
10
|
+
import { initializeFormsForExtendedProcedure, removeFormsForExtendedProcedure } from './form-initialization.utils';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Aggregates products from a procedure into appointmentProducts
|
|
@@ -134,6 +135,16 @@ export async function addExtendedProcedureUtil(
|
|
|
134
135
|
// Create extended procedure info
|
|
135
136
|
const extendedProcedureInfo = await createExtendedProcedureInfo(db, procedureId);
|
|
136
137
|
|
|
138
|
+
// Get procedure data for forms and products
|
|
139
|
+
const procedureRef = doc(db, PROCEDURES_COLLECTION, procedureId);
|
|
140
|
+
const procedureSnap = await getDoc(procedureRef);
|
|
141
|
+
|
|
142
|
+
if (!procedureSnap.exists()) {
|
|
143
|
+
throw new Error(`Procedure with ID ${procedureId} not found`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const procedureData = procedureSnap.data();
|
|
147
|
+
|
|
137
148
|
// Aggregate products
|
|
138
149
|
const updatedProducts = await aggregateProductsFromProcedure(
|
|
139
150
|
db,
|
|
@@ -141,6 +152,28 @@ export async function addExtendedProcedureUtil(
|
|
|
141
152
|
metadata.appointmentProducts || []
|
|
142
153
|
);
|
|
143
154
|
|
|
155
|
+
// Initialize forms for extended procedure
|
|
156
|
+
let updatedLinkedFormIds = appointment.linkedFormIds || [];
|
|
157
|
+
let updatedLinkedForms = appointment.linkedForms || [];
|
|
158
|
+
let updatedPendingUserFormsIds = appointment.pendingUserFormsIds || [];
|
|
159
|
+
|
|
160
|
+
if (procedureData.documentationTemplates && procedureData.documentationTemplates.length > 0) {
|
|
161
|
+
const formInitResult = await initializeFormsForExtendedProcedure(
|
|
162
|
+
db,
|
|
163
|
+
appointmentId,
|
|
164
|
+
procedureId,
|
|
165
|
+
procedureData.documentationTemplates,
|
|
166
|
+
appointment.patientId,
|
|
167
|
+
appointment.practitionerId,
|
|
168
|
+
appointment.clinicBranchId
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
// Merge form IDs and info
|
|
172
|
+
updatedLinkedFormIds = [...updatedLinkedFormIds, ...formInitResult.allLinkedFormIds];
|
|
173
|
+
updatedLinkedForms = [...updatedLinkedForms, ...formInitResult.initializedFormsInfo];
|
|
174
|
+
updatedPendingUserFormsIds = [...updatedPendingUserFormsIds, ...formInitResult.pendingUserFormsIds];
|
|
175
|
+
}
|
|
176
|
+
|
|
144
177
|
// Add extended procedure
|
|
145
178
|
const extendedProcedures = [...(metadata.extendedProcedures || []), extendedProcedureInfo];
|
|
146
179
|
|
|
@@ -149,6 +182,9 @@ export async function addExtendedProcedureUtil(
|
|
|
149
182
|
await updateDoc(appointmentRef, {
|
|
150
183
|
'metadata.extendedProcedures': extendedProcedures,
|
|
151
184
|
'metadata.appointmentProducts': updatedProducts,
|
|
185
|
+
linkedFormIds: updatedLinkedFormIds,
|
|
186
|
+
linkedForms: updatedLinkedForms,
|
|
187
|
+
pendingUserFormsIds: updatedPendingUserFormsIds,
|
|
152
188
|
updatedAt: serverTimestamp(),
|
|
153
189
|
});
|
|
154
190
|
|
|
@@ -191,11 +227,28 @@ export async function removeExtendedProcedureUtil(
|
|
|
191
227
|
p => p.procedureId !== procedureId
|
|
192
228
|
);
|
|
193
229
|
|
|
230
|
+
// Remove forms associated with this procedure
|
|
231
|
+
const removedFormIds = await removeFormsForExtendedProcedure(db, appointmentId, procedureId);
|
|
232
|
+
|
|
233
|
+
// Update appointment form arrays
|
|
234
|
+
const updatedLinkedFormIds = (appointment.linkedFormIds || []).filter(
|
|
235
|
+
formId => !removedFormIds.includes(formId)
|
|
236
|
+
);
|
|
237
|
+
const updatedLinkedForms = (appointment.linkedForms || []).filter(
|
|
238
|
+
form => !removedFormIds.includes(form.formId)
|
|
239
|
+
);
|
|
240
|
+
const updatedPendingUserFormsIds = (appointment.pendingUserFormsIds || []).filter(
|
|
241
|
+
formId => !removedFormIds.includes(formId)
|
|
242
|
+
);
|
|
243
|
+
|
|
194
244
|
// Update appointment
|
|
195
245
|
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
196
246
|
await updateDoc(appointmentRef, {
|
|
197
247
|
'metadata.extendedProcedures': metadata.extendedProcedures,
|
|
198
248
|
'metadata.appointmentProducts': updatedProducts,
|
|
249
|
+
linkedFormIds: updatedLinkedFormIds,
|
|
250
|
+
linkedForms: updatedLinkedForms,
|
|
251
|
+
pendingUserFormsIds: updatedPendingUserFormsIds,
|
|
199
252
|
updatedAt: serverTimestamp(),
|
|
200
253
|
});
|
|
201
254
|
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { Firestore, collection, doc, addDoc, deleteDoc, getDocs, query, where, serverTimestamp, getDoc } from 'firebase/firestore';
|
|
2
|
+
import {
|
|
3
|
+
DocumentTemplate,
|
|
4
|
+
FilledDocumentStatus,
|
|
5
|
+
DOCTOR_FORMS_SUBCOLLECTION,
|
|
6
|
+
DOCUMENTATION_TEMPLATES_COLLECTION,
|
|
7
|
+
} from '../../../types/documentation-templates';
|
|
8
|
+
import {
|
|
9
|
+
APPOINTMENTS_COLLECTION,
|
|
10
|
+
LinkedFormInfo,
|
|
11
|
+
} from '../../../types/appointment';
|
|
12
|
+
import { TechnologyDocumentationTemplate } from '../../../backoffice/types/technology.types';
|
|
13
|
+
|
|
14
|
+
export interface InitializeExtendedProcedureFormsResult {
|
|
15
|
+
initializedFormsInfo: LinkedFormInfo[];
|
|
16
|
+
pendingUserFormsIds: string[];
|
|
17
|
+
allLinkedFormIds: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Initializes forms for an extended procedure using client-side Firestore
|
|
22
|
+
* Similar to DocumentManagerAdminService but for client-side usage
|
|
23
|
+
* @param db Firestore instance
|
|
24
|
+
* @param appointmentId Appointment ID
|
|
25
|
+
* @param procedureId Procedure ID for forms
|
|
26
|
+
* @param technologyTemplates Technology documentation templates
|
|
27
|
+
* @param patientId Patient ID
|
|
28
|
+
* @param practitionerId Practitioner ID
|
|
29
|
+
* @param clinicId Clinic ID
|
|
30
|
+
* @returns Form initialization result
|
|
31
|
+
*/
|
|
32
|
+
export async function initializeFormsForExtendedProcedure(
|
|
33
|
+
db: Firestore,
|
|
34
|
+
appointmentId: string,
|
|
35
|
+
procedureId: string,
|
|
36
|
+
technologyTemplates: TechnologyDocumentationTemplate[],
|
|
37
|
+
patientId: string,
|
|
38
|
+
practitionerId: string,
|
|
39
|
+
clinicId: string
|
|
40
|
+
): Promise<InitializeExtendedProcedureFormsResult> {
|
|
41
|
+
const initializedFormsInfo: LinkedFormInfo[] = [];
|
|
42
|
+
const pendingUserFormsIds: string[] = [];
|
|
43
|
+
const allLinkedFormIds: string[] = [];
|
|
44
|
+
|
|
45
|
+
if (!technologyTemplates || technologyTemplates.length === 0) {
|
|
46
|
+
console.log(
|
|
47
|
+
`[FormInit] No document templates to initialize for extended procedure ${procedureId} in appointment ${appointmentId}.`
|
|
48
|
+
);
|
|
49
|
+
return {
|
|
50
|
+
initializedFormsInfo,
|
|
51
|
+
pendingUserFormsIds,
|
|
52
|
+
allLinkedFormIds,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Fetch all template documents
|
|
57
|
+
const templateIds = technologyTemplates.map((t) => t.templateId);
|
|
58
|
+
|
|
59
|
+
// Note: Client-side Firestore doesn't support 'in' queries with more than 10 items
|
|
60
|
+
// We'll fetch templates one by one for now (can be optimized later)
|
|
61
|
+
const templatesMap = new Map<string, DocumentTemplate>();
|
|
62
|
+
|
|
63
|
+
for (const templateId of templateIds) {
|
|
64
|
+
try {
|
|
65
|
+
const templateDoc = doc(db, DOCUMENTATION_TEMPLATES_COLLECTION, templateId);
|
|
66
|
+
const templateSnap = await getDoc(templateDoc);
|
|
67
|
+
|
|
68
|
+
if (templateSnap.exists()) {
|
|
69
|
+
templatesMap.set(templateId, templateSnap.data() as DocumentTemplate);
|
|
70
|
+
} else {
|
|
71
|
+
console.warn(
|
|
72
|
+
`[FormInit] Template ${templateId} not found in Firestore.`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error(`[FormInit] Error fetching template ${templateId}:`, error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Initialize forms for each template (only doctor forms for extended procedures)
|
|
81
|
+
for (const templateRef of technologyTemplates) {
|
|
82
|
+
const template = templatesMap.get(templateRef.templateId);
|
|
83
|
+
if (!template) {
|
|
84
|
+
console.warn(
|
|
85
|
+
`[FormInit] Template ${templateRef.templateId} not found in Firestore.`
|
|
86
|
+
);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Skip user forms - only create doctor forms for extended procedures
|
|
91
|
+
if (templateRef.isUserForm) {
|
|
92
|
+
console.log(
|
|
93
|
+
`[FormInit] Skipping user form ${templateRef.templateId} for extended procedure ${procedureId}.`
|
|
94
|
+
);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const isRequired = templateRef.isRequired;
|
|
99
|
+
const formSubcollectionPath = DOCTOR_FORMS_SUBCOLLECTION;
|
|
100
|
+
|
|
101
|
+
// Create form document in subcollection
|
|
102
|
+
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
103
|
+
const formsCollectionRef = collection(appointmentRef, formSubcollectionPath);
|
|
104
|
+
|
|
105
|
+
const filledDocumentData = {
|
|
106
|
+
templateId: templateRef.templateId,
|
|
107
|
+
templateVersion: template.version,
|
|
108
|
+
isUserForm: false, // Always false for extended procedures
|
|
109
|
+
isRequired: isRequired,
|
|
110
|
+
appointmentId: appointmentId,
|
|
111
|
+
procedureId: procedureId,
|
|
112
|
+
patientId: patientId,
|
|
113
|
+
practitionerId: practitionerId,
|
|
114
|
+
clinicId: clinicId,
|
|
115
|
+
createdAt: serverTimestamp(),
|
|
116
|
+
updatedAt: serverTimestamp(),
|
|
117
|
+
values: {},
|
|
118
|
+
status: FilledDocumentStatus.PENDING,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
try {
|
|
122
|
+
const docRef = await addDoc(formsCollectionRef, filledDocumentData);
|
|
123
|
+
const filledDocumentId = docRef.id;
|
|
124
|
+
|
|
125
|
+
// No user forms for extended procedures, so no pending user forms
|
|
126
|
+
|
|
127
|
+
allLinkedFormIds.push(filledDocumentId);
|
|
128
|
+
|
|
129
|
+
const linkedForm: LinkedFormInfo = {
|
|
130
|
+
formId: filledDocumentId,
|
|
131
|
+
templateId: template.id,
|
|
132
|
+
templateVersion: template.version,
|
|
133
|
+
title: template.title,
|
|
134
|
+
isUserForm: false, // Always false for extended procedures
|
|
135
|
+
isRequired: isRequired,
|
|
136
|
+
sortingOrder: templateRef.sortingOrder,
|
|
137
|
+
status: FilledDocumentStatus.PENDING,
|
|
138
|
+
path: docRef.path,
|
|
139
|
+
};
|
|
140
|
+
initializedFormsInfo.push(linkedForm);
|
|
141
|
+
|
|
142
|
+
console.log(
|
|
143
|
+
`[FormInit] Created FilledDocument ${filledDocumentId} (template: ${template.id}) for extended procedure ${procedureId} in appointment ${appointmentId}.`
|
|
144
|
+
);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(
|
|
147
|
+
`[FormInit] Error creating form for template ${templateRef.templateId}:`,
|
|
148
|
+
error
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return { initializedFormsInfo, pendingUserFormsIds, allLinkedFormIds };
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Removes all forms associated with a specific procedure from an appointment
|
|
158
|
+
* @param db Firestore instance
|
|
159
|
+
* @param appointmentId Appointment ID
|
|
160
|
+
* @param procedureId Procedure ID to remove forms for
|
|
161
|
+
* @returns Array of removed form IDs
|
|
162
|
+
*/
|
|
163
|
+
export async function removeFormsForExtendedProcedure(
|
|
164
|
+
db: Firestore,
|
|
165
|
+
appointmentId: string,
|
|
166
|
+
procedureId: string
|
|
167
|
+
): Promise<string[]> {
|
|
168
|
+
const removedFormIds: string[] = [];
|
|
169
|
+
|
|
170
|
+
// Only remove from doctor forms subcollection (no user forms for extended procedures)
|
|
171
|
+
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
172
|
+
const doctorFormsRef = collection(appointmentRef, DOCTOR_FORMS_SUBCOLLECTION);
|
|
173
|
+
|
|
174
|
+
// Query doctor forms for this procedure
|
|
175
|
+
const doctorFormsQuery = query(
|
|
176
|
+
doctorFormsRef,
|
|
177
|
+
where('procedureId', '==', procedureId)
|
|
178
|
+
);
|
|
179
|
+
const doctorFormsSnap = await getDocs(doctorFormsQuery);
|
|
180
|
+
|
|
181
|
+
for (const formDoc of doctorFormsSnap.docs) {
|
|
182
|
+
try {
|
|
183
|
+
await deleteDoc(formDoc.ref);
|
|
184
|
+
removedFormIds.push(formDoc.id);
|
|
185
|
+
console.log(
|
|
186
|
+
`[FormInit] Removed doctor form ${formDoc.id} for extended procedure ${procedureId} from appointment ${appointmentId}.`
|
|
187
|
+
);
|
|
188
|
+
} catch (error) {
|
|
189
|
+
console.error(
|
|
190
|
+
`[FormInit] Error removing doctor form ${formDoc.id}:`,
|
|
191
|
+
error
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return removedFormIds;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Gets all forms associated with a specific procedure in an appointment
|
|
201
|
+
* @param db Firestore instance
|
|
202
|
+
* @param appointmentId Appointment ID
|
|
203
|
+
* @param procedureId Procedure ID
|
|
204
|
+
* @returns Array of form IDs
|
|
205
|
+
*/
|
|
206
|
+
export async function getFormsForExtendedProcedure(
|
|
207
|
+
db: Firestore,
|
|
208
|
+
appointmentId: string,
|
|
209
|
+
procedureId: string
|
|
210
|
+
): Promise<string[]> {
|
|
211
|
+
const formIds: string[] = [];
|
|
212
|
+
|
|
213
|
+
const appointmentRef = doc(db, APPOINTMENTS_COLLECTION, appointmentId);
|
|
214
|
+
const doctorFormsRef = collection(appointmentRef, DOCTOR_FORMS_SUBCOLLECTION);
|
|
215
|
+
|
|
216
|
+
// Query doctor forms for this procedure
|
|
217
|
+
const doctorFormsQuery = query(
|
|
218
|
+
doctorFormsRef,
|
|
219
|
+
where('procedureId', '==', procedureId)
|
|
220
|
+
);
|
|
221
|
+
const doctorFormsSnap = await getDocs(doctorFormsQuery);
|
|
222
|
+
doctorFormsSnap.docs.forEach(doc => formIds.push(doc.id));
|
|
223
|
+
|
|
224
|
+
return formIds;
|
|
225
|
+
}
|