@blackcode_sa/metaestetics-api 1.12.32 → 1.12.33
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 +68 -21
- package/dist/admin/index.d.ts +68 -21
- package/dist/admin/index.js +35 -5
- package/dist/admin/index.mjs +35 -5
- package/dist/index.d.mts +169 -22
- package/dist/index.d.ts +169 -22
- package/dist/index.js +2602 -1771
- package/dist/index.mjs +1823 -992
- package/package.json +1 -1
- package/src/admin/booking/booking.admin.ts +40 -4
- package/src/services/appointment/appointment.service.ts +278 -0
- package/src/services/appointment/utils/extended-procedure.utils.ts +232 -0
- package/src/services/appointment/utils/zone-management.utils.ts +335 -0
- package/src/services/patient/patient.service.ts +46 -0
- package/src/services/procedure/procedure.service.ts +54 -0
- package/src/types/appointment/index.ts +75 -26
- package/src/validations/appointment.schema.ts +100 -4
|
@@ -53,8 +53,14 @@ export const procedureExtendedInfoSchema = z.object({
|
|
|
53
53
|
procedureTechnologyName: z.string(),
|
|
54
54
|
procedureProductBrandId: z.string(),
|
|
55
55
|
procedureProductBrandName: z.string(),
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
procedureProducts: z.array(
|
|
57
|
+
z.object({
|
|
58
|
+
productId: z.string().min(MIN_STRING_LENGTH, 'Product ID is required'),
|
|
59
|
+
productName: z.string().min(MIN_STRING_LENGTH, 'Product name is required'),
|
|
60
|
+
brandId: z.string().min(MIN_STRING_LENGTH, 'Brand ID is required'),
|
|
61
|
+
brandName: z.string().min(MIN_STRING_LENGTH, 'Brand name is required'),
|
|
62
|
+
})
|
|
63
|
+
),
|
|
58
64
|
});
|
|
59
65
|
|
|
60
66
|
export const linkedFormInfoSchema = z.object({
|
|
@@ -164,18 +170,108 @@ export const finalBillingSchema = z.object({
|
|
|
164
170
|
taxRate: z.number().min(0).max(1, 'Tax rate must be between 0 and 1'),
|
|
165
171
|
taxPrice: z.number().min(0, 'Tax price must be non-negative'),
|
|
166
172
|
finalPrice: z.number().min(0, 'Final price must be non-negative'),
|
|
167
|
-
|
|
173
|
+
currency: z.nativeEnum(Currency),
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Schema for zone item data (product or note per zone)
|
|
178
|
+
*/
|
|
179
|
+
export const zoneItemDataSchema = z.object({
|
|
180
|
+
productId: z.string().optional(),
|
|
181
|
+
productName: z.string().optional(),
|
|
182
|
+
productBrandId: z.string().optional(),
|
|
183
|
+
productBrandName: z.string().optional(),
|
|
184
|
+
belongingProcedureId: z.string().min(MIN_STRING_LENGTH, 'Belonging procedure ID is required'),
|
|
185
|
+
type: z.enum(['item', 'note'], {
|
|
186
|
+
required_error: 'Type must be either "item" or "note"',
|
|
187
|
+
}),
|
|
188
|
+
price: z.number().min(0, 'Price must be non-negative').optional(),
|
|
189
|
+
currency: z.nativeEnum(Currency).optional(),
|
|
190
|
+
unitOfMeasurement: z.nativeEnum(PricingMeasure).optional(),
|
|
191
|
+
priceOverrideAmount: z.number().min(0, 'Price override amount must be non-negative').optional(),
|
|
192
|
+
quantity: z.number().min(0, 'Quantity must be non-negative').optional(),
|
|
193
|
+
parentZone: z.string().min(MIN_STRING_LENGTH, 'Parent zone is required').refine(
|
|
194
|
+
val => {
|
|
195
|
+
const parts = val.split('.');
|
|
196
|
+
return parts.length === 2;
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
message: 'Parent zone must be in "category.zone" format (e.g., "face.forehead")',
|
|
200
|
+
}
|
|
201
|
+
),
|
|
202
|
+
subzones: z.array(z.string()).refine(
|
|
203
|
+
val => {
|
|
204
|
+
return val.every(subzone => {
|
|
205
|
+
const parts = subzone.split('.');
|
|
206
|
+
return parts.length === 3;
|
|
207
|
+
});
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
message: 'Subzones must be in "category.zone.subzone" format (e.g., "face.forehead.left")',
|
|
211
|
+
}
|
|
212
|
+
),
|
|
213
|
+
notes: z.string().max(MAX_STRING_LENGTH_LONG, 'Notes too long').optional(),
|
|
214
|
+
subtotal: z.number().min(0, 'Subtotal must be non-negative').optional(),
|
|
215
|
+
ionNumber: z.string().optional(),
|
|
216
|
+
}).refine(
|
|
217
|
+
data => {
|
|
218
|
+
if (data.type === 'item') {
|
|
219
|
+
return !!(data.productId && data.productName && (data.price || data.priceOverrideAmount));
|
|
220
|
+
}
|
|
221
|
+
return true;
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
message: 'Item type requires productId, productName, and either price or priceOverrideAmount',
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Schema for appointment product metadata
|
|
230
|
+
*/
|
|
231
|
+
export const appointmentProductMetadataSchema = z.object({
|
|
232
|
+
productId: z.string().min(MIN_STRING_LENGTH, 'Product ID is required'),
|
|
233
|
+
productName: z.string().min(MIN_STRING_LENGTH, 'Product name is required'),
|
|
234
|
+
brandId: z.string().min(MIN_STRING_LENGTH, 'Brand ID is required'),
|
|
235
|
+
brandName: z.string().min(MIN_STRING_LENGTH, 'Brand name is required'),
|
|
236
|
+
procedureId: z.string().min(MIN_STRING_LENGTH, 'Procedure ID is required'),
|
|
237
|
+
price: z.number().min(0, 'Price must be non-negative'),
|
|
168
238
|
currency: z.nativeEnum(Currency),
|
|
169
239
|
unitOfMeasurement: z.nativeEnum(PricingMeasure),
|
|
170
240
|
});
|
|
171
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Schema for extended procedure info
|
|
244
|
+
*/
|
|
245
|
+
export const extendedProcedureInfoSchema = z.object({
|
|
246
|
+
procedureId: z.string().min(MIN_STRING_LENGTH, 'Procedure ID is required'),
|
|
247
|
+
procedureName: z.string().min(MIN_STRING_LENGTH, 'Procedure name is required'),
|
|
248
|
+
procedureFamily: z.any(),
|
|
249
|
+
procedureCategoryId: z.string().min(MIN_STRING_LENGTH, 'Category ID is required'),
|
|
250
|
+
procedureCategoryName: z.string().min(MIN_STRING_LENGTH, 'Category name is required'),
|
|
251
|
+
procedureSubCategoryId: z.string().min(MIN_STRING_LENGTH, 'Subcategory ID is required'),
|
|
252
|
+
procedureSubCategoryName: z.string().min(MIN_STRING_LENGTH, 'Subcategory name is required'),
|
|
253
|
+
procedureTechnologyId: z.string().min(MIN_STRING_LENGTH, 'Technology ID is required'),
|
|
254
|
+
procedureTechnologyName: z.string().min(MIN_STRING_LENGTH, 'Technology name is required'),
|
|
255
|
+
procedureProducts: z.array(
|
|
256
|
+
z.object({
|
|
257
|
+
productId: z.string().min(MIN_STRING_LENGTH, 'Product ID is required'),
|
|
258
|
+
productName: z.string().min(MIN_STRING_LENGTH, 'Product name is required'),
|
|
259
|
+
brandId: z.string().min(MIN_STRING_LENGTH, 'Brand ID is required'),
|
|
260
|
+
brandName: z.string().min(MIN_STRING_LENGTH, 'Brand name is required'),
|
|
261
|
+
})
|
|
262
|
+
),
|
|
263
|
+
});
|
|
264
|
+
|
|
172
265
|
/**
|
|
173
266
|
* Schema for appointment metadata containing zone-specific information
|
|
174
267
|
*/
|
|
175
268
|
export const appointmentMetadataSchema = z.object({
|
|
176
269
|
selectedZones: z.array(z.string()).nullable(),
|
|
177
270
|
zonePhotos: z.record(z.string(), beforeAfterPerZoneSchema).nullable(),
|
|
178
|
-
|
|
271
|
+
zonesData: z.record(z.string(), z.array(zoneItemDataSchema)).nullable(),
|
|
272
|
+
appointmentProducts: z.array(appointmentProductMetadataSchema),
|
|
273
|
+
extendedProcedures: z.array(extendedProcedureInfoSchema),
|
|
274
|
+
zoneBilling: z.record(z.string(), billingPerZoneSchema).nullable().optional(),
|
|
179
275
|
finalbilling: finalBillingSchema.nullable(),
|
|
180
276
|
finalizationNotes: z.string().nullable(),
|
|
181
277
|
});
|