@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.
- package/dist/admin/index.d.mts +126 -1
- package/dist/admin/index.d.ts +126 -1
- package/dist/admin/index.js +347 -10
- package/dist/admin/index.mjs +345 -10
- package/dist/index.d.mts +64 -71
- package/dist/index.d.ts +64 -71
- package/dist/index.js +327 -710
- package/dist/index.mjs +363 -750
- package/package.json +2 -1
- package/src/admin/aggregation/README.md +79 -0
- package/src/admin/aggregation/clinic/README.md +52 -0
- package/src/admin/aggregation/patient/README.md +27 -0
- package/src/admin/aggregation/practitioner/README.md +42 -0
- package/src/admin/aggregation/procedure/README.md +43 -0
- package/src/admin/index.ts +17 -2
- package/src/admin/mailing/README.md +95 -0
- package/src/admin/mailing/base.mailing.service.ts +131 -0
- package/src/admin/mailing/index.ts +2 -0
- package/src/admin/mailing/practitionerInvite/index.ts +1 -0
- package/src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts +256 -0
- package/src/admin/mailing/practitionerInvite/templates/invitation.template.ts +101 -0
- package/src/services/README.md +106 -0
- package/src/services/calendar/utils/appointment.utils.ts +42 -91
- package/src/services/clinic/README.md +87 -0
- package/src/services/clinic/clinic.service.ts +3 -126
- package/src/services/clinic/utils/clinic.utils.ts +2 -2
- package/src/services/practitioner/README.md +145 -0
- package/src/services/practitioner/practitioner.service.ts +119 -395
- package/src/services/procedure/README.md +88 -0
- package/src/services/procedure/procedure.service.ts +332 -369
package/dist/admin/index.mjs
CHANGED
|
@@ -20,9 +20,9 @@ var NotificationStatus = /* @__PURE__ */ ((NotificationStatus2) => {
|
|
|
20
20
|
import * as admin from "firebase-admin";
|
|
21
21
|
import { Expo } from "expo-server-sdk";
|
|
22
22
|
var NotificationsAdmin = class {
|
|
23
|
-
constructor(
|
|
23
|
+
constructor(firestore7) {
|
|
24
24
|
this.expo = new Expo();
|
|
25
|
-
this.db =
|
|
25
|
+
this.db = firestore7 || admin.firestore();
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* Dohvata notifikaciju po ID-u
|
|
@@ -209,8 +209,8 @@ var ClinicAggregationService = class {
|
|
|
209
209
|
* Constructor for ClinicAggregationService.
|
|
210
210
|
* @param firestore Optional Firestore instance. If not provided, it uses the default admin SDK instance.
|
|
211
211
|
*/
|
|
212
|
-
constructor(
|
|
213
|
-
this.db =
|
|
212
|
+
constructor(firestore7) {
|
|
213
|
+
this.db = firestore7 || admin2.firestore();
|
|
214
214
|
}
|
|
215
215
|
/**
|
|
216
216
|
* Adds clinic information to a clinic group when a new clinic is created
|
|
@@ -684,8 +684,8 @@ var ClinicAggregationService = class {
|
|
|
684
684
|
import * as admin3 from "firebase-admin";
|
|
685
685
|
var CALENDAR_SUBCOLLECTION_ID2 = "calendar";
|
|
686
686
|
var PractitionerAggregationService = class {
|
|
687
|
-
constructor(
|
|
688
|
-
this.db =
|
|
687
|
+
constructor(firestore7) {
|
|
688
|
+
this.db = firestore7 || admin3.firestore();
|
|
689
689
|
}
|
|
690
690
|
/**
|
|
691
691
|
* Adds practitioner information to a clinic when a new practitioner is created
|
|
@@ -1020,8 +1020,8 @@ var PractitionerAggregationService = class {
|
|
|
1020
1020
|
import * as admin4 from "firebase-admin";
|
|
1021
1021
|
var CALENDAR_SUBCOLLECTION_ID3 = "calendar";
|
|
1022
1022
|
var ProcedureAggregationService = class {
|
|
1023
|
-
constructor(
|
|
1024
|
-
this.db =
|
|
1023
|
+
constructor(firestore7) {
|
|
1024
|
+
this.db = firestore7 || admin4.firestore();
|
|
1025
1025
|
}
|
|
1026
1026
|
/**
|
|
1027
1027
|
* Adds procedure information to a practitioner when a new procedure is created
|
|
@@ -1405,8 +1405,8 @@ var ProcedureAggregationService = class {
|
|
|
1405
1405
|
import * as admin5 from "firebase-admin";
|
|
1406
1406
|
var CALENDAR_SUBCOLLECTION_ID4 = "calendar";
|
|
1407
1407
|
var PatientAggregationService = class {
|
|
1408
|
-
constructor(
|
|
1409
|
-
this.db =
|
|
1408
|
+
constructor(firestore7) {
|
|
1409
|
+
this.db = firestore7 || admin5.firestore();
|
|
1410
1410
|
}
|
|
1411
1411
|
// --- Methods for Patient Creation --- >
|
|
1412
1412
|
// No specific aggregations defined for patient creation in the plan.
|
|
@@ -1510,6 +1510,339 @@ var PatientAggregationService = class {
|
|
|
1510
1510
|
}
|
|
1511
1511
|
};
|
|
1512
1512
|
|
|
1513
|
+
// src/admin/mailing/base.mailing.service.ts
|
|
1514
|
+
import * as admin6 from "firebase-admin";
|
|
1515
|
+
var BaseMailingService = class {
|
|
1516
|
+
// Removed config property as it's no longer managed here
|
|
1517
|
+
// protected config: MailgunConfig;
|
|
1518
|
+
/**
|
|
1519
|
+
* Constructor for BaseMailingService
|
|
1520
|
+
* @param firestore Firestore instance provided by the caller
|
|
1521
|
+
* @param mailgunClient Mailgun client instance provided by the caller
|
|
1522
|
+
*/
|
|
1523
|
+
constructor(firestore7, mailgunClient) {
|
|
1524
|
+
this.db = firestore7;
|
|
1525
|
+
this.mailgunClient = mailgunClient;
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* Sends an email using Mailgun
|
|
1529
|
+
* @param data Email data to send, including the 'from' address
|
|
1530
|
+
* @returns Promise with the sending result
|
|
1531
|
+
*/
|
|
1532
|
+
async sendEmail(data) {
|
|
1533
|
+
try {
|
|
1534
|
+
if (!data.from) {
|
|
1535
|
+
throw new Error(
|
|
1536
|
+
"Email 'from' address must be provided in sendEmail data."
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
return await new Promise(
|
|
1540
|
+
(resolve, reject) => {
|
|
1541
|
+
this.mailgunClient.messages().send(data, (error, body) => {
|
|
1542
|
+
if (error) {
|
|
1543
|
+
console.error("[BaseMailingService] Error sending email:", error);
|
|
1544
|
+
reject(error);
|
|
1545
|
+
} else {
|
|
1546
|
+
console.log(
|
|
1547
|
+
"[BaseMailingService] Email sent successfully:",
|
|
1548
|
+
body
|
|
1549
|
+
);
|
|
1550
|
+
resolve(body);
|
|
1551
|
+
}
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
);
|
|
1555
|
+
} catch (error) {
|
|
1556
|
+
console.error("[BaseMailingService] Error in sendEmail:", error);
|
|
1557
|
+
throw error;
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Logs email sending attempt to Firestore for tracking
|
|
1562
|
+
* @param emailData Email data that was sent
|
|
1563
|
+
* @param success Whether the email was sent successfully
|
|
1564
|
+
* @param error Error object if the email failed to send
|
|
1565
|
+
*/
|
|
1566
|
+
async logEmailAttempt(emailData, success, error) {
|
|
1567
|
+
try {
|
|
1568
|
+
const emailLogRef = this.db.collection("email_logs").doc();
|
|
1569
|
+
await emailLogRef.set({
|
|
1570
|
+
to: emailData.to,
|
|
1571
|
+
subject: emailData.subject,
|
|
1572
|
+
templateName: emailData.templateName,
|
|
1573
|
+
success,
|
|
1574
|
+
error: error ? JSON.stringify(error) : null,
|
|
1575
|
+
sentAt: admin6.firestore.FieldValue.serverTimestamp()
|
|
1576
|
+
});
|
|
1577
|
+
} catch (logError) {
|
|
1578
|
+
console.error(
|
|
1579
|
+
"[BaseMailingService] Error logging email attempt:",
|
|
1580
|
+
logError
|
|
1581
|
+
);
|
|
1582
|
+
}
|
|
1583
|
+
}
|
|
1584
|
+
/**
|
|
1585
|
+
* Renders a simple HTML email template with variables
|
|
1586
|
+
* @param template HTML template string
|
|
1587
|
+
* @param variables Key-value pairs to replace in the template
|
|
1588
|
+
* @returns Rendered HTML string
|
|
1589
|
+
*/
|
|
1590
|
+
renderTemplate(template, variables) {
|
|
1591
|
+
let rendered = template;
|
|
1592
|
+
Object.entries(variables).forEach(([key, value]) => {
|
|
1593
|
+
const regex = new RegExp(`{{\\s*${key}\\s*}}`, "g");
|
|
1594
|
+
rendered = rendered.replace(regex, value);
|
|
1595
|
+
});
|
|
1596
|
+
return rendered;
|
|
1597
|
+
}
|
|
1598
|
+
};
|
|
1599
|
+
|
|
1600
|
+
// src/admin/mailing/practitionerInvite/templates/invitation.template.ts
|
|
1601
|
+
var practitionerInvitationTemplate = `
|
|
1602
|
+
<!DOCTYPE html>
|
|
1603
|
+
<html>
|
|
1604
|
+
<head>
|
|
1605
|
+
<meta charset="UTF-8">
|
|
1606
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1607
|
+
<title>Join {{clinicName}} as a Practitioner</title>
|
|
1608
|
+
<style>
|
|
1609
|
+
body {
|
|
1610
|
+
font-family: Arial, sans-serif;
|
|
1611
|
+
line-height: 1.6;
|
|
1612
|
+
color: #333;
|
|
1613
|
+
margin: 0;
|
|
1614
|
+
padding: 0;
|
|
1615
|
+
}
|
|
1616
|
+
.container {
|
|
1617
|
+
max-width: 600px;
|
|
1618
|
+
margin: 0 auto;
|
|
1619
|
+
padding: 20px;
|
|
1620
|
+
}
|
|
1621
|
+
.header {
|
|
1622
|
+
background-color: #4A90E2;
|
|
1623
|
+
padding: 20px;
|
|
1624
|
+
text-align: center;
|
|
1625
|
+
color: white;
|
|
1626
|
+
}
|
|
1627
|
+
.content {
|
|
1628
|
+
padding: 20px;
|
|
1629
|
+
background-color: #f9f9f9;
|
|
1630
|
+
}
|
|
1631
|
+
.footer {
|
|
1632
|
+
padding: 20px;
|
|
1633
|
+
text-align: center;
|
|
1634
|
+
font-size: 12px;
|
|
1635
|
+
color: #888;
|
|
1636
|
+
}
|
|
1637
|
+
.button {
|
|
1638
|
+
display: inline-block;
|
|
1639
|
+
background-color: #4A90E2;
|
|
1640
|
+
color: white;
|
|
1641
|
+
text-decoration: none;
|
|
1642
|
+
padding: 12px 24px;
|
|
1643
|
+
border-radius: 4px;
|
|
1644
|
+
margin: 20px 0;
|
|
1645
|
+
font-weight: bold;
|
|
1646
|
+
}
|
|
1647
|
+
.token {
|
|
1648
|
+
font-size: 24px;
|
|
1649
|
+
font-weight: bold;
|
|
1650
|
+
color: #4A90E2;
|
|
1651
|
+
padding: 10px;
|
|
1652
|
+
background-color: #e9f0f9;
|
|
1653
|
+
border-radius: 4px;
|
|
1654
|
+
display: inline-block;
|
|
1655
|
+
letter-spacing: 2px;
|
|
1656
|
+
margin: 10px 0;
|
|
1657
|
+
}
|
|
1658
|
+
</style>
|
|
1659
|
+
</head>
|
|
1660
|
+
<body>
|
|
1661
|
+
<div class="container">
|
|
1662
|
+
<div class="header">
|
|
1663
|
+
<h1>You've Been Invited</h1>
|
|
1664
|
+
</div>
|
|
1665
|
+
<div class="content">
|
|
1666
|
+
<p>Hello {{practitionerName}},</p>
|
|
1667
|
+
|
|
1668
|
+
<p>You have been invited to join <strong>{{clinicName}}</strong> as a healthcare practitioner.</p>
|
|
1669
|
+
|
|
1670
|
+
<p>Your profile has been created and is ready for you to claim. Please use the following token to register:</p>
|
|
1671
|
+
|
|
1672
|
+
<div style="text-align: center;">
|
|
1673
|
+
<span class="token">{{inviteToken}}</span>
|
|
1674
|
+
</div>
|
|
1675
|
+
|
|
1676
|
+
<p>This token will expire on <strong>{{expirationDate}}</strong>.</p>
|
|
1677
|
+
|
|
1678
|
+
<p>To create your account:</p>
|
|
1679
|
+
<ol>
|
|
1680
|
+
<li>Visit {{registrationUrl}}</li>
|
|
1681
|
+
<li>Enter your email and create a password</li>
|
|
1682
|
+
<li>When prompted, enter the token above</li>
|
|
1683
|
+
</ol>
|
|
1684
|
+
|
|
1685
|
+
<div style="text-align: center;">
|
|
1686
|
+
<a href="{{registrationUrl}}" class="button">Create Your Account</a>
|
|
1687
|
+
</div>
|
|
1688
|
+
|
|
1689
|
+
<p>If you have any questions, please contact {{contactName}} at {{contactEmail}}.</p>
|
|
1690
|
+
</div>
|
|
1691
|
+
<div class="footer">
|
|
1692
|
+
<p>This is an automated message from {{clinicName}}. Please do not reply to this email.</p>
|
|
1693
|
+
<p>© {{currentYear}} {{clinicName}}. All rights reserved.</p>
|
|
1694
|
+
</div>
|
|
1695
|
+
</div>
|
|
1696
|
+
</body>
|
|
1697
|
+
</html>
|
|
1698
|
+
`;
|
|
1699
|
+
|
|
1700
|
+
// src/admin/mailing/practitionerInvite/practitionerInvite.mailing.ts
|
|
1701
|
+
var PractitionerInviteMailingService = class extends BaseMailingService {
|
|
1702
|
+
/**
|
|
1703
|
+
* Constructor for PractitionerInviteMailingService
|
|
1704
|
+
* @param firestore Firestore instance provided by the caller
|
|
1705
|
+
* @param mailgunClient Mailgun client instance provided by the caller
|
|
1706
|
+
*/
|
|
1707
|
+
constructor(firestore7, mailgunClient) {
|
|
1708
|
+
super(firestore7, mailgunClient);
|
|
1709
|
+
this.DEFAULT_REGISTRATION_URL = "https://app.medclinic.com/register";
|
|
1710
|
+
this.DEFAULT_SUBJECT = "You've Been Invited to Join as a Practitioner";
|
|
1711
|
+
this.DEFAULT_FROM_ADDRESS = "MedClinic <no-reply@your-domain.com>";
|
|
1712
|
+
}
|
|
1713
|
+
/**
|
|
1714
|
+
* Sends a practitioner invitation email
|
|
1715
|
+
* @param data The practitioner invitation data
|
|
1716
|
+
* @returns Promise resolved when email is sent
|
|
1717
|
+
*/
|
|
1718
|
+
async sendInvitationEmail(data) {
|
|
1719
|
+
var _a, _b, _c, _d;
|
|
1720
|
+
try {
|
|
1721
|
+
console.log(
|
|
1722
|
+
"[PractitionerInviteMailingService] Sending invitation email to",
|
|
1723
|
+
data.token.email
|
|
1724
|
+
);
|
|
1725
|
+
const expirationDate = data.token.expiresAt.toDate().toLocaleDateString("en-US", {
|
|
1726
|
+
weekday: "long",
|
|
1727
|
+
year: "numeric",
|
|
1728
|
+
month: "long",
|
|
1729
|
+
day: "numeric"
|
|
1730
|
+
});
|
|
1731
|
+
const registrationUrl = ((_a = data.options) == null ? void 0 : _a.registrationUrl) || this.DEFAULT_REGISTRATION_URL;
|
|
1732
|
+
const contactName = data.clinic.contactName || "Clinic Administrator";
|
|
1733
|
+
const contactEmail = data.clinic.contactEmail;
|
|
1734
|
+
const subject = ((_b = data.options) == null ? void 0 : _b.customSubject) || this.DEFAULT_SUBJECT;
|
|
1735
|
+
const fromAddress = ((_c = data.options) == null ? void 0 : _c.fromAddress) || this.DEFAULT_FROM_ADDRESS;
|
|
1736
|
+
const currentYear = (/* @__PURE__ */ new Date()).getFullYear().toString();
|
|
1737
|
+
const practitionerName = `${data.practitioner.firstName} ${data.practitioner.lastName}`;
|
|
1738
|
+
const templateVariables = {
|
|
1739
|
+
clinicName: data.clinic.name,
|
|
1740
|
+
practitionerName,
|
|
1741
|
+
inviteToken: data.token.token,
|
|
1742
|
+
expirationDate,
|
|
1743
|
+
registrationUrl,
|
|
1744
|
+
contactName,
|
|
1745
|
+
contactEmail,
|
|
1746
|
+
currentYear
|
|
1747
|
+
};
|
|
1748
|
+
const html = this.renderTemplate(
|
|
1749
|
+
practitionerInvitationTemplate,
|
|
1750
|
+
templateVariables
|
|
1751
|
+
);
|
|
1752
|
+
const emailData = {
|
|
1753
|
+
to: data.token.email,
|
|
1754
|
+
from: fromAddress,
|
|
1755
|
+
subject,
|
|
1756
|
+
html
|
|
1757
|
+
};
|
|
1758
|
+
const result = await this.sendEmail(emailData);
|
|
1759
|
+
await this.logEmailAttempt(
|
|
1760
|
+
{
|
|
1761
|
+
to: data.token.email,
|
|
1762
|
+
subject,
|
|
1763
|
+
templateName: "practitioner_invitation"
|
|
1764
|
+
},
|
|
1765
|
+
true
|
|
1766
|
+
);
|
|
1767
|
+
return result;
|
|
1768
|
+
} catch (error) {
|
|
1769
|
+
console.error(
|
|
1770
|
+
"[PractitionerInviteMailingService] Error sending invitation email:",
|
|
1771
|
+
error
|
|
1772
|
+
);
|
|
1773
|
+
await this.logEmailAttempt(
|
|
1774
|
+
{
|
|
1775
|
+
to: data.token.email,
|
|
1776
|
+
subject: ((_d = data.options) == null ? void 0 : _d.customSubject) || this.DEFAULT_SUBJECT,
|
|
1777
|
+
templateName: "practitioner_invitation"
|
|
1778
|
+
},
|
|
1779
|
+
false,
|
|
1780
|
+
error
|
|
1781
|
+
);
|
|
1782
|
+
throw error;
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
/**
|
|
1786
|
+
* Handles the practitioner token creation event from Cloud Functions
|
|
1787
|
+
* Fetches necessary data using defined types and collection constants,
|
|
1788
|
+
* and sends the invitation email.
|
|
1789
|
+
* @param tokenData The fully typed token object including its id
|
|
1790
|
+
* @param fromAddress The 'from' email address to use, obtained from config
|
|
1791
|
+
* @returns Promise resolved when the email is sent
|
|
1792
|
+
*/
|
|
1793
|
+
async handleTokenCreationEvent(tokenData, fromAddress) {
|
|
1794
|
+
try {
|
|
1795
|
+
console.log(
|
|
1796
|
+
"[PractitionerInviteMailingService] Handling token creation event for token:",
|
|
1797
|
+
tokenData.id
|
|
1798
|
+
);
|
|
1799
|
+
const practitionerRef = this.db.collection(PRACTITIONERS_COLLECTION).doc(tokenData.practitionerId);
|
|
1800
|
+
const practitionerDoc = await practitionerRef.get();
|
|
1801
|
+
if (!practitionerDoc.exists) {
|
|
1802
|
+
throw new Error(`Practitioner ${tokenData.practitionerId} not found`);
|
|
1803
|
+
}
|
|
1804
|
+
const practitionerData = practitionerDoc.data();
|
|
1805
|
+
const clinicRef = this.db.collection(CLINICS_COLLECTION).doc(tokenData.clinicId);
|
|
1806
|
+
const clinicDoc = await clinicRef.get();
|
|
1807
|
+
if (!clinicDoc.exists) {
|
|
1808
|
+
throw new Error(`Clinic ${tokenData.clinicId} not found`);
|
|
1809
|
+
}
|
|
1810
|
+
const clinicData = clinicDoc.data();
|
|
1811
|
+
const emailData = {
|
|
1812
|
+
token: {
|
|
1813
|
+
id: tokenData.id,
|
|
1814
|
+
token: tokenData.token,
|
|
1815
|
+
practitionerId: tokenData.practitionerId,
|
|
1816
|
+
email: tokenData.email,
|
|
1817
|
+
clinicId: tokenData.clinicId,
|
|
1818
|
+
expiresAt: tokenData.expiresAt
|
|
1819
|
+
},
|
|
1820
|
+
practitioner: {
|
|
1821
|
+
firstName: practitionerData.basicInfo.firstName || "",
|
|
1822
|
+
lastName: practitionerData.basicInfo.lastName || ""
|
|
1823
|
+
},
|
|
1824
|
+
clinic: {
|
|
1825
|
+
name: clinicData.name || "Medical Clinic",
|
|
1826
|
+
contactEmail: clinicData.contactInfo.email || "contact@medclinic.com"
|
|
1827
|
+
},
|
|
1828
|
+
options: {
|
|
1829
|
+
fromAddress
|
|
1830
|
+
}
|
|
1831
|
+
};
|
|
1832
|
+
await this.sendInvitationEmail(emailData);
|
|
1833
|
+
console.log(
|
|
1834
|
+
"[PractitionerInviteMailingService] Invitation email sent successfully"
|
|
1835
|
+
);
|
|
1836
|
+
} catch (error) {
|
|
1837
|
+
console.error(
|
|
1838
|
+
"[PractitionerInviteMailingService] Error handling token creation event:",
|
|
1839
|
+
error
|
|
1840
|
+
);
|
|
1841
|
+
throw error;
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
};
|
|
1845
|
+
|
|
1513
1846
|
// src/types/index.ts
|
|
1514
1847
|
var UserRole = /* @__PURE__ */ ((UserRole2) => {
|
|
1515
1848
|
UserRole2["PATIENT"] = "patient";
|
|
@@ -1522,6 +1855,7 @@ var UserRole = /* @__PURE__ */ ((UserRole2) => {
|
|
|
1522
1855
|
// src/admin/index.ts
|
|
1523
1856
|
console.log("[Admin Module] Initialized and services exported.");
|
|
1524
1857
|
export {
|
|
1858
|
+
BaseMailingService,
|
|
1525
1859
|
ClinicAggregationService,
|
|
1526
1860
|
NOTIFICATIONS_COLLECTION,
|
|
1527
1861
|
NotificationStatus,
|
|
@@ -1529,6 +1863,7 @@ export {
|
|
|
1529
1863
|
NotificationsAdmin,
|
|
1530
1864
|
PatientAggregationService,
|
|
1531
1865
|
PractitionerAggregationService,
|
|
1866
|
+
PractitionerInviteMailingService,
|
|
1532
1867
|
ProcedureAggregationService,
|
|
1533
1868
|
UserRole
|
|
1534
1869
|
};
|
package/dist/index.d.mts
CHANGED
|
@@ -4545,31 +4545,16 @@ declare class ClinicService extends BaseService {
|
|
|
4545
4545
|
private clinicGroupService;
|
|
4546
4546
|
private clinicAdminService;
|
|
4547
4547
|
constructor(db: Firestore, auth: Auth, app: FirebaseApp, clinicGroupService: ClinicGroupService, clinicAdminService: ClinicAdminService);
|
|
4548
|
-
/**
|
|
4549
|
-
* Creates an aggregated ClinicInfo object from Clinic data.
|
|
4550
|
-
* @param clinic The clinic object
|
|
4551
|
-
* @returns ClinicInfo object
|
|
4552
|
-
*/
|
|
4553
|
-
private _createClinicInfoForAggregation;
|
|
4554
|
-
/**
|
|
4555
|
-
* Updates the ClinicInfo within the clinicsInfo array for multiple practitioners.
|
|
4556
|
-
* @param practitionerIds IDs of practitioners to update
|
|
4557
|
-
* @param clinicInfo The updated ClinicInfo object
|
|
4558
|
-
*/
|
|
4559
|
-
private _updateClinicInfoInPractitioners;
|
|
4560
4548
|
/**
|
|
4561
4549
|
* Creates a new clinic.
|
|
4562
|
-
* Initializes empty doctorsInfo and proceduresInfo.
|
|
4563
|
-
* Aggregation into Clinic happens via PractitionerService and ProcedureService.
|
|
4564
4550
|
*/
|
|
4565
4551
|
createClinic(data: CreateClinicData, creatorAdminId: string): Promise<Clinic>;
|
|
4566
4552
|
/**
|
|
4567
|
-
* Updates a clinic
|
|
4553
|
+
* Updates a clinic.
|
|
4568
4554
|
*/
|
|
4569
4555
|
updateClinic(clinicId: string, data: Partial<Omit<Clinic, "id" | "createdAt" | "clinicGroupId">>, adminId: string): Promise<Clinic>;
|
|
4570
4556
|
/**
|
|
4571
4557
|
* Deactivates a clinic.
|
|
4572
|
-
* Note: Does not currently remove ClinicInfo from practitioners (might be desired).
|
|
4573
4558
|
*/
|
|
4574
4559
|
deactivateClinic(clinicId: string, adminId: string): Promise<void>;
|
|
4575
4560
|
/**
|
|
@@ -4582,7 +4567,6 @@ declare class ClinicService extends BaseService {
|
|
|
4582
4567
|
getClinicsByGroup(groupId: string): Promise<Clinic[]>;
|
|
4583
4568
|
/**
|
|
4584
4569
|
* Pretražuje klinike u određenom radijusu
|
|
4585
|
-
* REVIEW: SearchUtils.findClinicsInRadius might need updating for filters.
|
|
4586
4570
|
*/
|
|
4587
4571
|
findClinicsInRadius(center: {
|
|
4588
4572
|
latitude: number;
|
|
@@ -4708,28 +4692,9 @@ declare class PractitionerService extends BaseService {
|
|
|
4708
4692
|
private clinicService?;
|
|
4709
4693
|
constructor(db: Firestore, auth: Auth, app: FirebaseApp, clinicService?: ClinicService);
|
|
4710
4694
|
private getClinicService;
|
|
4711
|
-
/**
|
|
4712
|
-
* Postavlja referencu na ClinicService nakon inicijalizacije
|
|
4713
|
-
*/
|
|
4714
4695
|
setClinicService(clinicService: ClinicService): void;
|
|
4715
4696
|
/**
|
|
4716
|
-
*
|
|
4717
|
-
* @param clinicIds Array of clinic IDs the practitioner works at
|
|
4718
|
-
* @returns Array of ClinicInfo objects
|
|
4719
|
-
*/
|
|
4720
|
-
private aggregateClinicInfo;
|
|
4721
|
-
/**
|
|
4722
|
-
* @deprecated Aggregation of procedure info is now handled by ProcedureService.
|
|
4723
|
-
*/
|
|
4724
|
-
private aggregateProcedureInfo;
|
|
4725
|
-
/**
|
|
4726
|
-
* Updates aggregated data (clinics and procedures) for a practitioner
|
|
4727
|
-
* @param practitionerId ID of the practitioner to update
|
|
4728
|
-
* @returns Updated practitioner
|
|
4729
|
-
*/
|
|
4730
|
-
updateAggregatedData(practitionerId: string): Promise<Practitioner | null>;
|
|
4731
|
-
/**
|
|
4732
|
-
* Kreira novog zdravstvenog radnika
|
|
4697
|
+
* Creates a new practitioner
|
|
4733
4698
|
*/
|
|
4734
4699
|
createPractitioner(data: CreatePractitionerData): Promise<Practitioner>;
|
|
4735
4700
|
/**
|
|
@@ -4791,15 +4756,15 @@ declare class PractitionerService extends BaseService {
|
|
|
4791
4756
|
*/
|
|
4792
4757
|
getDraftPractitionersByClinic(clinicId: string): Promise<Practitioner[]>;
|
|
4793
4758
|
/**
|
|
4794
|
-
*
|
|
4759
|
+
* Updates a practitioner
|
|
4795
4760
|
*/
|
|
4796
4761
|
updatePractitioner(practitionerId: string, data: UpdatePractitionerData): Promise<Practitioner>;
|
|
4797
4762
|
/**
|
|
4798
|
-
*
|
|
4763
|
+
* Adds a clinic to a practitioner
|
|
4799
4764
|
*/
|
|
4800
4765
|
addClinic(practitionerId: string, clinicId: string): Promise<void>;
|
|
4801
4766
|
/**
|
|
4802
|
-
*
|
|
4767
|
+
* Removes a clinic from a practitioner
|
|
4803
4768
|
*/
|
|
4804
4769
|
removeClinic(practitionerId: string, clinicId: string): Promise<void>;
|
|
4805
4770
|
/**
|
|
@@ -4880,30 +4845,6 @@ declare class PractitionerService extends BaseService {
|
|
|
4880
4845
|
practitioners: Practitioner[];
|
|
4881
4846
|
lastDoc: any;
|
|
4882
4847
|
}>;
|
|
4883
|
-
/**
|
|
4884
|
-
* Aggregates essential clinic information for embedding in Practitioner.
|
|
4885
|
-
* @param clinicIds Array of clinic IDs the practitioner works at
|
|
4886
|
-
* @returns Array of ClinicInfo objects
|
|
4887
|
-
*/
|
|
4888
|
-
private _aggregateClinicInfoForPractitioner;
|
|
4889
|
-
/**
|
|
4890
|
-
* Creates an aggregated DoctorInfo object from Practitioner data.
|
|
4891
|
-
* @param practitioner The practitioner object
|
|
4892
|
-
* @returns DoctorInfo object
|
|
4893
|
-
*/
|
|
4894
|
-
private _createDoctorInfoForClinic;
|
|
4895
|
-
/**
|
|
4896
|
-
* Updates the DoctorInfo within the doctorsInfo array for multiple clinics.
|
|
4897
|
-
* @param clinicIds IDs of clinics to update
|
|
4898
|
-
* @param doctorInfo The updated DoctorInfo object
|
|
4899
|
-
*/
|
|
4900
|
-
private _updateDoctorInfoInClinics;
|
|
4901
|
-
/**
|
|
4902
|
-
* Removes DoctorInfo from the doctorsInfo array for multiple clinics.
|
|
4903
|
-
* @param clinicIds IDs of clinics to update
|
|
4904
|
-
* @param practitionerId ID of the practitioner whose info should be removed
|
|
4905
|
-
*/
|
|
4906
|
-
private _removeDoctorInfoFromClinics;
|
|
4907
4848
|
}
|
|
4908
4849
|
|
|
4909
4850
|
declare class UserService extends BaseService {
|
|
@@ -5225,11 +5166,8 @@ declare class ProcedureService extends BaseService {
|
|
|
5225
5166
|
private technologyService;
|
|
5226
5167
|
private productService;
|
|
5227
5168
|
constructor(db: Firestore, auth: Auth, app: FirebaseApp, categoryService: CategoryService, subcategoryService: SubcategoryService, technologyService: TechnologyService, productService: ProductService);
|
|
5228
|
-
private _createProcedureSummaryInfo;
|
|
5229
|
-
private _updatePractitionerProcedures;
|
|
5230
|
-
private _updateClinicProcedures;
|
|
5231
5169
|
/**
|
|
5232
|
-
* Creates a new procedure
|
|
5170
|
+
* Creates a new procedure
|
|
5233
5171
|
* @param data - The data for creating a new procedure
|
|
5234
5172
|
* @returns The created procedure
|
|
5235
5173
|
*/
|
|
@@ -5253,19 +5191,19 @@ declare class ProcedureService extends BaseService {
|
|
|
5253
5191
|
*/
|
|
5254
5192
|
getProceduresByPractitioner(practitionerId: string): Promise<Procedure[]>;
|
|
5255
5193
|
/**
|
|
5256
|
-
* Updates a procedure
|
|
5194
|
+
* Updates a procedure
|
|
5257
5195
|
* @param id - The ID of the procedure to update
|
|
5258
5196
|
* @param data - The data to update the procedure with
|
|
5259
5197
|
* @returns The updated procedure
|
|
5260
5198
|
*/
|
|
5261
5199
|
updateProcedure(id: string, data: UpdateProcedureData): Promise<Procedure>;
|
|
5262
5200
|
/**
|
|
5263
|
-
* Deactivates a procedure (soft delete)
|
|
5201
|
+
* Deactivates a procedure (soft delete)
|
|
5264
5202
|
* @param id - The ID of the procedure to deactivate
|
|
5265
5203
|
*/
|
|
5266
5204
|
deactivateProcedure(id: string): Promise<void>;
|
|
5267
5205
|
/**
|
|
5268
|
-
* Deletes a procedure permanently
|
|
5206
|
+
* Deletes a procedure permanently
|
|
5269
5207
|
* @param id - The ID of the procedure to delete
|
|
5270
5208
|
* @returns A boolean indicating if the deletion was successful
|
|
5271
5209
|
*/
|
|
@@ -5292,6 +5230,61 @@ declare class ProcedureService extends BaseService {
|
|
|
5292
5230
|
procedures: Procedure[];
|
|
5293
5231
|
lastDoc: any;
|
|
5294
5232
|
}>;
|
|
5233
|
+
/**
|
|
5234
|
+
* Searches and filters procedures based on multiple criteria
|
|
5235
|
+
*
|
|
5236
|
+
* @param filters - Various filters to apply
|
|
5237
|
+
* @param filters.nameSearch - Optional search text for procedure name
|
|
5238
|
+
* @param filters.treatmentBenefits - Optional array of treatment benefits to filter by
|
|
5239
|
+
* @param filters.procedureFamily - Optional procedure family to filter by
|
|
5240
|
+
* @param filters.procedureCategory - Optional procedure category to filter by
|
|
5241
|
+
* @param filters.procedureSubcategory - Optional procedure subcategory to filter by
|
|
5242
|
+
* @param filters.procedureTechnology - Optional procedure technology to filter by
|
|
5243
|
+
* @param filters.location - Optional location for distance-based search
|
|
5244
|
+
* @param filters.radiusInKm - Optional radius in kilometers (required if location is provided)
|
|
5245
|
+
* @param filters.minPrice - Optional minimum price
|
|
5246
|
+
* @param filters.maxPrice - Optional maximum price
|
|
5247
|
+
* @param filters.minRating - Optional minimum rating (0-5)
|
|
5248
|
+
* @param filters.maxRating - Optional maximum rating (0-5)
|
|
5249
|
+
* @param filters.pagination - Optional number of results per page
|
|
5250
|
+
* @param filters.lastDoc - Optional last document for pagination
|
|
5251
|
+
* @param filters.isActive - Optional filter for active procedures only
|
|
5252
|
+
* @returns Filtered procedures and the last document for pagination
|
|
5253
|
+
*/
|
|
5254
|
+
getProceduresByFilters(filters: {
|
|
5255
|
+
nameSearch?: string;
|
|
5256
|
+
treatmentBenefits?: TreatmentBenefit[];
|
|
5257
|
+
procedureFamily?: ProcedureFamily;
|
|
5258
|
+
procedureCategory?: string;
|
|
5259
|
+
procedureSubcategory?: string;
|
|
5260
|
+
procedureTechnology?: string;
|
|
5261
|
+
location?: {
|
|
5262
|
+
latitude: number;
|
|
5263
|
+
longitude: number;
|
|
5264
|
+
};
|
|
5265
|
+
radiusInKm?: number;
|
|
5266
|
+
minPrice?: number;
|
|
5267
|
+
maxPrice?: number;
|
|
5268
|
+
minRating?: number;
|
|
5269
|
+
maxRating?: number;
|
|
5270
|
+
pagination?: number;
|
|
5271
|
+
lastDoc?: any;
|
|
5272
|
+
isActive?: boolean;
|
|
5273
|
+
}): Promise<{
|
|
5274
|
+
procedures: (Procedure & {
|
|
5275
|
+
distance?: number;
|
|
5276
|
+
})[];
|
|
5277
|
+
lastDoc: any;
|
|
5278
|
+
}>;
|
|
5279
|
+
/**
|
|
5280
|
+
* Helper method to apply in-memory filters to procedures
|
|
5281
|
+
* Used by getProceduresByFilters to apply filters that can't be done in Firestore queries
|
|
5282
|
+
*
|
|
5283
|
+
* @param procedures - The procedures to filter
|
|
5284
|
+
* @param filters - The filters to apply
|
|
5285
|
+
* @returns Filtered procedures
|
|
5286
|
+
*/
|
|
5287
|
+
private applyInMemoryFilters;
|
|
5295
5288
|
}
|
|
5296
5289
|
|
|
5297
5290
|
/**
|