@blackcode_sa/metaestetics-api 1.12.2 → 1.12.4
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/backoffice/index.d.mts +64 -14
- package/dist/backoffice/index.d.ts +64 -14
- package/dist/backoffice/index.js +72 -53
- package/dist/backoffice/index.mjs +72 -53
- package/dist/index.d.mts +212 -18
- package/dist/index.d.ts +212 -18
- package/dist/index.js +139 -53
- package/dist/index.mjs +137 -53
- package/package.json +1 -1
- package/src/backoffice/services/FIXES_README.md +102 -0
- package/src/backoffice/services/category.service.ts +46 -27
- package/src/backoffice/services/product.service.ts +52 -74
- package/src/backoffice/services/technology.service.ts +99 -116
- package/src/backoffice/types/category.types.ts +28 -2
- package/src/backoffice/types/product.types.ts +10 -9
- package/src/backoffice/types/technology.types.ts +31 -59
- package/src/types/clinic/index.ts +89 -0
- package/src/validations/clinic.schema.ts +68 -0
package/dist/index.js
CHANGED
|
@@ -37,6 +37,7 @@ __export(index_exports, {
|
|
|
37
37
|
AppointmentStatus: () => AppointmentStatus,
|
|
38
38
|
AuthService: () => AuthService,
|
|
39
39
|
BaseService: () => BaseService,
|
|
40
|
+
BillingTransactionType: () => BillingTransactionType,
|
|
40
41
|
BlockingCondition: () => BlockingCondition,
|
|
41
42
|
BrandService: () => BrandService,
|
|
42
43
|
CALENDAR_COLLECTION: () => CALENDAR_COLLECTION,
|
|
@@ -120,6 +121,7 @@ __export(index_exports, {
|
|
|
120
121
|
SearchLocationEnum: () => SearchLocationEnum,
|
|
121
122
|
SubcategoryService: () => SubcategoryService,
|
|
122
123
|
SubscriptionModel: () => SubscriptionModel,
|
|
124
|
+
SubscriptionStatus: () => SubscriptionStatus,
|
|
123
125
|
SyncedCalendarProvider: () => SyncedCalendarProvider,
|
|
124
126
|
SyncedCalendarsService: () => SyncedCalendarsService,
|
|
125
127
|
TechnologyService: () => TechnologyService,
|
|
@@ -888,6 +890,23 @@ var SubscriptionModel = /* @__PURE__ */ ((SubscriptionModel2) => {
|
|
|
888
890
|
SubscriptionModel2["ENTERPRISE"] = "enterprise";
|
|
889
891
|
return SubscriptionModel2;
|
|
890
892
|
})(SubscriptionModel || {});
|
|
893
|
+
var SubscriptionStatus = /* @__PURE__ */ ((SubscriptionStatus2) => {
|
|
894
|
+
SubscriptionStatus2["ACTIVE"] = "active";
|
|
895
|
+
SubscriptionStatus2["PENDING_CANCELLATION"] = "pending_cancellation";
|
|
896
|
+
SubscriptionStatus2["CANCELED"] = "canceled";
|
|
897
|
+
SubscriptionStatus2["PAST_DUE"] = "past_due";
|
|
898
|
+
SubscriptionStatus2["TRIALING"] = "trialing";
|
|
899
|
+
return SubscriptionStatus2;
|
|
900
|
+
})(SubscriptionStatus || {});
|
|
901
|
+
var BillingTransactionType = /* @__PURE__ */ ((BillingTransactionType2) => {
|
|
902
|
+
BillingTransactionType2["SUBSCRIPTION_ACTIVATED"] = "subscription_activated";
|
|
903
|
+
BillingTransactionType2["SUBSCRIPTION_RENEWED"] = "subscription_renewed";
|
|
904
|
+
BillingTransactionType2["SUBSCRIPTION_UPDATED"] = "subscription_updated";
|
|
905
|
+
BillingTransactionType2["SUBSCRIPTION_CANCELED"] = "subscription_canceled";
|
|
906
|
+
BillingTransactionType2["SUBSCRIPTION_REACTIVATED"] = "subscription_reactivated";
|
|
907
|
+
BillingTransactionType2["SUBSCRIPTION_DELETED"] = "subscription_deleted";
|
|
908
|
+
return BillingTransactionType2;
|
|
909
|
+
})(BillingTransactionType || {});
|
|
891
910
|
|
|
892
911
|
// src/types/patient/medical-info.types.ts
|
|
893
912
|
var PATIENT_MEDICAL_INFO_COLLECTION = "medical_info";
|
|
@@ -3508,6 +3527,50 @@ var adminTokenSchema = import_zod10.z.object({
|
|
|
3508
3527
|
expiresAt: import_zod10.z.instanceof(Date).or(import_zod10.z.instanceof(import_firestore9.Timestamp))
|
|
3509
3528
|
// Timestamp
|
|
3510
3529
|
});
|
|
3530
|
+
var stripeTransactionDataSchema = import_zod10.z.object({
|
|
3531
|
+
sessionId: import_zod10.z.string().optional(),
|
|
3532
|
+
subscriptionId: import_zod10.z.string().optional(),
|
|
3533
|
+
invoiceId: import_zod10.z.string().optional(),
|
|
3534
|
+
priceId: import_zod10.z.string(),
|
|
3535
|
+
customerId: import_zod10.z.string()
|
|
3536
|
+
});
|
|
3537
|
+
var planDetailsSchema = import_zod10.z.object({
|
|
3538
|
+
planName: import_zod10.z.string(),
|
|
3539
|
+
planPeriod: import_zod10.z.string(),
|
|
3540
|
+
planDisplayName: import_zod10.z.string()
|
|
3541
|
+
});
|
|
3542
|
+
var billingInfoSchema = import_zod10.z.object({
|
|
3543
|
+
stripeCustomerId: import_zod10.z.string(),
|
|
3544
|
+
subscriptionStatus: import_zod10.z.nativeEnum(SubscriptionStatus),
|
|
3545
|
+
planType: import_zod10.z.string(),
|
|
3546
|
+
stripeSubscriptionId: import_zod10.z.string().nullable(),
|
|
3547
|
+
stripePriceId: import_zod10.z.string().nullable(),
|
|
3548
|
+
currentPeriodStart: import_zod10.z.instanceof(Date).or(import_zod10.z.instanceof(import_firestore9.Timestamp)).nullable(),
|
|
3549
|
+
currentPeriodEnd: import_zod10.z.instanceof(Date).or(import_zod10.z.instanceof(import_firestore9.Timestamp)).nullable(),
|
|
3550
|
+
updatedAt: import_zod10.z.instanceof(Date).or(import_zod10.z.instanceof(import_firestore9.Timestamp))
|
|
3551
|
+
});
|
|
3552
|
+
var billingTransactionSchema = import_zod10.z.object({
|
|
3553
|
+
id: import_zod10.z.string(),
|
|
3554
|
+
clinicGroupId: import_zod10.z.string(),
|
|
3555
|
+
type: import_zod10.z.nativeEnum(BillingTransactionType),
|
|
3556
|
+
description: import_zod10.z.string(),
|
|
3557
|
+
amount: import_zod10.z.number(),
|
|
3558
|
+
currency: import_zod10.z.string(),
|
|
3559
|
+
stripeData: stripeTransactionDataSchema,
|
|
3560
|
+
planDetails: planDetailsSchema,
|
|
3561
|
+
metadata: import_zod10.z.record(import_zod10.z.any()).optional(),
|
|
3562
|
+
timestamp: import_zod10.z.instanceof(Date).or(import_zod10.z.instanceof(import_firestore9.Timestamp)),
|
|
3563
|
+
createdAt: import_zod10.z.instanceof(Date).or(import_zod10.z.instanceof(import_firestore9.Timestamp))
|
|
3564
|
+
});
|
|
3565
|
+
var createBillingTransactionSchema = import_zod10.z.object({
|
|
3566
|
+
type: import_zod10.z.nativeEnum(BillingTransactionType),
|
|
3567
|
+
description: import_zod10.z.string(),
|
|
3568
|
+
amount: import_zod10.z.number(),
|
|
3569
|
+
currency: import_zod10.z.string(),
|
|
3570
|
+
stripeData: stripeTransactionDataSchema,
|
|
3571
|
+
planDetails: planDetailsSchema,
|
|
3572
|
+
metadata: import_zod10.z.record(import_zod10.z.any()).optional()
|
|
3573
|
+
});
|
|
3511
3574
|
var createAdminTokenSchema = import_zod10.z.object({
|
|
3512
3575
|
expiresInDays: import_zod10.z.number().min(1).max(30).optional(),
|
|
3513
3576
|
email: import_zod10.z.string().email().optional().nullable()
|
|
@@ -3534,6 +3597,7 @@ var clinicGroupSchema = import_zod10.z.object({
|
|
|
3534
3597
|
practiceType: import_zod10.z.nativeEnum(PracticeType).optional(),
|
|
3535
3598
|
languages: import_zod10.z.array(import_zod10.z.nativeEnum(Language)).optional(),
|
|
3536
3599
|
subscriptionModel: import_zod10.z.nativeEnum(SubscriptionModel),
|
|
3600
|
+
billing: billingInfoSchema.optional(),
|
|
3537
3601
|
calendarSyncEnabled: import_zod10.z.boolean().optional(),
|
|
3538
3602
|
autoConfirmAppointments: import_zod10.z.boolean().optional(),
|
|
3539
3603
|
businessIdentificationNumber: import_zod10.z.string().optional().nullable(),
|
|
@@ -3599,6 +3663,7 @@ var createClinicGroupSchema = import_zod10.z.object({
|
|
|
3599
3663
|
practiceType: import_zod10.z.nativeEnum(PracticeType).optional(),
|
|
3600
3664
|
languages: import_zod10.z.array(import_zod10.z.nativeEnum(Language)).optional(),
|
|
3601
3665
|
subscriptionModel: import_zod10.z.nativeEnum(SubscriptionModel).optional().default("no_subscription" /* NO_SUBSCRIPTION */),
|
|
3666
|
+
billing: billingInfoSchema.optional(),
|
|
3602
3667
|
calendarSyncEnabled: import_zod10.z.boolean().optional(),
|
|
3603
3668
|
autoConfirmAppointments: import_zod10.z.boolean().optional(),
|
|
3604
3669
|
businessIdentificationNumber: import_zod10.z.string().optional().nullable(),
|
|
@@ -16544,6 +16609,26 @@ var CategoryService = class extends BaseService {
|
|
|
16544
16609
|
})
|
|
16545
16610
|
);
|
|
16546
16611
|
}
|
|
16612
|
+
/**
|
|
16613
|
+
* Vraća sve kategorije za određenu familiju za potrebe filtera (bez paginacije)
|
|
16614
|
+
* @param family - Familija procedura (aesthetics/surgery)
|
|
16615
|
+
* @returns Lista aktivnih kategorija koje pripadaju traženoj familiji
|
|
16616
|
+
*/
|
|
16617
|
+
async getAllForFilterByFamily(family) {
|
|
16618
|
+
const q = (0, import_firestore50.query)(
|
|
16619
|
+
this.categoriesRef,
|
|
16620
|
+
(0, import_firestore50.where)("family", "==", family),
|
|
16621
|
+
(0, import_firestore50.where)("isActive", "==", true),
|
|
16622
|
+
(0, import_firestore50.orderBy)("name")
|
|
16623
|
+
);
|
|
16624
|
+
const snapshot = await (0, import_firestore50.getDocs)(q);
|
|
16625
|
+
return snapshot.docs.map(
|
|
16626
|
+
(doc38) => ({
|
|
16627
|
+
id: doc38.id,
|
|
16628
|
+
...doc38.data()
|
|
16629
|
+
})
|
|
16630
|
+
);
|
|
16631
|
+
}
|
|
16547
16632
|
/**
|
|
16548
16633
|
* Vraća sve kategorije sa paginacijom
|
|
16549
16634
|
* @param options - Pagination and filter options
|
|
@@ -17177,7 +17262,9 @@ var TechnologyService = class extends BaseService {
|
|
|
17177
17262
|
if (!technology) {
|
|
17178
17263
|
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17179
17264
|
}
|
|
17180
|
-
const updatedContraindications = (technology.contraindications || []).filter(
|
|
17265
|
+
const updatedContraindications = (technology.contraindications || []).filter(
|
|
17266
|
+
(c) => c.id !== contraindication.id
|
|
17267
|
+
);
|
|
17181
17268
|
await (0, import_firestore52.updateDoc)(docRef, {
|
|
17182
17269
|
contraindications: updatedContraindications,
|
|
17183
17270
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -17198,9 +17285,7 @@ var TechnologyService = class extends BaseService {
|
|
|
17198
17285
|
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17199
17286
|
}
|
|
17200
17287
|
const contraindications = technology.contraindications || [];
|
|
17201
|
-
const index = contraindications.findIndex(
|
|
17202
|
-
(c) => c.id === contraindication.id
|
|
17203
|
-
);
|
|
17288
|
+
const index = contraindications.findIndex((c) => c.id === contraindication.id);
|
|
17204
17289
|
if (index === -1) {
|
|
17205
17290
|
console.warn(
|
|
17206
17291
|
`Contraindication with id ${contraindication.id} not found for technology ${technologyId}. No update performed.`
|
|
@@ -17249,9 +17334,7 @@ var TechnologyService = class extends BaseService {
|
|
|
17249
17334
|
if (!technology) {
|
|
17250
17335
|
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17251
17336
|
}
|
|
17252
|
-
const updatedBenefits = (technology.benefits || []).filter(
|
|
17253
|
-
(b) => b.id !== benefit.id
|
|
17254
|
-
);
|
|
17337
|
+
const updatedBenefits = (technology.benefits || []).filter((b) => b.id !== benefit.id);
|
|
17255
17338
|
await (0, import_firestore52.updateDoc)(docRef, {
|
|
17256
17339
|
benefits: updatedBenefits,
|
|
17257
17340
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -17357,9 +17440,7 @@ var TechnologyService = class extends BaseService {
|
|
|
17357
17440
|
* );
|
|
17358
17441
|
*/
|
|
17359
17442
|
validateCertification(requiredCertification, practitionerCertification) {
|
|
17360
|
-
const doctorLevel = Object.values(CertificationLevel).indexOf(
|
|
17361
|
-
practitionerCertification.level
|
|
17362
|
-
);
|
|
17443
|
+
const doctorLevel = Object.values(CertificationLevel).indexOf(practitionerCertification.level);
|
|
17363
17444
|
const requiredLevel = Object.values(CertificationLevel).indexOf(
|
|
17364
17445
|
requiredCertification.minimumLevel
|
|
17365
17446
|
);
|
|
@@ -17400,18 +17481,11 @@ var TechnologyService = class extends BaseService {
|
|
|
17400
17481
|
async getAllowedTechnologies(practitioner) {
|
|
17401
17482
|
const allTechnologies = await this.getAll();
|
|
17402
17483
|
const allowedTechnologies = allTechnologies.technologies.filter(
|
|
17403
|
-
(technology) => this.validateCertification(
|
|
17404
|
-
technology.certificationRequirement,
|
|
17405
|
-
practitioner.certification
|
|
17406
|
-
)
|
|
17484
|
+
(technology) => this.validateCertification(technology.certificationRequirement, practitioner.certification)
|
|
17407
17485
|
);
|
|
17408
17486
|
const families = [...new Set(allowedTechnologies.map((t) => t.family))];
|
|
17409
|
-
const categories = [
|
|
17410
|
-
|
|
17411
|
-
];
|
|
17412
|
-
const subcategories = [
|
|
17413
|
-
...new Set(allowedTechnologies.map((t) => t.subcategoryId))
|
|
17414
|
-
];
|
|
17487
|
+
const categories = [...new Set(allowedTechnologies.map((t) => t.categoryId))];
|
|
17488
|
+
const subcategories = [...new Set(allowedTechnologies.map((t) => t.subcategoryId))];
|
|
17415
17489
|
return {
|
|
17416
17490
|
technologies: allowedTechnologies,
|
|
17417
17491
|
families,
|
|
@@ -17419,6 +17493,25 @@ var TechnologyService = class extends BaseService {
|
|
|
17419
17493
|
subcategories
|
|
17420
17494
|
};
|
|
17421
17495
|
}
|
|
17496
|
+
/**
|
|
17497
|
+
* Gets all active technologies for a subcategory for filter dropdowns (by subcategory only).
|
|
17498
|
+
* @param subcategoryId - The ID of the subcategory.
|
|
17499
|
+
*/
|
|
17500
|
+
async getAllForFilterBySubcategory(subcategoryId) {
|
|
17501
|
+
const q = (0, import_firestore52.query)(
|
|
17502
|
+
(0, import_firestore52.collection)(this.db, TECHNOLOGIES_COLLECTION),
|
|
17503
|
+
(0, import_firestore52.where)("isActive", "==", true),
|
|
17504
|
+
(0, import_firestore52.where)("subcategoryId", "==", subcategoryId),
|
|
17505
|
+
(0, import_firestore52.orderBy)("name")
|
|
17506
|
+
);
|
|
17507
|
+
const snapshot = await (0, import_firestore52.getDocs)(q);
|
|
17508
|
+
return snapshot.docs.map(
|
|
17509
|
+
(doc38) => ({
|
|
17510
|
+
id: doc38.id,
|
|
17511
|
+
...doc38.data()
|
|
17512
|
+
})
|
|
17513
|
+
);
|
|
17514
|
+
}
|
|
17422
17515
|
/**
|
|
17423
17516
|
* Gets all active technologies for a subcategory for filter dropdowns.
|
|
17424
17517
|
* @param categoryId - The ID of the parent category.
|
|
@@ -17473,12 +17566,7 @@ var ProductService = class extends BaseService {
|
|
|
17473
17566
|
* @returns Firestore collection reference
|
|
17474
17567
|
*/
|
|
17475
17568
|
getProductsRef(technologyId) {
|
|
17476
|
-
return (0, import_firestore53.collection)(
|
|
17477
|
-
this.db,
|
|
17478
|
-
TECHNOLOGIES_COLLECTION,
|
|
17479
|
-
technologyId,
|
|
17480
|
-
PRODUCTS_COLLECTION
|
|
17481
|
-
);
|
|
17569
|
+
return (0, import_firestore53.collection)(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
|
|
17482
17570
|
}
|
|
17483
17571
|
/**
|
|
17484
17572
|
* Creates a new product under technology
|
|
@@ -17493,10 +17581,7 @@ var ProductService = class extends BaseService {
|
|
|
17493
17581
|
updatedAt: now,
|
|
17494
17582
|
isActive: true
|
|
17495
17583
|
};
|
|
17496
|
-
const productRef = await (0, import_firestore53.addDoc)(
|
|
17497
|
-
this.getProductsRef(technologyId),
|
|
17498
|
-
newProduct
|
|
17499
|
-
);
|
|
17584
|
+
const productRef = await (0, import_firestore53.addDoc)(this.getProductsRef(technologyId), newProduct);
|
|
17500
17585
|
return { id: productRef.id, ...newProduct };
|
|
17501
17586
|
}
|
|
17502
17587
|
/**
|
|
@@ -17504,17 +17589,8 @@ var ProductService = class extends BaseService {
|
|
|
17504
17589
|
* This uses a collectionGroup query to search across all technologies.
|
|
17505
17590
|
*/
|
|
17506
17591
|
async getAll(options) {
|
|
17507
|
-
const {
|
|
17508
|
-
|
|
17509
|
-
lastVisible,
|
|
17510
|
-
categoryId,
|
|
17511
|
-
subcategoryId,
|
|
17512
|
-
technologyId
|
|
17513
|
-
} = options;
|
|
17514
|
-
const constraints = [
|
|
17515
|
-
(0, import_firestore53.where)("isActive", "==", true),
|
|
17516
|
-
(0, import_firestore53.orderBy)("name")
|
|
17517
|
-
];
|
|
17592
|
+
const { rowsPerPage, lastVisible, categoryId, subcategoryId, technologyId } = options;
|
|
17593
|
+
const constraints = [(0, import_firestore53.where)("isActive", "==", true), (0, import_firestore53.orderBy)("name")];
|
|
17518
17594
|
if (categoryId) {
|
|
17519
17595
|
constraints.push((0, import_firestore53.where)("categoryId", "==", categoryId));
|
|
17520
17596
|
}
|
|
@@ -17528,10 +17604,7 @@ var ProductService = class extends BaseService {
|
|
|
17528
17604
|
constraints.push((0, import_firestore53.startAfter)(lastVisible));
|
|
17529
17605
|
}
|
|
17530
17606
|
constraints.push((0, import_firestore53.limit)(rowsPerPage));
|
|
17531
|
-
const q = (0, import_firestore53.query)(
|
|
17532
|
-
(0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION),
|
|
17533
|
-
...constraints
|
|
17534
|
-
);
|
|
17607
|
+
const q = (0, import_firestore53.query)((0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION), ...constraints);
|
|
17535
17608
|
const snapshot = await (0, import_firestore53.getDocs)(q);
|
|
17536
17609
|
const products = snapshot.docs.map(
|
|
17537
17610
|
(doc38) => ({
|
|
@@ -17557,10 +17630,7 @@ var ProductService = class extends BaseService {
|
|
|
17557
17630
|
if (technologyId) {
|
|
17558
17631
|
constraints.push((0, import_firestore53.where)("technologyId", "==", technologyId));
|
|
17559
17632
|
}
|
|
17560
|
-
const q = (0, import_firestore53.query)(
|
|
17561
|
-
(0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION),
|
|
17562
|
-
...constraints
|
|
17563
|
-
);
|
|
17633
|
+
const q = (0, import_firestore53.query)((0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION), ...constraints);
|
|
17564
17634
|
const snapshot = await (0, import_firestore53.getCountFromServer)(q);
|
|
17565
17635
|
return snapshot.data().count;
|
|
17566
17636
|
}
|
|
@@ -17569,10 +17639,7 @@ var ProductService = class extends BaseService {
|
|
|
17569
17639
|
* This uses a single collectionGroup query for efficiency.
|
|
17570
17640
|
*/
|
|
17571
17641
|
async getProductCounts() {
|
|
17572
|
-
const q = (0, import_firestore53.query)(
|
|
17573
|
-
(0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION),
|
|
17574
|
-
(0, import_firestore53.where)("isActive", "==", true)
|
|
17575
|
-
);
|
|
17642
|
+
const q = (0, import_firestore53.query)((0, import_firestore53.collectionGroup)(this.db, PRODUCTS_COLLECTION), (0, import_firestore53.where)("isActive", "==", true));
|
|
17576
17643
|
const snapshot = await (0, import_firestore53.getDocs)(q);
|
|
17577
17644
|
const counts = {
|
|
17578
17645
|
byCategory: {},
|
|
@@ -17597,6 +17664,23 @@ var ProductService = class extends BaseService {
|
|
|
17597
17664
|
});
|
|
17598
17665
|
return counts;
|
|
17599
17666
|
}
|
|
17667
|
+
/**
|
|
17668
|
+
* Gets all products for a specific technology (non-paginated, for filters/dropdowns)
|
|
17669
|
+
*/
|
|
17670
|
+
async getAllByTechnology(technologyId) {
|
|
17671
|
+
const q = (0, import_firestore53.query)(
|
|
17672
|
+
this.getProductsRef(technologyId),
|
|
17673
|
+
(0, import_firestore53.where)("isActive", "==", true),
|
|
17674
|
+
(0, import_firestore53.orderBy)("name")
|
|
17675
|
+
);
|
|
17676
|
+
const snapshot = await (0, import_firestore53.getDocs)(q);
|
|
17677
|
+
return snapshot.docs.map(
|
|
17678
|
+
(doc38) => ({
|
|
17679
|
+
id: doc38.id,
|
|
17680
|
+
...doc38.data()
|
|
17681
|
+
})
|
|
17682
|
+
);
|
|
17683
|
+
}
|
|
17600
17684
|
/**
|
|
17601
17685
|
* Gets all products for a brand by filtering through all technologies
|
|
17602
17686
|
*/
|
|
@@ -17945,6 +18029,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
|
|
|
17945
18029
|
AppointmentStatus,
|
|
17946
18030
|
AuthService,
|
|
17947
18031
|
BaseService,
|
|
18032
|
+
BillingTransactionType,
|
|
17948
18033
|
BlockingCondition,
|
|
17949
18034
|
BrandService,
|
|
17950
18035
|
CALENDAR_COLLECTION,
|
|
@@ -18028,6 +18113,7 @@ var RequirementType = /* @__PURE__ */ ((RequirementType2) => {
|
|
|
18028
18113
|
SearchLocationEnum,
|
|
18029
18114
|
SubcategoryService,
|
|
18030
18115
|
SubscriptionModel,
|
|
18116
|
+
SubscriptionStatus,
|
|
18031
18117
|
SyncedCalendarProvider,
|
|
18032
18118
|
SyncedCalendarsService,
|
|
18033
18119
|
TechnologyService,
|
package/dist/index.mjs
CHANGED
|
@@ -772,6 +772,23 @@ var SubscriptionModel = /* @__PURE__ */ ((SubscriptionModel2) => {
|
|
|
772
772
|
SubscriptionModel2["ENTERPRISE"] = "enterprise";
|
|
773
773
|
return SubscriptionModel2;
|
|
774
774
|
})(SubscriptionModel || {});
|
|
775
|
+
var SubscriptionStatus = /* @__PURE__ */ ((SubscriptionStatus2) => {
|
|
776
|
+
SubscriptionStatus2["ACTIVE"] = "active";
|
|
777
|
+
SubscriptionStatus2["PENDING_CANCELLATION"] = "pending_cancellation";
|
|
778
|
+
SubscriptionStatus2["CANCELED"] = "canceled";
|
|
779
|
+
SubscriptionStatus2["PAST_DUE"] = "past_due";
|
|
780
|
+
SubscriptionStatus2["TRIALING"] = "trialing";
|
|
781
|
+
return SubscriptionStatus2;
|
|
782
|
+
})(SubscriptionStatus || {});
|
|
783
|
+
var BillingTransactionType = /* @__PURE__ */ ((BillingTransactionType2) => {
|
|
784
|
+
BillingTransactionType2["SUBSCRIPTION_ACTIVATED"] = "subscription_activated";
|
|
785
|
+
BillingTransactionType2["SUBSCRIPTION_RENEWED"] = "subscription_renewed";
|
|
786
|
+
BillingTransactionType2["SUBSCRIPTION_UPDATED"] = "subscription_updated";
|
|
787
|
+
BillingTransactionType2["SUBSCRIPTION_CANCELED"] = "subscription_canceled";
|
|
788
|
+
BillingTransactionType2["SUBSCRIPTION_REACTIVATED"] = "subscription_reactivated";
|
|
789
|
+
BillingTransactionType2["SUBSCRIPTION_DELETED"] = "subscription_deleted";
|
|
790
|
+
return BillingTransactionType2;
|
|
791
|
+
})(BillingTransactionType || {});
|
|
775
792
|
|
|
776
793
|
// src/types/patient/medical-info.types.ts
|
|
777
794
|
var PATIENT_MEDICAL_INFO_COLLECTION = "medical_info";
|
|
@@ -3490,6 +3507,50 @@ var adminTokenSchema = z10.object({
|
|
|
3490
3507
|
expiresAt: z10.instanceof(Date).or(z10.instanceof(Timestamp6))
|
|
3491
3508
|
// Timestamp
|
|
3492
3509
|
});
|
|
3510
|
+
var stripeTransactionDataSchema = z10.object({
|
|
3511
|
+
sessionId: z10.string().optional(),
|
|
3512
|
+
subscriptionId: z10.string().optional(),
|
|
3513
|
+
invoiceId: z10.string().optional(),
|
|
3514
|
+
priceId: z10.string(),
|
|
3515
|
+
customerId: z10.string()
|
|
3516
|
+
});
|
|
3517
|
+
var planDetailsSchema = z10.object({
|
|
3518
|
+
planName: z10.string(),
|
|
3519
|
+
planPeriod: z10.string(),
|
|
3520
|
+
planDisplayName: z10.string()
|
|
3521
|
+
});
|
|
3522
|
+
var billingInfoSchema = z10.object({
|
|
3523
|
+
stripeCustomerId: z10.string(),
|
|
3524
|
+
subscriptionStatus: z10.nativeEnum(SubscriptionStatus),
|
|
3525
|
+
planType: z10.string(),
|
|
3526
|
+
stripeSubscriptionId: z10.string().nullable(),
|
|
3527
|
+
stripePriceId: z10.string().nullable(),
|
|
3528
|
+
currentPeriodStart: z10.instanceof(Date).or(z10.instanceof(Timestamp6)).nullable(),
|
|
3529
|
+
currentPeriodEnd: z10.instanceof(Date).or(z10.instanceof(Timestamp6)).nullable(),
|
|
3530
|
+
updatedAt: z10.instanceof(Date).or(z10.instanceof(Timestamp6))
|
|
3531
|
+
});
|
|
3532
|
+
var billingTransactionSchema = z10.object({
|
|
3533
|
+
id: z10.string(),
|
|
3534
|
+
clinicGroupId: z10.string(),
|
|
3535
|
+
type: z10.nativeEnum(BillingTransactionType),
|
|
3536
|
+
description: z10.string(),
|
|
3537
|
+
amount: z10.number(),
|
|
3538
|
+
currency: z10.string(),
|
|
3539
|
+
stripeData: stripeTransactionDataSchema,
|
|
3540
|
+
planDetails: planDetailsSchema,
|
|
3541
|
+
metadata: z10.record(z10.any()).optional(),
|
|
3542
|
+
timestamp: z10.instanceof(Date).or(z10.instanceof(Timestamp6)),
|
|
3543
|
+
createdAt: z10.instanceof(Date).or(z10.instanceof(Timestamp6))
|
|
3544
|
+
});
|
|
3545
|
+
var createBillingTransactionSchema = z10.object({
|
|
3546
|
+
type: z10.nativeEnum(BillingTransactionType),
|
|
3547
|
+
description: z10.string(),
|
|
3548
|
+
amount: z10.number(),
|
|
3549
|
+
currency: z10.string(),
|
|
3550
|
+
stripeData: stripeTransactionDataSchema,
|
|
3551
|
+
planDetails: planDetailsSchema,
|
|
3552
|
+
metadata: z10.record(z10.any()).optional()
|
|
3553
|
+
});
|
|
3493
3554
|
var createAdminTokenSchema = z10.object({
|
|
3494
3555
|
expiresInDays: z10.number().min(1).max(30).optional(),
|
|
3495
3556
|
email: z10.string().email().optional().nullable()
|
|
@@ -3516,6 +3577,7 @@ var clinicGroupSchema = z10.object({
|
|
|
3516
3577
|
practiceType: z10.nativeEnum(PracticeType).optional(),
|
|
3517
3578
|
languages: z10.array(z10.nativeEnum(Language)).optional(),
|
|
3518
3579
|
subscriptionModel: z10.nativeEnum(SubscriptionModel),
|
|
3580
|
+
billing: billingInfoSchema.optional(),
|
|
3519
3581
|
calendarSyncEnabled: z10.boolean().optional(),
|
|
3520
3582
|
autoConfirmAppointments: z10.boolean().optional(),
|
|
3521
3583
|
businessIdentificationNumber: z10.string().optional().nullable(),
|
|
@@ -3581,6 +3643,7 @@ var createClinicGroupSchema = z10.object({
|
|
|
3581
3643
|
practiceType: z10.nativeEnum(PracticeType).optional(),
|
|
3582
3644
|
languages: z10.array(z10.nativeEnum(Language)).optional(),
|
|
3583
3645
|
subscriptionModel: z10.nativeEnum(SubscriptionModel).optional().default("no_subscription" /* NO_SUBSCRIPTION */),
|
|
3646
|
+
billing: billingInfoSchema.optional(),
|
|
3584
3647
|
calendarSyncEnabled: z10.boolean().optional(),
|
|
3585
3648
|
autoConfirmAppointments: z10.boolean().optional(),
|
|
3586
3649
|
businessIdentificationNumber: z10.string().optional().nullable(),
|
|
@@ -16829,6 +16892,26 @@ var CategoryService = class extends BaseService {
|
|
|
16829
16892
|
})
|
|
16830
16893
|
);
|
|
16831
16894
|
}
|
|
16895
|
+
/**
|
|
16896
|
+
* Vraća sve kategorije za određenu familiju za potrebe filtera (bez paginacije)
|
|
16897
|
+
* @param family - Familija procedura (aesthetics/surgery)
|
|
16898
|
+
* @returns Lista aktivnih kategorija koje pripadaju traženoj familiji
|
|
16899
|
+
*/
|
|
16900
|
+
async getAllForFilterByFamily(family) {
|
|
16901
|
+
const q = query32(
|
|
16902
|
+
this.categoriesRef,
|
|
16903
|
+
where32("family", "==", family),
|
|
16904
|
+
where32("isActive", "==", true),
|
|
16905
|
+
orderBy19("name")
|
|
16906
|
+
);
|
|
16907
|
+
const snapshot = await getDocs32(q);
|
|
16908
|
+
return snapshot.docs.map(
|
|
16909
|
+
(doc38) => ({
|
|
16910
|
+
id: doc38.id,
|
|
16911
|
+
...doc38.data()
|
|
16912
|
+
})
|
|
16913
|
+
);
|
|
16914
|
+
}
|
|
16832
16915
|
/**
|
|
16833
16916
|
* Vraća sve kategorije sa paginacijom
|
|
16834
16917
|
* @param options - Pagination and filter options
|
|
@@ -17492,7 +17575,9 @@ var TechnologyService = class extends BaseService {
|
|
|
17492
17575
|
if (!technology) {
|
|
17493
17576
|
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17494
17577
|
}
|
|
17495
|
-
const updatedContraindications = (technology.contraindications || []).filter(
|
|
17578
|
+
const updatedContraindications = (technology.contraindications || []).filter(
|
|
17579
|
+
(c) => c.id !== contraindication.id
|
|
17580
|
+
);
|
|
17496
17581
|
await updateDoc33(docRef, {
|
|
17497
17582
|
contraindications: updatedContraindications,
|
|
17498
17583
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -17513,9 +17598,7 @@ var TechnologyService = class extends BaseService {
|
|
|
17513
17598
|
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17514
17599
|
}
|
|
17515
17600
|
const contraindications = technology.contraindications || [];
|
|
17516
|
-
const index = contraindications.findIndex(
|
|
17517
|
-
(c) => c.id === contraindication.id
|
|
17518
|
-
);
|
|
17601
|
+
const index = contraindications.findIndex((c) => c.id === contraindication.id);
|
|
17519
17602
|
if (index === -1) {
|
|
17520
17603
|
console.warn(
|
|
17521
17604
|
`Contraindication with id ${contraindication.id} not found for technology ${technologyId}. No update performed.`
|
|
@@ -17564,9 +17647,7 @@ var TechnologyService = class extends BaseService {
|
|
|
17564
17647
|
if (!technology) {
|
|
17565
17648
|
throw new Error(`Technology with id ${technologyId} not found`);
|
|
17566
17649
|
}
|
|
17567
|
-
const updatedBenefits = (technology.benefits || []).filter(
|
|
17568
|
-
(b) => b.id !== benefit.id
|
|
17569
|
-
);
|
|
17650
|
+
const updatedBenefits = (technology.benefits || []).filter((b) => b.id !== benefit.id);
|
|
17570
17651
|
await updateDoc33(docRef, {
|
|
17571
17652
|
benefits: updatedBenefits,
|
|
17572
17653
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -17672,9 +17753,7 @@ var TechnologyService = class extends BaseService {
|
|
|
17672
17753
|
* );
|
|
17673
17754
|
*/
|
|
17674
17755
|
validateCertification(requiredCertification, practitionerCertification) {
|
|
17675
|
-
const doctorLevel = Object.values(CertificationLevel).indexOf(
|
|
17676
|
-
practitionerCertification.level
|
|
17677
|
-
);
|
|
17756
|
+
const doctorLevel = Object.values(CertificationLevel).indexOf(practitionerCertification.level);
|
|
17678
17757
|
const requiredLevel = Object.values(CertificationLevel).indexOf(
|
|
17679
17758
|
requiredCertification.minimumLevel
|
|
17680
17759
|
);
|
|
@@ -17715,18 +17794,11 @@ var TechnologyService = class extends BaseService {
|
|
|
17715
17794
|
async getAllowedTechnologies(practitioner) {
|
|
17716
17795
|
const allTechnologies = await this.getAll();
|
|
17717
17796
|
const allowedTechnologies = allTechnologies.technologies.filter(
|
|
17718
|
-
(technology) => this.validateCertification(
|
|
17719
|
-
technology.certificationRequirement,
|
|
17720
|
-
practitioner.certification
|
|
17721
|
-
)
|
|
17797
|
+
(technology) => this.validateCertification(technology.certificationRequirement, practitioner.certification)
|
|
17722
17798
|
);
|
|
17723
17799
|
const families = [...new Set(allowedTechnologies.map((t) => t.family))];
|
|
17724
|
-
const categories = [
|
|
17725
|
-
|
|
17726
|
-
];
|
|
17727
|
-
const subcategories = [
|
|
17728
|
-
...new Set(allowedTechnologies.map((t) => t.subcategoryId))
|
|
17729
|
-
];
|
|
17800
|
+
const categories = [...new Set(allowedTechnologies.map((t) => t.categoryId))];
|
|
17801
|
+
const subcategories = [...new Set(allowedTechnologies.map((t) => t.subcategoryId))];
|
|
17730
17802
|
return {
|
|
17731
17803
|
technologies: allowedTechnologies,
|
|
17732
17804
|
families,
|
|
@@ -17734,6 +17806,25 @@ var TechnologyService = class extends BaseService {
|
|
|
17734
17806
|
subcategories
|
|
17735
17807
|
};
|
|
17736
17808
|
}
|
|
17809
|
+
/**
|
|
17810
|
+
* Gets all active technologies for a subcategory for filter dropdowns (by subcategory only).
|
|
17811
|
+
* @param subcategoryId - The ID of the subcategory.
|
|
17812
|
+
*/
|
|
17813
|
+
async getAllForFilterBySubcategory(subcategoryId) {
|
|
17814
|
+
const q = query34(
|
|
17815
|
+
collection34(this.db, TECHNOLOGIES_COLLECTION),
|
|
17816
|
+
where34("isActive", "==", true),
|
|
17817
|
+
where34("subcategoryId", "==", subcategoryId),
|
|
17818
|
+
orderBy21("name")
|
|
17819
|
+
);
|
|
17820
|
+
const snapshot = await getDocs34(q);
|
|
17821
|
+
return snapshot.docs.map(
|
|
17822
|
+
(doc38) => ({
|
|
17823
|
+
id: doc38.id,
|
|
17824
|
+
...doc38.data()
|
|
17825
|
+
})
|
|
17826
|
+
);
|
|
17827
|
+
}
|
|
17737
17828
|
/**
|
|
17738
17829
|
* Gets all active technologies for a subcategory for filter dropdowns.
|
|
17739
17830
|
* @param categoryId - The ID of the parent category.
|
|
@@ -17802,12 +17893,7 @@ var ProductService = class extends BaseService {
|
|
|
17802
17893
|
* @returns Firestore collection reference
|
|
17803
17894
|
*/
|
|
17804
17895
|
getProductsRef(technologyId) {
|
|
17805
|
-
return collection35(
|
|
17806
|
-
this.db,
|
|
17807
|
-
TECHNOLOGIES_COLLECTION,
|
|
17808
|
-
technologyId,
|
|
17809
|
-
PRODUCTS_COLLECTION
|
|
17810
|
-
);
|
|
17896
|
+
return collection35(this.db, TECHNOLOGIES_COLLECTION, technologyId, PRODUCTS_COLLECTION);
|
|
17811
17897
|
}
|
|
17812
17898
|
/**
|
|
17813
17899
|
* Creates a new product under technology
|
|
@@ -17822,10 +17908,7 @@ var ProductService = class extends BaseService {
|
|
|
17822
17908
|
updatedAt: now,
|
|
17823
17909
|
isActive: true
|
|
17824
17910
|
};
|
|
17825
|
-
const productRef = await addDoc7(
|
|
17826
|
-
this.getProductsRef(technologyId),
|
|
17827
|
-
newProduct
|
|
17828
|
-
);
|
|
17911
|
+
const productRef = await addDoc7(this.getProductsRef(technologyId), newProduct);
|
|
17829
17912
|
return { id: productRef.id, ...newProduct };
|
|
17830
17913
|
}
|
|
17831
17914
|
/**
|
|
@@ -17833,17 +17916,8 @@ var ProductService = class extends BaseService {
|
|
|
17833
17916
|
* This uses a collectionGroup query to search across all technologies.
|
|
17834
17917
|
*/
|
|
17835
17918
|
async getAll(options) {
|
|
17836
|
-
const {
|
|
17837
|
-
|
|
17838
|
-
lastVisible,
|
|
17839
|
-
categoryId,
|
|
17840
|
-
subcategoryId,
|
|
17841
|
-
technologyId
|
|
17842
|
-
} = options;
|
|
17843
|
-
const constraints = [
|
|
17844
|
-
where35("isActive", "==", true),
|
|
17845
|
-
orderBy22("name")
|
|
17846
|
-
];
|
|
17919
|
+
const { rowsPerPage, lastVisible, categoryId, subcategoryId, technologyId } = options;
|
|
17920
|
+
const constraints = [where35("isActive", "==", true), orderBy22("name")];
|
|
17847
17921
|
if (categoryId) {
|
|
17848
17922
|
constraints.push(where35("categoryId", "==", categoryId));
|
|
17849
17923
|
}
|
|
@@ -17857,10 +17931,7 @@ var ProductService = class extends BaseService {
|
|
|
17857
17931
|
constraints.push(startAfter18(lastVisible));
|
|
17858
17932
|
}
|
|
17859
17933
|
constraints.push(limit20(rowsPerPage));
|
|
17860
|
-
const q = query35(
|
|
17861
|
-
collectionGroup3(this.db, PRODUCTS_COLLECTION),
|
|
17862
|
-
...constraints
|
|
17863
|
-
);
|
|
17934
|
+
const q = query35(collectionGroup3(this.db, PRODUCTS_COLLECTION), ...constraints);
|
|
17864
17935
|
const snapshot = await getDocs35(q);
|
|
17865
17936
|
const products = snapshot.docs.map(
|
|
17866
17937
|
(doc38) => ({
|
|
@@ -17886,10 +17957,7 @@ var ProductService = class extends BaseService {
|
|
|
17886
17957
|
if (technologyId) {
|
|
17887
17958
|
constraints.push(where35("technologyId", "==", technologyId));
|
|
17888
17959
|
}
|
|
17889
|
-
const q = query35(
|
|
17890
|
-
collectionGroup3(this.db, PRODUCTS_COLLECTION),
|
|
17891
|
-
...constraints
|
|
17892
|
-
);
|
|
17960
|
+
const q = query35(collectionGroup3(this.db, PRODUCTS_COLLECTION), ...constraints);
|
|
17893
17961
|
const snapshot = await getCountFromServer6(q);
|
|
17894
17962
|
return snapshot.data().count;
|
|
17895
17963
|
}
|
|
@@ -17898,10 +17966,7 @@ var ProductService = class extends BaseService {
|
|
|
17898
17966
|
* This uses a single collectionGroup query for efficiency.
|
|
17899
17967
|
*/
|
|
17900
17968
|
async getProductCounts() {
|
|
17901
|
-
const q = query35(
|
|
17902
|
-
collectionGroup3(this.db, PRODUCTS_COLLECTION),
|
|
17903
|
-
where35("isActive", "==", true)
|
|
17904
|
-
);
|
|
17969
|
+
const q = query35(collectionGroup3(this.db, PRODUCTS_COLLECTION), where35("isActive", "==", true));
|
|
17905
17970
|
const snapshot = await getDocs35(q);
|
|
17906
17971
|
const counts = {
|
|
17907
17972
|
byCategory: {},
|
|
@@ -17926,6 +17991,23 @@ var ProductService = class extends BaseService {
|
|
|
17926
17991
|
});
|
|
17927
17992
|
return counts;
|
|
17928
17993
|
}
|
|
17994
|
+
/**
|
|
17995
|
+
* Gets all products for a specific technology (non-paginated, for filters/dropdowns)
|
|
17996
|
+
*/
|
|
17997
|
+
async getAllByTechnology(technologyId) {
|
|
17998
|
+
const q = query35(
|
|
17999
|
+
this.getProductsRef(technologyId),
|
|
18000
|
+
where35("isActive", "==", true),
|
|
18001
|
+
orderBy22("name")
|
|
18002
|
+
);
|
|
18003
|
+
const snapshot = await getDocs35(q);
|
|
18004
|
+
return snapshot.docs.map(
|
|
18005
|
+
(doc38) => ({
|
|
18006
|
+
id: doc38.id,
|
|
18007
|
+
...doc38.data()
|
|
18008
|
+
})
|
|
18009
|
+
);
|
|
18010
|
+
}
|
|
17929
18011
|
/**
|
|
17930
18012
|
* Gets all products for a brand by filtering through all technologies
|
|
17931
18013
|
*/
|
|
@@ -18280,6 +18362,7 @@ export {
|
|
|
18280
18362
|
AppointmentStatus,
|
|
18281
18363
|
AuthService,
|
|
18282
18364
|
BaseService,
|
|
18365
|
+
BillingTransactionType,
|
|
18283
18366
|
BlockingCondition,
|
|
18284
18367
|
BrandService,
|
|
18285
18368
|
CALENDAR_COLLECTION,
|
|
@@ -18363,6 +18446,7 @@ export {
|
|
|
18363
18446
|
SearchLocationEnum,
|
|
18364
18447
|
SubcategoryService,
|
|
18365
18448
|
SubscriptionModel,
|
|
18449
|
+
SubscriptionStatus,
|
|
18366
18450
|
SyncedCalendarProvider,
|
|
18367
18451
|
SyncedCalendarsService,
|
|
18368
18452
|
TechnologyService,
|
package/package.json
CHANGED