@blackcode_sa/metaestetics-api 1.12.17 → 1.12.19
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 +1 -1
- package/dist/admin/index.d.ts +1 -1
- package/dist/admin/index.js +27 -10
- package/dist/admin/index.mjs +27 -10
- package/dist/backoffice/index.js +2 -2
- package/dist/backoffice/index.mjs +2 -2
- package/dist/index.js +6 -3
- package/dist/index.mjs +6 -3
- package/package.json +1 -1
- package/src/admin/free-consultation/README.md +82 -0
- package/src/admin/free-consultation/free-consultation-utils.admin.ts +70 -54
- package/src/backoffice/services/technology.service.ts +2 -2
- package/src/services/user/user.service.ts +8 -1
package/dist/admin/index.d.mts
CHANGED
|
@@ -3388,7 +3388,7 @@ declare class DocumentManagerAdminService {
|
|
|
3388
3388
|
|
|
3389
3389
|
/**
|
|
3390
3390
|
* Ensures that the free consultation infrastructure exists in the database
|
|
3391
|
-
* Creates category, subcategory, and
|
|
3391
|
+
* Creates category, subcategory, technology, and product if they don't exist
|
|
3392
3392
|
* @param db - Firestore database instance (optional, defaults to admin.firestore())
|
|
3393
3393
|
* @returns Promise<boolean> - Always returns true after ensuring infrastructure exists
|
|
3394
3394
|
*/
|
package/dist/admin/index.d.ts
CHANGED
|
@@ -3388,7 +3388,7 @@ declare class DocumentManagerAdminService {
|
|
|
3388
3388
|
|
|
3389
3389
|
/**
|
|
3390
3390
|
* Ensures that the free consultation infrastructure exists in the database
|
|
3391
|
-
* Creates category, subcategory, and
|
|
3391
|
+
* Creates category, subcategory, technology, and product if they don't exist
|
|
3392
3392
|
* @param db - Firestore database instance (optional, defaults to admin.firestore())
|
|
3393
3393
|
* @returns Promise<boolean> - Always returns true after ensuring infrastructure exists
|
|
3394
3394
|
*/
|
package/dist/admin/index.js
CHANGED
|
@@ -7383,13 +7383,14 @@ var SUBCATEGORIES_COLLECTION = "subcategories";
|
|
|
7383
7383
|
// src/backoffice/types/technology.types.ts
|
|
7384
7384
|
var TECHNOLOGIES_COLLECTION = "technologies";
|
|
7385
7385
|
|
|
7386
|
+
// src/backoffice/types/product.types.ts
|
|
7387
|
+
var PRODUCTS_COLLECTION = "products";
|
|
7388
|
+
|
|
7386
7389
|
// src/admin/free-consultation/free-consultation-utils.admin.ts
|
|
7387
7390
|
async function freeConsultationInfrastructure(db) {
|
|
7388
7391
|
const firestore18 = db || admin16.firestore();
|
|
7389
7392
|
try {
|
|
7390
|
-
console.log(
|
|
7391
|
-
"[freeConsultationInfrastructure] Checking free consultation infrastructure..."
|
|
7392
|
-
);
|
|
7393
|
+
console.log("[freeConsultationInfrastructure] Checking free consultation infrastructure...");
|
|
7393
7394
|
const technologyRef = firestore18.collection(TECHNOLOGIES_COLLECTION).doc("free-consultation-tech");
|
|
7394
7395
|
const technologyDoc = await technologyRef.get();
|
|
7395
7396
|
if (technologyDoc.exists) {
|
|
@@ -7398,19 +7399,14 @@ async function freeConsultationInfrastructure(db) {
|
|
|
7398
7399
|
);
|
|
7399
7400
|
return true;
|
|
7400
7401
|
}
|
|
7401
|
-
console.log(
|
|
7402
|
-
"[freeConsultationInfrastructure] Creating free consultation infrastructure..."
|
|
7403
|
-
);
|
|
7402
|
+
console.log("[freeConsultationInfrastructure] Creating free consultation infrastructure...");
|
|
7404
7403
|
await createFreeConsultationInfrastructure(firestore18);
|
|
7405
7404
|
console.log(
|
|
7406
7405
|
"[freeConsultationInfrastructure] Successfully created free consultation infrastructure"
|
|
7407
7406
|
);
|
|
7408
7407
|
return true;
|
|
7409
7408
|
} catch (error) {
|
|
7410
|
-
console.error(
|
|
7411
|
-
"[freeConsultationInfrastructure] Error ensuring infrastructure:",
|
|
7412
|
-
error
|
|
7413
|
-
);
|
|
7409
|
+
console.error("[freeConsultationInfrastructure] Error ensuring infrastructure:", error);
|
|
7414
7410
|
throw error;
|
|
7415
7411
|
}
|
|
7416
7412
|
}
|
|
@@ -7474,11 +7470,32 @@ async function createFreeConsultationInfrastructure(db) {
|
|
|
7474
7470
|
updatedAt: now
|
|
7475
7471
|
};
|
|
7476
7472
|
batch.set(technologyRef, technologyData);
|
|
7473
|
+
const productRef = db.collection(TECHNOLOGIES_COLLECTION).doc("free-consultation-tech").collection(PRODUCTS_COLLECTION).doc("free-consultation-product");
|
|
7474
|
+
const productData = {
|
|
7475
|
+
id: "free-consultation-product",
|
|
7476
|
+
name: "Free Consultation Service",
|
|
7477
|
+
description: "No physical product required for consultation services",
|
|
7478
|
+
brandId: "consultation-brand",
|
|
7479
|
+
brandName: "Consultation Services",
|
|
7480
|
+
technologyId: "free-consultation-tech",
|
|
7481
|
+
technologyName: "Free Consultation Technology",
|
|
7482
|
+
categoryId: "consultation",
|
|
7483
|
+
subcategoryId: "free-consultation",
|
|
7484
|
+
isActive: true,
|
|
7485
|
+
createdAt: now,
|
|
7486
|
+
updatedAt: now,
|
|
7487
|
+
technicalDetails: "Virtual consultation service - no physical product required",
|
|
7488
|
+
warnings: [],
|
|
7489
|
+
indications: ["Initial patient assessment", "Treatment planning", "Patient education"],
|
|
7490
|
+
contraindications: []
|
|
7491
|
+
};
|
|
7492
|
+
batch.set(productRef, productData);
|
|
7477
7493
|
await batch.commit();
|
|
7478
7494
|
console.log("[freeConsultationInfrastructure] Successfully created:");
|
|
7479
7495
|
console.log(" \u2713 Category: consultation");
|
|
7480
7496
|
console.log(" \u2713 Subcategory: free-consultation");
|
|
7481
7497
|
console.log(" \u2713 Technology: free-consultation-tech");
|
|
7498
|
+
console.log(" \u2713 Product: free-consultation-product");
|
|
7482
7499
|
}
|
|
7483
7500
|
|
|
7484
7501
|
// src/admin/mailing/practitionerInvite/templates/invitation.template.ts
|
package/dist/admin/index.mjs
CHANGED
|
@@ -7321,13 +7321,14 @@ var SUBCATEGORIES_COLLECTION = "subcategories";
|
|
|
7321
7321
|
// src/backoffice/types/technology.types.ts
|
|
7322
7322
|
var TECHNOLOGIES_COLLECTION = "technologies";
|
|
7323
7323
|
|
|
7324
|
+
// src/backoffice/types/product.types.ts
|
|
7325
|
+
var PRODUCTS_COLLECTION = "products";
|
|
7326
|
+
|
|
7324
7327
|
// src/admin/free-consultation/free-consultation-utils.admin.ts
|
|
7325
7328
|
async function freeConsultationInfrastructure(db) {
|
|
7326
7329
|
const firestore18 = db || admin16.firestore();
|
|
7327
7330
|
try {
|
|
7328
|
-
console.log(
|
|
7329
|
-
"[freeConsultationInfrastructure] Checking free consultation infrastructure..."
|
|
7330
|
-
);
|
|
7331
|
+
console.log("[freeConsultationInfrastructure] Checking free consultation infrastructure...");
|
|
7331
7332
|
const technologyRef = firestore18.collection(TECHNOLOGIES_COLLECTION).doc("free-consultation-tech");
|
|
7332
7333
|
const technologyDoc = await technologyRef.get();
|
|
7333
7334
|
if (technologyDoc.exists) {
|
|
@@ -7336,19 +7337,14 @@ async function freeConsultationInfrastructure(db) {
|
|
|
7336
7337
|
);
|
|
7337
7338
|
return true;
|
|
7338
7339
|
}
|
|
7339
|
-
console.log(
|
|
7340
|
-
"[freeConsultationInfrastructure] Creating free consultation infrastructure..."
|
|
7341
|
-
);
|
|
7340
|
+
console.log("[freeConsultationInfrastructure] Creating free consultation infrastructure...");
|
|
7342
7341
|
await createFreeConsultationInfrastructure(firestore18);
|
|
7343
7342
|
console.log(
|
|
7344
7343
|
"[freeConsultationInfrastructure] Successfully created free consultation infrastructure"
|
|
7345
7344
|
);
|
|
7346
7345
|
return true;
|
|
7347
7346
|
} catch (error) {
|
|
7348
|
-
console.error(
|
|
7349
|
-
"[freeConsultationInfrastructure] Error ensuring infrastructure:",
|
|
7350
|
-
error
|
|
7351
|
-
);
|
|
7347
|
+
console.error("[freeConsultationInfrastructure] Error ensuring infrastructure:", error);
|
|
7352
7348
|
throw error;
|
|
7353
7349
|
}
|
|
7354
7350
|
}
|
|
@@ -7412,11 +7408,32 @@ async function createFreeConsultationInfrastructure(db) {
|
|
|
7412
7408
|
updatedAt: now
|
|
7413
7409
|
};
|
|
7414
7410
|
batch.set(technologyRef, technologyData);
|
|
7411
|
+
const productRef = db.collection(TECHNOLOGIES_COLLECTION).doc("free-consultation-tech").collection(PRODUCTS_COLLECTION).doc("free-consultation-product");
|
|
7412
|
+
const productData = {
|
|
7413
|
+
id: "free-consultation-product",
|
|
7414
|
+
name: "Free Consultation Service",
|
|
7415
|
+
description: "No physical product required for consultation services",
|
|
7416
|
+
brandId: "consultation-brand",
|
|
7417
|
+
brandName: "Consultation Services",
|
|
7418
|
+
technologyId: "free-consultation-tech",
|
|
7419
|
+
technologyName: "Free Consultation Technology",
|
|
7420
|
+
categoryId: "consultation",
|
|
7421
|
+
subcategoryId: "free-consultation",
|
|
7422
|
+
isActive: true,
|
|
7423
|
+
createdAt: now,
|
|
7424
|
+
updatedAt: now,
|
|
7425
|
+
technicalDetails: "Virtual consultation service - no physical product required",
|
|
7426
|
+
warnings: [],
|
|
7427
|
+
indications: ["Initial patient assessment", "Treatment planning", "Patient education"],
|
|
7428
|
+
contraindications: []
|
|
7429
|
+
};
|
|
7430
|
+
batch.set(productRef, productData);
|
|
7415
7431
|
await batch.commit();
|
|
7416
7432
|
console.log("[freeConsultationInfrastructure] Successfully created:");
|
|
7417
7433
|
console.log(" \u2713 Category: consultation");
|
|
7418
7434
|
console.log(" \u2713 Subcategory: free-consultation");
|
|
7419
7435
|
console.log(" \u2713 Technology: free-consultation-tech");
|
|
7436
|
+
console.log(" \u2713 Product: free-consultation-product");
|
|
7420
7437
|
}
|
|
7421
7438
|
|
|
7422
7439
|
// src/admin/mailing/practitionerInvite/templates/invitation.template.ts
|
package/dist/backoffice/index.js
CHANGED
|
@@ -2276,8 +2276,8 @@ var TechnologyService = class extends BaseService {
|
|
|
2276
2276
|
* console.log(allowedTechnologies.subcategories); // ["subcategory1", "subcategory2"]
|
|
2277
2277
|
*/
|
|
2278
2278
|
async getAllowedTechnologies(practitioner) {
|
|
2279
|
-
const allTechnologies = await this.
|
|
2280
|
-
const allowedTechnologies = allTechnologies.
|
|
2279
|
+
const allTechnologies = await this.getAllForFilter();
|
|
2280
|
+
const allowedTechnologies = allTechnologies.filter(
|
|
2281
2281
|
(technology) => this.validateCertification(technology.certificationRequirement, practitioner.certification)
|
|
2282
2282
|
);
|
|
2283
2283
|
const families = [...new Set(allowedTechnologies.map((t) => t.family))];
|
|
@@ -2292,8 +2292,8 @@ var TechnologyService = class extends BaseService {
|
|
|
2292
2292
|
* console.log(allowedTechnologies.subcategories); // ["subcategory1", "subcategory2"]
|
|
2293
2293
|
*/
|
|
2294
2294
|
async getAllowedTechnologies(practitioner) {
|
|
2295
|
-
const allTechnologies = await this.
|
|
2296
|
-
const allowedTechnologies = allTechnologies.
|
|
2295
|
+
const allTechnologies = await this.getAllForFilter();
|
|
2296
|
+
const allowedTechnologies = allTechnologies.filter(
|
|
2297
2297
|
(technology) => this.validateCertification(technology.certificationRequirement, practitioner.certification)
|
|
2298
2298
|
);
|
|
2299
2299
|
const families = [...new Set(allowedTechnologies.map((t) => t.family))];
|
package/dist/index.js
CHANGED
|
@@ -7406,9 +7406,12 @@ var UserService = class extends BaseService {
|
|
|
7406
7406
|
if ((await this.getUserById(userId)).patientProfile || patientProfile2.userRef) {
|
|
7407
7407
|
throw new Error("User already has a patient profile.");
|
|
7408
7408
|
}
|
|
7409
|
+
const sensitiveInfo = await patientService.getSensitiveInfo(patientProfile2.id, userId);
|
|
7410
|
+
const fullDisplayName = sensitiveInfo ? `${sensitiveInfo.firstName} ${sensitiveInfo.lastName}` : patientProfile2.displayName;
|
|
7409
7411
|
await patientService.updatePatientProfile(patientProfile2.id, {
|
|
7410
7412
|
userRef: userId,
|
|
7411
|
-
isManual: false
|
|
7413
|
+
isManual: false,
|
|
7414
|
+
displayName: fullDisplayName
|
|
7412
7415
|
});
|
|
7413
7416
|
await patientService.markPatientTokenAsUsed(token.id, token.patientId, userId);
|
|
7414
7417
|
profiles.patientProfile = patientProfile2.id;
|
|
@@ -17298,8 +17301,8 @@ var TechnologyService = class extends BaseService {
|
|
|
17298
17301
|
* console.log(allowedTechnologies.subcategories); // ["subcategory1", "subcategory2"]
|
|
17299
17302
|
*/
|
|
17300
17303
|
async getAllowedTechnologies(practitioner) {
|
|
17301
|
-
const allTechnologies = await this.
|
|
17302
|
-
const allowedTechnologies = allTechnologies.
|
|
17304
|
+
const allTechnologies = await this.getAllForFilter();
|
|
17305
|
+
const allowedTechnologies = allTechnologies.filter(
|
|
17303
17306
|
(technology) => this.validateCertification(technology.certificationRequirement, practitioner.certification)
|
|
17304
17307
|
);
|
|
17305
17308
|
const families = [...new Set(allowedTechnologies.map((t) => t.family))];
|
package/dist/index.mjs
CHANGED
|
@@ -7447,9 +7447,12 @@ var UserService = class extends BaseService {
|
|
|
7447
7447
|
if ((await this.getUserById(userId)).patientProfile || patientProfile2.userRef) {
|
|
7448
7448
|
throw new Error("User already has a patient profile.");
|
|
7449
7449
|
}
|
|
7450
|
+
const sensitiveInfo = await patientService.getSensitiveInfo(patientProfile2.id, userId);
|
|
7451
|
+
const fullDisplayName = sensitiveInfo ? `${sensitiveInfo.firstName} ${sensitiveInfo.lastName}` : patientProfile2.displayName;
|
|
7450
7452
|
await patientService.updatePatientProfile(patientProfile2.id, {
|
|
7451
7453
|
userRef: userId,
|
|
7452
|
-
isManual: false
|
|
7454
|
+
isManual: false,
|
|
7455
|
+
displayName: fullDisplayName
|
|
7453
7456
|
});
|
|
7454
7457
|
await patientService.markPatientTokenAsUsed(token.id, token.patientId, userId);
|
|
7455
7458
|
profiles.patientProfile = patientProfile2.id;
|
|
@@ -17618,8 +17621,8 @@ var TechnologyService = class extends BaseService {
|
|
|
17618
17621
|
* console.log(allowedTechnologies.subcategories); // ["subcategory1", "subcategory2"]
|
|
17619
17622
|
*/
|
|
17620
17623
|
async getAllowedTechnologies(practitioner) {
|
|
17621
|
-
const allTechnologies = await this.
|
|
17622
|
-
const allowedTechnologies = allTechnologies.
|
|
17624
|
+
const allTechnologies = await this.getAllForFilter();
|
|
17625
|
+
const allowedTechnologies = allTechnologies.filter(
|
|
17623
17626
|
(technology) => this.validateCertification(technology.certificationRequirement, practitioner.certification)
|
|
17624
17627
|
);
|
|
17625
17628
|
const families = [...new Set(allowedTechnologies.map((t) => t.family))];
|
package/package.json
CHANGED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Free Consultation Infrastructure
|
|
2
|
+
|
|
3
|
+
This module manages the infrastructure required for free consultation procedures in the MetaEstetics system.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The free consultation feature allows practitioners to offer complimentary initial consultations to patients. This requires specific infrastructure components to be present in the database.
|
|
8
|
+
|
|
9
|
+
## Infrastructure Components
|
|
10
|
+
|
|
11
|
+
The system creates the following components when `freeConsultationInfrastructure()` is called:
|
|
12
|
+
|
|
13
|
+
### 1. Category: "consultation"
|
|
14
|
+
- **ID**: `consultation`
|
|
15
|
+
- **Name**: Consultation
|
|
16
|
+
- **Description**: Professional consultation services for treatment planning and assessment
|
|
17
|
+
- **Family**: AESTHETICS
|
|
18
|
+
|
|
19
|
+
### 2. Subcategory: "free-consultation"
|
|
20
|
+
- **ID**: `free-consultation`
|
|
21
|
+
- **Name**: Free Consultation
|
|
22
|
+
- **Description**: Complimentary initial consultation to discuss treatment options and assess patient needs
|
|
23
|
+
- **Parent Category**: consultation
|
|
24
|
+
|
|
25
|
+
### 3. Technology: "free-consultation-tech"
|
|
26
|
+
- **ID**: `free-consultation-tech`
|
|
27
|
+
- **Name**: Free Consultation Technology
|
|
28
|
+
- **Description**: Technology framework for providing free initial consultations to patients
|
|
29
|
+
- **Requirements**: No pre/post requirements
|
|
30
|
+
- **Certification**: Minimum level AESTHETICIAN
|
|
31
|
+
|
|
32
|
+
### 4. Product: "free-consultation-product"
|
|
33
|
+
- **ID**: `free-consultation-product`
|
|
34
|
+
- **Name**: Free Consultation Service
|
|
35
|
+
- **Description**: No physical product required for consultation services
|
|
36
|
+
- **Brand**: Consultation Services
|
|
37
|
+
- **Type**: Virtual service
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
### Ensuring Infrastructure Exists
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
import { freeConsultationInfrastructure } from './free-consultation-utils.admin';
|
|
45
|
+
|
|
46
|
+
// Ensure infrastructure exists before creating consultation procedures
|
|
47
|
+
const infrastructureExists = await freeConsultationInfrastructure();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Creating Free Consultation Procedures
|
|
51
|
+
|
|
52
|
+
The infrastructure is automatically checked and created when practitioners enable free consultations through the `PractitionerService.EnableFreeConsultation()` method.
|
|
53
|
+
|
|
54
|
+
## Error Handling
|
|
55
|
+
|
|
56
|
+
If you encounter the error:
|
|
57
|
+
```
|
|
58
|
+
Product with ID free-consultation-product not found for technology free-consultation-tech
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This indicates that the infrastructure was not properly created. The system will automatically attempt to create the missing infrastructure when the error occurs.
|
|
62
|
+
|
|
63
|
+
## Database Structure
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
categories/
|
|
67
|
+
consultation/
|
|
68
|
+
subcategories/
|
|
69
|
+
free-consultation/
|
|
70
|
+
|
|
71
|
+
technologies/
|
|
72
|
+
free-consultation-tech/
|
|
73
|
+
products/
|
|
74
|
+
free-consultation-product/
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Notes
|
|
78
|
+
|
|
79
|
+
- The infrastructure is created atomically using Firestore batch operations
|
|
80
|
+
- All components are created with `isActive: true`
|
|
81
|
+
- The system checks for existing infrastructure before attempting to create new components
|
|
82
|
+
- No physical products are required for consultation procedures
|
|
@@ -1,80 +1,72 @@
|
|
|
1
|
-
import * as admin from
|
|
2
|
-
import { ProcedureFamily } from
|
|
1
|
+
import * as admin from 'firebase-admin';
|
|
2
|
+
import { ProcedureFamily } from '../../backoffice/types/static/procedure-family.types';
|
|
3
3
|
import {
|
|
4
4
|
CertificationLevel,
|
|
5
5
|
CertificationSpecialty,
|
|
6
|
-
} from
|
|
7
|
-
import { CATEGORIES_COLLECTION } from
|
|
8
|
-
import { SUBCATEGORIES_COLLECTION } from
|
|
9
|
-
import { TECHNOLOGIES_COLLECTION } from
|
|
6
|
+
} from '../../backoffice/types/static/certification.types';
|
|
7
|
+
import { CATEGORIES_COLLECTION } from '../../backoffice/types/category.types';
|
|
8
|
+
import { SUBCATEGORIES_COLLECTION } from '../../backoffice/types/subcategory.types';
|
|
9
|
+
import { TECHNOLOGIES_COLLECTION } from '../../backoffice/types/technology.types';
|
|
10
|
+
import { PRODUCTS_COLLECTION } from '../../backoffice/types/product.types';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Ensures that the free consultation infrastructure exists in the database
|
|
13
|
-
* Creates category, subcategory, and
|
|
14
|
+
* Creates category, subcategory, technology, and product if they don't exist
|
|
14
15
|
* @param db - Firestore database instance (optional, defaults to admin.firestore())
|
|
15
16
|
* @returns Promise<boolean> - Always returns true after ensuring infrastructure exists
|
|
16
17
|
*/
|
|
17
18
|
export async function freeConsultationInfrastructure(
|
|
18
|
-
db?: admin.firestore.Firestore
|
|
19
|
+
db?: admin.firestore.Firestore,
|
|
19
20
|
): Promise<boolean> {
|
|
20
21
|
const firestore = db || admin.firestore();
|
|
21
22
|
|
|
22
23
|
try {
|
|
23
|
-
console.log(
|
|
24
|
-
"[freeConsultationInfrastructure] Checking free consultation infrastructure..."
|
|
25
|
-
);
|
|
24
|
+
console.log('[freeConsultationInfrastructure] Checking free consultation infrastructure...');
|
|
26
25
|
|
|
27
26
|
// Check if the technology already exists
|
|
28
27
|
const technologyRef = firestore
|
|
29
28
|
.collection(TECHNOLOGIES_COLLECTION)
|
|
30
|
-
.doc(
|
|
29
|
+
.doc('free-consultation-tech');
|
|
31
30
|
|
|
32
31
|
const technologyDoc = await technologyRef.get();
|
|
33
32
|
|
|
34
33
|
if (technologyDoc.exists) {
|
|
35
34
|
console.log(
|
|
36
|
-
|
|
35
|
+
'[freeConsultationInfrastructure] Free consultation infrastructure already exists',
|
|
37
36
|
);
|
|
38
37
|
return true;
|
|
39
38
|
}
|
|
40
39
|
|
|
41
|
-
console.log(
|
|
42
|
-
"[freeConsultationInfrastructure] Creating free consultation infrastructure..."
|
|
43
|
-
);
|
|
40
|
+
console.log('[freeConsultationInfrastructure] Creating free consultation infrastructure...');
|
|
44
41
|
|
|
45
|
-
// Create the infrastructure in the correct order: Category → Subcategory → Technology
|
|
42
|
+
// Create the infrastructure in the correct order: Category → Subcategory → Technology → Product
|
|
46
43
|
await createFreeConsultationInfrastructure(firestore);
|
|
47
44
|
|
|
48
45
|
console.log(
|
|
49
|
-
|
|
46
|
+
'[freeConsultationInfrastructure] Successfully created free consultation infrastructure',
|
|
50
47
|
);
|
|
51
48
|
return true;
|
|
52
49
|
} catch (error) {
|
|
53
|
-
console.error(
|
|
54
|
-
"[freeConsultationInfrastructure] Error ensuring infrastructure:",
|
|
55
|
-
error
|
|
56
|
-
);
|
|
50
|
+
console.error('[freeConsultationInfrastructure] Error ensuring infrastructure:', error);
|
|
57
51
|
throw error;
|
|
58
52
|
}
|
|
59
53
|
}
|
|
60
54
|
|
|
61
55
|
/**
|
|
62
56
|
* Creates the complete free consultation infrastructure
|
|
57
|
+
* Creates category, subcategory, technology, and product in the correct order
|
|
63
58
|
* @param db - Firestore database instance
|
|
64
59
|
*/
|
|
65
|
-
async function createFreeConsultationInfrastructure(
|
|
66
|
-
db: admin.firestore.Firestore
|
|
67
|
-
): Promise<void> {
|
|
60
|
+
async function createFreeConsultationInfrastructure(db: admin.firestore.Firestore): Promise<void> {
|
|
68
61
|
const batch = db.batch();
|
|
69
62
|
const now = new Date();
|
|
70
63
|
|
|
71
64
|
// 1. Create Category: "consultation"
|
|
72
|
-
const categoryRef = db.collection(CATEGORIES_COLLECTION).doc(
|
|
65
|
+
const categoryRef = db.collection(CATEGORIES_COLLECTION).doc('consultation');
|
|
73
66
|
const categoryData = {
|
|
74
|
-
id:
|
|
75
|
-
name:
|
|
76
|
-
description:
|
|
77
|
-
"Professional consultation services for treatment planning and assessment",
|
|
67
|
+
id: 'consultation',
|
|
68
|
+
name: 'Consultation',
|
|
69
|
+
description: 'Professional consultation services for treatment planning and assessment',
|
|
78
70
|
family: ProcedureFamily.AESTHETICS,
|
|
79
71
|
isActive: true,
|
|
80
72
|
createdAt: now,
|
|
@@ -85,16 +77,16 @@ async function createFreeConsultationInfrastructure(
|
|
|
85
77
|
// 2. Create Subcategory: "free-consultation"
|
|
86
78
|
const subcategoryRef = db
|
|
87
79
|
.collection(CATEGORIES_COLLECTION)
|
|
88
|
-
.doc(
|
|
80
|
+
.doc('consultation')
|
|
89
81
|
.collection(SUBCATEGORIES_COLLECTION)
|
|
90
|
-
.doc(
|
|
82
|
+
.doc('free-consultation');
|
|
91
83
|
|
|
92
84
|
const subcategoryData = {
|
|
93
|
-
id:
|
|
94
|
-
name:
|
|
85
|
+
id: 'free-consultation',
|
|
86
|
+
name: 'Free Consultation',
|
|
95
87
|
description:
|
|
96
|
-
|
|
97
|
-
categoryId:
|
|
88
|
+
'Complimentary initial consultation to discuss treatment options and assess patient needs',
|
|
89
|
+
categoryId: 'consultation',
|
|
98
90
|
isActive: true,
|
|
99
91
|
createdAt: now,
|
|
100
92
|
updatedAt: now,
|
|
@@ -102,19 +94,15 @@ async function createFreeConsultationInfrastructure(
|
|
|
102
94
|
batch.set(subcategoryRef, subcategoryData);
|
|
103
95
|
|
|
104
96
|
// 3. Create Technology: "free-consultation-tech"
|
|
105
|
-
const technologyRef = db
|
|
106
|
-
.collection(TECHNOLOGIES_COLLECTION)
|
|
107
|
-
.doc("free-consultation-tech");
|
|
97
|
+
const technologyRef = db.collection(TECHNOLOGIES_COLLECTION).doc('free-consultation-tech');
|
|
108
98
|
const technologyData = {
|
|
109
|
-
id:
|
|
110
|
-
name:
|
|
111
|
-
description:
|
|
112
|
-
"Technology framework for providing free initial consultations to patients",
|
|
99
|
+
id: 'free-consultation-tech',
|
|
100
|
+
name: 'Free Consultation Technology',
|
|
101
|
+
description: 'Technology framework for providing free initial consultations to patients',
|
|
113
102
|
family: ProcedureFamily.AESTHETICS,
|
|
114
|
-
categoryId:
|
|
115
|
-
subcategoryId:
|
|
116
|
-
technicalDetails:
|
|
117
|
-
"Standard consultation protocol for initial patient assessment",
|
|
103
|
+
categoryId: 'consultation',
|
|
104
|
+
subcategoryId: 'free-consultation',
|
|
105
|
+
technicalDetails: 'Standard consultation protocol for initial patient assessment',
|
|
118
106
|
requirements: {
|
|
119
107
|
pre: [], // No pre-requirements for consultation
|
|
120
108
|
post: [], // No post-requirements for consultation
|
|
@@ -122,9 +110,9 @@ async function createFreeConsultationInfrastructure(
|
|
|
122
110
|
blockingConditions: [], // No blocking conditions for consultation
|
|
123
111
|
contraindications: [], // No contraindications for consultation
|
|
124
112
|
benefits: [
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
113
|
+
'IMPROVED_PATIENT_UNDERSTANDING',
|
|
114
|
+
'BETTER_TREATMENT_PLANNING',
|
|
115
|
+
'ENHANCED_PATIENT_CONFIDENCE',
|
|
128
116
|
],
|
|
129
117
|
certificationRequirement: {
|
|
130
118
|
minimumLevel: CertificationLevel.AESTHETICIAN,
|
|
@@ -137,11 +125,39 @@ async function createFreeConsultationInfrastructure(
|
|
|
137
125
|
};
|
|
138
126
|
batch.set(technologyRef, technologyData);
|
|
139
127
|
|
|
128
|
+
// 4. Create Product: "free-consultation-product"
|
|
129
|
+
const productRef = db
|
|
130
|
+
.collection(TECHNOLOGIES_COLLECTION)
|
|
131
|
+
.doc('free-consultation-tech')
|
|
132
|
+
.collection(PRODUCTS_COLLECTION)
|
|
133
|
+
.doc('free-consultation-product');
|
|
134
|
+
|
|
135
|
+
const productData = {
|
|
136
|
+
id: 'free-consultation-product',
|
|
137
|
+
name: 'Free Consultation Service',
|
|
138
|
+
description: 'No physical product required for consultation services',
|
|
139
|
+
brandId: 'consultation-brand',
|
|
140
|
+
brandName: 'Consultation Services',
|
|
141
|
+
technologyId: 'free-consultation-tech',
|
|
142
|
+
technologyName: 'Free Consultation Technology',
|
|
143
|
+
categoryId: 'consultation',
|
|
144
|
+
subcategoryId: 'free-consultation',
|
|
145
|
+
isActive: true,
|
|
146
|
+
createdAt: now,
|
|
147
|
+
updatedAt: now,
|
|
148
|
+
technicalDetails: 'Virtual consultation service - no physical product required',
|
|
149
|
+
warnings: [],
|
|
150
|
+
indications: ['Initial patient assessment', 'Treatment planning', 'Patient education'],
|
|
151
|
+
contraindications: [],
|
|
152
|
+
};
|
|
153
|
+
batch.set(productRef, productData);
|
|
154
|
+
|
|
140
155
|
// Commit all changes atomically
|
|
141
156
|
await batch.commit();
|
|
142
157
|
|
|
143
|
-
console.log(
|
|
144
|
-
console.log(
|
|
145
|
-
console.log(
|
|
146
|
-
console.log(
|
|
158
|
+
console.log('[freeConsultationInfrastructure] Successfully created:');
|
|
159
|
+
console.log(' ✓ Category: consultation');
|
|
160
|
+
console.log(' ✓ Subcategory: free-consultation');
|
|
161
|
+
console.log(' ✓ Technology: free-consultation-tech');
|
|
162
|
+
console.log(' ✓ Product: free-consultation-product');
|
|
147
163
|
}
|
|
@@ -693,10 +693,10 @@ export class TechnologyService extends BaseService implements ITechnologyService
|
|
|
693
693
|
subcategories: string[];
|
|
694
694
|
}> {
|
|
695
695
|
// Get all active technologies
|
|
696
|
-
const allTechnologies = await this.
|
|
696
|
+
const allTechnologies = await this.getAllForFilter();
|
|
697
697
|
|
|
698
698
|
// Filter technologies based on certification requirements
|
|
699
|
-
const allowedTechnologies = allTechnologies.
|
|
699
|
+
const allowedTechnologies = allTechnologies.filter(technology =>
|
|
700
700
|
this.validateCertification(technology.certificationRequirement, practitioner.certification),
|
|
701
701
|
);
|
|
702
702
|
|
|
@@ -178,10 +178,17 @@ export class UserService extends BaseService {
|
|
|
178
178
|
throw new Error('User already has a patient profile.');
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
// Claim the profile: link userRef
|
|
181
|
+
// Claim the profile: link userRef, set isManual to false, and update displayName
|
|
182
|
+
// Get sensitive info to construct full display name
|
|
183
|
+
const sensitiveInfo = await patientService.getSensitiveInfo(patientProfile.id, userId);
|
|
184
|
+
const fullDisplayName = sensitiveInfo
|
|
185
|
+
? `${sensitiveInfo.firstName} ${sensitiveInfo.lastName}`
|
|
186
|
+
: patientProfile.displayName;
|
|
187
|
+
|
|
182
188
|
await patientService.updatePatientProfile(patientProfile.id, {
|
|
183
189
|
userRef: userId,
|
|
184
190
|
isManual: false,
|
|
191
|
+
displayName: fullDisplayName,
|
|
185
192
|
});
|
|
186
193
|
|
|
187
194
|
// Mark the token as used
|