@imranq2/fhirpatientsummary 1.0.32 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/dist/index.cjs +332 -134
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +332 -134
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -189,6 +189,8 @@ var IPSSectionResourceFilters = {
|
|
|
189
189
|
};
|
|
190
190
|
var IPSSectionSummaryCompositionFilter = {
|
|
191
191
|
["AllergyIntoleranceSection" /* ALLERGIES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "allergy_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
192
|
+
["ProblemSection" /* PROBLEMS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "condition_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
193
|
+
["HistoryOfPastIllnessSection" /* MEDICAL_HISTORY */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "condition_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
192
194
|
["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "vital_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
193
195
|
["PlanOfCareSection" /* CARE_PLAN */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "careplan_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
194
196
|
["ImmunizationSection" /* IMMUNIZATIONS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "immunization_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
@@ -197,7 +199,8 @@ var IPSSectionSummaryCompositionFilter = {
|
|
|
197
199
|
["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "procedure_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
|
|
198
200
|
};
|
|
199
201
|
var IPSSectionSummaryIPSCompositionFilter = {
|
|
200
|
-
["
|
|
202
|
+
["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_patient_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
203
|
+
["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_vital_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
|
|
201
204
|
};
|
|
202
205
|
var IPSSectionResourceHelper = class {
|
|
203
206
|
static getResourceFilterForSection(section) {
|
|
@@ -209,10 +212,16 @@ var IPSSectionResourceHelper = class {
|
|
|
209
212
|
return resources.filter(filter);
|
|
210
213
|
}
|
|
211
214
|
static getSummaryCompositionFilterForSection(section) {
|
|
212
|
-
|
|
215
|
+
const sectionCompositionEnabled = process.env.SUMMARY_COMPOSITION_SECTIONS ? process.env.SUMMARY_COMPOSITION_SECTIONS.split(",").some(
|
|
216
|
+
(s) => s.trim().toLowerCase() === section.toString().toLowerCase() || s.trim().toLowerCase() === "all"
|
|
217
|
+
) : false;
|
|
218
|
+
return sectionCompositionEnabled ? IPSSectionSummaryCompositionFilter[section] : void 0;
|
|
213
219
|
}
|
|
214
220
|
static getSummaryIPSCompositionFilterForSection(section) {
|
|
215
|
-
|
|
221
|
+
const sectionIPSCompositionEnabled = process.env.SUMMARY_IPS_COMPOSITION_SECTIONS ? process.env.SUMMARY_IPS_COMPOSITION_SECTIONS.split(",").some(
|
|
222
|
+
(s) => s.trim().toLowerCase() === section.toString().toLowerCase() || s.trim().toLowerCase() === "all"
|
|
223
|
+
) : false;
|
|
224
|
+
return sectionIPSCompositionEnabled ? IPSSectionSummaryIPSCompositionFilter[section] : void 0;
|
|
216
225
|
}
|
|
217
226
|
};
|
|
218
227
|
function codingMatches(coding, code, system) {
|
|
@@ -912,18 +921,6 @@ var TemplateUtilities = class {
|
|
|
912
921
|
}
|
|
913
922
|
return "";
|
|
914
923
|
}
|
|
915
|
-
/**
|
|
916
|
-
* Returns the owner tag from the resource meta.security array.
|
|
917
|
-
* @param resource - FHIR resource with meta tag
|
|
918
|
-
* @returns The owner code if found, otherwise undefined
|
|
919
|
-
*/
|
|
920
|
-
getOwnerTag(resource) {
|
|
921
|
-
if (!resource?.meta?.security) return "";
|
|
922
|
-
const ownerEntry = resource.meta.security.find(
|
|
923
|
-
(sec) => sec.system === "https://www.icanbwell.com/owner" && !!sec.code
|
|
924
|
-
);
|
|
925
|
-
return ownerEntry?.code;
|
|
926
|
-
}
|
|
927
924
|
/**
|
|
928
925
|
* Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
|
|
929
926
|
* This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
|
|
@@ -944,6 +941,17 @@ var TemplateUtilities = class {
|
|
|
944
941
|
}
|
|
945
942
|
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
946
943
|
}
|
|
944
|
+
renderListSectionData(sectionData) {
|
|
945
|
+
if (!sectionData || !Array.isArray(sectionData) || sectionData.length === 0) {
|
|
946
|
+
return "";
|
|
947
|
+
}
|
|
948
|
+
const items = [];
|
|
949
|
+
for (const section of sectionData) {
|
|
950
|
+
items.push(this.renderTextAsHtml(section.text?.div || ""));
|
|
951
|
+
}
|
|
952
|
+
const listString = Array.from(items).map((item) => `<li>${item}</li>`).join("");
|
|
953
|
+
return `<ul>${listString}</ul>`;
|
|
954
|
+
}
|
|
947
955
|
/**
|
|
948
956
|
* Renders note elements from a FHIR resource in a standardized format
|
|
949
957
|
* Can render as simple comma-separated text or as styled HTML with timestamps
|
|
@@ -1431,6 +1439,60 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1431
1439
|
generateNarrative(resources, timezone) {
|
|
1432
1440
|
return _PatientTemplate.generateStaticNarrative(resources, timezone);
|
|
1433
1441
|
}
|
|
1442
|
+
/**
|
|
1443
|
+
* Generate HTML narrative for Patient resources using summary
|
|
1444
|
+
* @param resources - FHIR Composition resources
|
|
1445
|
+
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
1446
|
+
* @returns HTML string for rendering
|
|
1447
|
+
*/
|
|
1448
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1449
|
+
generateSummaryNarrative(resources, timezone) {
|
|
1450
|
+
const templateUtilities = new TemplateUtilities(resources);
|
|
1451
|
+
const compositionResources = resources[0];
|
|
1452
|
+
const data = {};
|
|
1453
|
+
for (const rowData of compositionResources.section ?? []) {
|
|
1454
|
+
for (const columnData of rowData.section ?? []) {
|
|
1455
|
+
switch (columnData.title) {
|
|
1456
|
+
case "Name":
|
|
1457
|
+
case "Address":
|
|
1458
|
+
case "Communication":
|
|
1459
|
+
data[columnData.title] = templateUtilities.renderListSectionData(columnData.section ?? []);
|
|
1460
|
+
break;
|
|
1461
|
+
case "Telecom": {
|
|
1462
|
+
const telecomStringParts = [];
|
|
1463
|
+
for (const telecomData of columnData.section ?? []) {
|
|
1464
|
+
const telecomSystem = telecomData?.title;
|
|
1465
|
+
const telecomValue = templateUtilities.renderListSectionData(telecomData.section ?? []);
|
|
1466
|
+
if (telecomSystem && telecomValue) {
|
|
1467
|
+
telecomStringParts.push(`<li><strong>${telecomSystem}:</strong>${telecomValue}</li>`);
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
data["Telecom"] = `<ul>${telecomStringParts.join("")}</ul>`;
|
|
1471
|
+
break;
|
|
1472
|
+
}
|
|
1473
|
+
default:
|
|
1474
|
+
if (columnData.title) {
|
|
1475
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1476
|
+
}
|
|
1477
|
+
break;
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
let html = `<p>This section merges all Patient resources into a single combined patient record, preferring non-empty values for each field.</p>`;
|
|
1482
|
+
html += `<div>
|
|
1483
|
+
<ul>
|
|
1484
|
+
<li><strong>Name(s):</strong>${data["Name"] || ""}</li>
|
|
1485
|
+
<li><strong>Gender:</strong>${data["Gender"] || ""}</li>
|
|
1486
|
+
<li><strong>Date of Birth:</strong>${data["Date of Birth"] || ""}</li>
|
|
1487
|
+
<li><strong>Telecom:</strong>${data["Telecom"] || ""}</li>
|
|
1488
|
+
<li><strong>Address(es):</strong>${data["Address"] || ""}</li>
|
|
1489
|
+
${data["Marital Status"] ? `<li><strong>Marital Status:</strong>${data["Marital Status"]}</li>` : ""}
|
|
1490
|
+
${data["Deceased"] ? `<li><strong>Deceased:</strong>${data["Deceased"]}</li>` : ""}
|
|
1491
|
+
<li><strong>Language(s):</strong>${data["Communication"] || ""}</li>
|
|
1492
|
+
</ul>
|
|
1493
|
+
</div>`;
|
|
1494
|
+
return html;
|
|
1495
|
+
}
|
|
1434
1496
|
/**
|
|
1435
1497
|
* Internal static implementation that actually generates the narrative
|
|
1436
1498
|
* @param resources - FHIR Patient resources
|
|
@@ -1441,6 +1503,7 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1441
1503
|
static generateStaticNarrative(resources, timezone) {
|
|
1442
1504
|
const templateUtilities = new TemplateUtilities(resources);
|
|
1443
1505
|
const combinedPatient = this.combinePatients(resources);
|
|
1506
|
+
const deceasedText = this.renderDeceased(combinedPatient);
|
|
1444
1507
|
let html = `<p>This section merges all Patient resources into a single combined patient record, preferring non-empty values for each field.</p>`;
|
|
1445
1508
|
html += `<div>
|
|
1446
1509
|
<ul>
|
|
@@ -1449,8 +1512,8 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1449
1512
|
<li><strong>Date of Birth:</strong>${combinedPatient.birthDate || ""}</li>
|
|
1450
1513
|
<li><strong>Telecom:</strong><ul>${this.renderTelecom(combinedPatient)}</ul></li>
|
|
1451
1514
|
<li><strong>Address(es):</strong>${this.renderAddresses(combinedPatient)}</li>
|
|
1452
|
-
|
|
1453
|
-
|
|
1515
|
+
${combinedPatient.maritalStatus?.text ? `<li><strong>Marital Status:</strong> ${combinedPatient.maritalStatus.text}</li>` : ""}
|
|
1516
|
+
${deceasedText ? `<li><strong>Deceased:</strong>${deceasedText}</li>` : ""}
|
|
1454
1517
|
<li><strong>Language(s):</strong>${this.renderCommunication(templateUtilities, combinedPatient)}</li>
|
|
1455
1518
|
</ul>
|
|
1456
1519
|
</div>`;
|
|
@@ -1524,7 +1587,8 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1524
1587
|
}
|
|
1525
1588
|
}
|
|
1526
1589
|
});
|
|
1527
|
-
|
|
1590
|
+
const namesHtml = Array.from(uniqueNames).map((nameText) => `<li>${nameText}</li>`).join("");
|
|
1591
|
+
return `<ul>${namesHtml}</ul>`;
|
|
1528
1592
|
}
|
|
1529
1593
|
/**
|
|
1530
1594
|
* Renders patient telecom information grouped by system
|
|
@@ -1628,7 +1692,8 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1628
1692
|
}
|
|
1629
1693
|
});
|
|
1630
1694
|
const deduplicatedAddresses = this.deduplicateSimilarAddresses(Array.from(uniqueAddresses));
|
|
1631
|
-
|
|
1695
|
+
const addressesHtml = deduplicatedAddresses.map((addressText) => `<li>${addressText}</li>`).join("");
|
|
1696
|
+
return `<ul>${addressesHtml}</ul>`;
|
|
1632
1697
|
}
|
|
1633
1698
|
/**
|
|
1634
1699
|
* Calculates the similarity between two strings using Levenshtein distance
|
|
@@ -1746,7 +1811,8 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1746
1811
|
uniqueLanguages.add(language);
|
|
1747
1812
|
}
|
|
1748
1813
|
});
|
|
1749
|
-
|
|
1814
|
+
const languagesHtml = Array.from(uniqueLanguages).map((language) => `<li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li>`).join("");
|
|
1815
|
+
return `<ul>${languagesHtml}</ul>`;
|
|
1750
1816
|
}
|
|
1751
1817
|
/**
|
|
1752
1818
|
* Capitalizes first letter of a string
|
|
@@ -1790,7 +1856,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1790
1856
|
<th>Code (System)</th>
|
|
1791
1857
|
<th>Criticality</th>
|
|
1792
1858
|
<th>Recorded Date</th>
|
|
1793
|
-
<th>Source</th>
|
|
1794
1859
|
</tr>
|
|
1795
1860
|
</thead>
|
|
1796
1861
|
<tbody>`;
|
|
@@ -1810,13 +1875,13 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1810
1875
|
case "Recorded Date":
|
|
1811
1876
|
data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1812
1877
|
break;
|
|
1813
|
-
case "Source":
|
|
1814
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1815
|
-
break;
|
|
1816
1878
|
default:
|
|
1817
1879
|
break;
|
|
1818
1880
|
}
|
|
1819
1881
|
}
|
|
1882
|
+
if (data["allergen"]?.toLowerCase() === "unknown") {
|
|
1883
|
+
continue;
|
|
1884
|
+
}
|
|
1820
1885
|
isSummaryCreated = true;
|
|
1821
1886
|
html += `
|
|
1822
1887
|
<tr>
|
|
@@ -1824,7 +1889,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1824
1889
|
<td>${data["codeSystem"] ?? ""}</td>
|
|
1825
1890
|
<td>${data["criticality"] ?? ""}</td>
|
|
1826
1891
|
<td>${templateUtilities.renderTime(data["recordedDate"], timezone) ?? ""}</td>
|
|
1827
|
-
<td>${data["source"] ?? ""}</td>
|
|
1828
1892
|
</tr>`;
|
|
1829
1893
|
}
|
|
1830
1894
|
}
|
|
@@ -1878,7 +1942,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1878
1942
|
<th>Reaction</th>
|
|
1879
1943
|
<th>Onset Date</th>
|
|
1880
1944
|
<th>Comments</th>
|
|
1881
|
-
<th>Source</th>
|
|
1882
1945
|
</tr>
|
|
1883
1946
|
</thead>
|
|
1884
1947
|
<tbody>`;
|
|
@@ -1908,7 +1971,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1908
1971
|
<th>Onset Date</th>
|
|
1909
1972
|
<th>Comments</th>
|
|
1910
1973
|
<th>Resolved Date</th>
|
|
1911
|
-
<th>Source</th>
|
|
1912
1974
|
</tr>
|
|
1913
1975
|
</thead>
|
|
1914
1976
|
<tbody>`;
|
|
@@ -1937,16 +1999,19 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1937
1999
|
static generateAllergyRows(allergies, templateUtilities, timezone, includeResolved = false) {
|
|
1938
2000
|
let html = "";
|
|
1939
2001
|
for (const allergy of allergies) {
|
|
2002
|
+
const allergenName = templateUtilities.codeableConceptDisplay(allergy.code);
|
|
2003
|
+
if (allergenName?.toLowerCase() === "unknown") {
|
|
2004
|
+
continue;
|
|
2005
|
+
}
|
|
1940
2006
|
html += `
|
|
1941
2007
|
<tr>
|
|
1942
|
-
<td class="Name"><span class="AllergenName">${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(
|
|
2008
|
+
<td class="Name"><span class="AllergenName">${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(allergenName))}</span></td>
|
|
1943
2009
|
<td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(allergy.clinicalStatus)) || ""}</td>
|
|
1944
2010
|
<td class="CodeSystem">${templateUtilities.codeableConceptCoding(allergy.code)}</td>
|
|
1945
2011
|
<td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || ""}</td>
|
|
1946
2012
|
<td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || ""}</td>
|
|
1947
2013
|
<td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || ""}</td>
|
|
1948
|
-
<td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td
|
|
1949
|
-
<td class="Source">${templateUtilities.getOwnerTag(allergy)}</td>`;
|
|
2014
|
+
<td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
|
|
1950
2015
|
if (includeResolved) {
|
|
1951
2016
|
let endDate = "";
|
|
1952
2017
|
if (allergy.extension && Array.isArray(allergy.extension)) {
|
|
@@ -2001,9 +2066,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2001
2066
|
<th>Status</th>
|
|
2002
2067
|
<th>Sig</th>
|
|
2003
2068
|
<th>Days of Supply</th>
|
|
2004
|
-
<th>Refills</th>
|
|
2005
2069
|
<th>Start Date</th>
|
|
2006
|
-
<th>Source</th>
|
|
2007
2070
|
</tr>
|
|
2008
2071
|
</thead>
|
|
2009
2072
|
<tbody>`;
|
|
@@ -2029,15 +2092,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2029
2092
|
case "Days Of Supply":
|
|
2030
2093
|
data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2031
2094
|
break;
|
|
2032
|
-
case "Refills Remaining":
|
|
2033
|
-
data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2034
|
-
break;
|
|
2035
2095
|
case "Authored On Date":
|
|
2036
2096
|
data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2037
2097
|
break;
|
|
2038
|
-
case "Source":
|
|
2039
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2040
|
-
break;
|
|
2041
2098
|
default:
|
|
2042
2099
|
break;
|
|
2043
2100
|
}
|
|
@@ -2053,6 +2110,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2053
2110
|
skippedMedications++;
|
|
2054
2111
|
}
|
|
2055
2112
|
if (data["status"] === "active" || startDateObj && startDateObj >= twoYearsAgo) {
|
|
2113
|
+
if (data["medication"]?.toLowerCase() === "unknown") {
|
|
2114
|
+
continue;
|
|
2115
|
+
}
|
|
2056
2116
|
isSummaryCreated = true;
|
|
2057
2117
|
html += `
|
|
2058
2118
|
<tr>
|
|
@@ -2061,9 +2121,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2061
2121
|
<td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
|
|
2062
2122
|
<td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
|
|
2063
2123
|
<td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
|
|
2064
|
-
<td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
|
|
2065
2124
|
<td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
|
|
2066
|
-
<td>${templateUtilities.renderTextAsHtml(data["source"])}</td>
|
|
2067
2125
|
</tr>`;
|
|
2068
2126
|
}
|
|
2069
2127
|
}
|
|
@@ -2188,9 +2246,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2188
2246
|
<th>Code (System)</th>
|
|
2189
2247
|
<th>Sig</th>
|
|
2190
2248
|
<th>Dispense Quantity</th>
|
|
2191
|
-
<th>Refills</th>
|
|
2192
2249
|
<th>Start Date</th>
|
|
2193
|
-
<th>Source</th>
|
|
2194
2250
|
</tr>
|
|
2195
2251
|
</thead>
|
|
2196
2252
|
<tbody>`;
|
|
@@ -2199,7 +2255,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2199
2255
|
let medicationName;
|
|
2200
2256
|
let sig;
|
|
2201
2257
|
let dispenseQuantity = "";
|
|
2202
|
-
let refills = "";
|
|
2203
2258
|
let startDate = "";
|
|
2204
2259
|
let codeSystemDisplay = "";
|
|
2205
2260
|
if (medication.type === "request") {
|
|
@@ -2215,7 +2270,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2215
2270
|
dispenseQuantity = `${quantity.value} ${quantity.unit || quantity.code || ""}`.trim();
|
|
2216
2271
|
}
|
|
2217
2272
|
}
|
|
2218
|
-
refills = mr.dispenseRequest?.numberOfRepeatsAllowed?.toString() || "";
|
|
2219
2273
|
if (mr.dispenseRequest?.validityPeriod) {
|
|
2220
2274
|
startDate = mr.dispenseRequest.validityPeriod.start || "";
|
|
2221
2275
|
} else {
|
|
@@ -2240,6 +2294,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2240
2294
|
codeSystemDisplay = templateUtilities.codeableConceptCoding(ms.medicationCodeableConcept);
|
|
2241
2295
|
}
|
|
2242
2296
|
}
|
|
2297
|
+
if (medicationName?.toLowerCase() === "unknown") {
|
|
2298
|
+
continue;
|
|
2299
|
+
}
|
|
2243
2300
|
html += `
|
|
2244
2301
|
<tr>
|
|
2245
2302
|
<td>${type}</td>
|
|
@@ -2247,9 +2304,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2247
2304
|
<td>${codeSystemDisplay}</td>
|
|
2248
2305
|
<td>${sig}</td>
|
|
2249
2306
|
<td>${dispenseQuantity}</td>
|
|
2250
|
-
<td>${refills}</td>
|
|
2251
2307
|
<td>${startDate}</td>
|
|
2252
|
-
<td>${templateUtilities.getOwnerTag(medication.resource)}</td>
|
|
2253
2308
|
</tr>`;
|
|
2254
2309
|
}
|
|
2255
2310
|
html += `
|
|
@@ -2294,7 +2349,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2294
2349
|
<th>Code (System)</th>
|
|
2295
2350
|
<th>Status</th>
|
|
2296
2351
|
<th>Date</th>
|
|
2297
|
-
<th>Source</th>
|
|
2298
2352
|
</tr>
|
|
2299
2353
|
</thead>
|
|
2300
2354
|
<tbody>`;
|
|
@@ -2314,14 +2368,14 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2314
2368
|
case "occurrenceDateTime":
|
|
2315
2369
|
data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2316
2370
|
break;
|
|
2317
|
-
case "Source":
|
|
2318
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2319
|
-
break;
|
|
2320
2371
|
default:
|
|
2321
2372
|
break;
|
|
2322
2373
|
}
|
|
2323
2374
|
}
|
|
2324
2375
|
if (data["status"] === "completed") {
|
|
2376
|
+
if (data["immunization"]?.toLowerCase() === "unknown") {
|
|
2377
|
+
continue;
|
|
2378
|
+
}
|
|
2325
2379
|
isSummaryCreated = true;
|
|
2326
2380
|
html += `
|
|
2327
2381
|
<tr>
|
|
@@ -2329,7 +2383,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2329
2383
|
<td>${data["codeSystem"] ?? ""}</td>
|
|
2330
2384
|
<td>${data["status"] ?? ""}</td>
|
|
2331
2385
|
<td>${templateUtilities.renderTime(data["occurrenceDateTime"], timezone) ?? ""}</td>
|
|
2332
|
-
<td>${data["source"] ?? ""}</td>
|
|
2333
2386
|
</tr>`;
|
|
2334
2387
|
}
|
|
2335
2388
|
}
|
|
@@ -2360,7 +2413,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2360
2413
|
<th>Lot Number</th>
|
|
2361
2414
|
<th>Comments</th>
|
|
2362
2415
|
<th>Date</th>
|
|
2363
|
-
<th>Source</th>
|
|
2364
2416
|
</tr>
|
|
2365
2417
|
</thead>
|
|
2366
2418
|
<tbody>`;
|
|
@@ -2368,9 +2420,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2368
2420
|
if (immunizations.length > 0) {
|
|
2369
2421
|
for (const resourceItem of immunizations) {
|
|
2370
2422
|
const imm = resourceItem;
|
|
2423
|
+
const immunizationName = templateUtilities.codeableConceptDisplay(imm.vaccineCode);
|
|
2424
|
+
if (immunizationName?.toLowerCase() === "unknown") {
|
|
2425
|
+
continue;
|
|
2426
|
+
}
|
|
2371
2427
|
html += `
|
|
2372
2428
|
<tr>
|
|
2373
|
-
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(
|
|
2429
|
+
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(immunizationName))}</td>
|
|
2374
2430
|
<td>${templateUtilities.codeableConceptCoding(imm.vaccineCode)}</td>
|
|
2375
2431
|
<td>${imm.status || ""}</td>
|
|
2376
2432
|
<td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
|
|
@@ -2378,7 +2434,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2378
2434
|
<td>${imm.lotNumber || ""}</td>
|
|
2379
2435
|
<td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
|
|
2380
2436
|
<td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
|
|
2381
|
-
<td>${templateUtilities.getOwnerTag(imm)}</td>
|
|
2382
2437
|
</tr>`;
|
|
2383
2438
|
}
|
|
2384
2439
|
}
|
|
@@ -2400,6 +2455,59 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2400
2455
|
generateNarrative(resources, timezone) {
|
|
2401
2456
|
return _ProblemListTemplate.generateStaticNarrative(resources, timezone);
|
|
2402
2457
|
}
|
|
2458
|
+
/**
|
|
2459
|
+
* Generate HTML narrative for Condition resources using summary
|
|
2460
|
+
* @param resources - FHIR Composition resources
|
|
2461
|
+
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
2462
|
+
* @returns HTML string for rendering
|
|
2463
|
+
*/
|
|
2464
|
+
generateSummaryNarrative(resources, timezone) {
|
|
2465
|
+
const templateUtilities = new TemplateUtilities(resources);
|
|
2466
|
+
let isSummaryCreated = false;
|
|
2467
|
+
let html = `<p>This list includes patient problems, sorted by recorded date (most recent first)</p>
|
|
2468
|
+
<div>
|
|
2469
|
+
<table>
|
|
2470
|
+
<thead>
|
|
2471
|
+
<tr>
|
|
2472
|
+
<th>Problem</th>
|
|
2473
|
+
<th>Code (System)</th>
|
|
2474
|
+
<th>Is Chronic</th>
|
|
2475
|
+
<th>Onset Date</th>
|
|
2476
|
+
<th>Last Confirmed Date</th>
|
|
2477
|
+
</tr>
|
|
2478
|
+
</thead>
|
|
2479
|
+
<tbody>`;
|
|
2480
|
+
for (const resourceItem of resources) {
|
|
2481
|
+
for (const rowData of resourceItem.section ?? []) {
|
|
2482
|
+
const sectionCodeableConcept = rowData.code;
|
|
2483
|
+
const data = {};
|
|
2484
|
+
for (const columnData of rowData.section ?? []) {
|
|
2485
|
+
if (columnData.title) {
|
|
2486
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
if (data["Condition Name"]?.toLowerCase() === "unknown") {
|
|
2490
|
+
continue;
|
|
2491
|
+
}
|
|
2492
|
+
if (data["Status"] === "active") {
|
|
2493
|
+
isSummaryCreated = true;
|
|
2494
|
+
html += `
|
|
2495
|
+
<tr>
|
|
2496
|
+
<td>${templateUtilities.capitalizeFirstLetter(data["Condition Name"] ?? "")}</td>
|
|
2497
|
+
<td>${templateUtilities.codeableConceptCoding(sectionCodeableConcept)}</td>
|
|
2498
|
+
<td>${data["Is Chronic"] ?? ""}</td>
|
|
2499
|
+
<td>${templateUtilities.renderTime(data["Onset Date"], timezone) ?? ""}</td>
|
|
2500
|
+
<td>${templateUtilities.renderTime(data["Last Confirmed Date"], timezone) ?? ""}</td>
|
|
2501
|
+
</tr>`;
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
html += `
|
|
2506
|
+
</tbody>
|
|
2507
|
+
</table>
|
|
2508
|
+
</div>`;
|
|
2509
|
+
return isSummaryCreated ? html : void 0;
|
|
2510
|
+
}
|
|
2403
2511
|
/**
|
|
2404
2512
|
* Internal static implementation that actually generates the narrative
|
|
2405
2513
|
* @param resources - FHIR Condition resources
|
|
@@ -2428,7 +2536,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2428
2536
|
<th>Code (System)</th>
|
|
2429
2537
|
<th>Onset Date</th>
|
|
2430
2538
|
<th>Recorded Date</th>
|
|
2431
|
-
<th>Source</th>
|
|
2432
2539
|
</tr>
|
|
2433
2540
|
</thead>
|
|
2434
2541
|
<tbody>`;
|
|
@@ -2439,13 +2546,15 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2439
2546
|
if (codeAndSystem && seenCodeAndSystems.has(codeAndSystem)) {
|
|
2440
2547
|
continue;
|
|
2441
2548
|
}
|
|
2549
|
+
if (conditionDisplay?.toLowerCase() === "unknown") {
|
|
2550
|
+
continue;
|
|
2551
|
+
}
|
|
2442
2552
|
seenCodeAndSystems.add(codeAndSystem);
|
|
2443
2553
|
html += `<tr>
|
|
2444
2554
|
<td class="Name">${templateUtilities.capitalizeFirstLetter(conditionDisplay)}</td>
|
|
2445
2555
|
<td class="CodeSystem">${codeAndSystem}</td>
|
|
2446
2556
|
<td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
|
|
2447
2557
|
<td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
|
|
2448
|
-
<td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
|
|
2449
2558
|
</tr>`;
|
|
2450
2559
|
}
|
|
2451
2560
|
html += `</tbody>
|
|
@@ -2485,7 +2594,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2485
2594
|
<th>Code (System)</th>
|
|
2486
2595
|
<th>Result</th>
|
|
2487
2596
|
<th>Date</th>
|
|
2488
|
-
<th>Source</th>
|
|
2489
2597
|
</tr>
|
|
2490
2598
|
</thead>
|
|
2491
2599
|
<tbody>`;
|
|
@@ -2518,6 +2626,9 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2518
2626
|
data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2519
2627
|
}
|
|
2520
2628
|
}
|
|
2629
|
+
if (data["Vital Name"]?.toLowerCase() === "unknown") {
|
|
2630
|
+
continue;
|
|
2631
|
+
}
|
|
2521
2632
|
isSummaryCreated = true;
|
|
2522
2633
|
html += `
|
|
2523
2634
|
<tr>
|
|
@@ -2525,7 +2636,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2525
2636
|
<td>${data["codeSystem"] ?? ""}</td>
|
|
2526
2637
|
<td>${templateUtilities.extractObservationSummaryValue(data, timezone) ?? ""}</td>
|
|
2527
2638
|
<td>${templateUtilities.extractObservationSummaryEffectiveTime(data, timezone) ?? ""}</td>
|
|
2528
|
-
<td>${data["Source"] ?? ""}</td>
|
|
2529
2639
|
</tr>`;
|
|
2530
2640
|
}
|
|
2531
2641
|
}
|
|
@@ -2563,14 +2673,17 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2563
2673
|
<th>Component(s)</th>
|
|
2564
2674
|
<th>Comments</th>
|
|
2565
2675
|
<th>Date</th>
|
|
2566
|
-
<th>Source</th>
|
|
2567
2676
|
</tr>
|
|
2568
2677
|
</thead>
|
|
2569
2678
|
<tbody>`;
|
|
2570
2679
|
for (const obs of observations) {
|
|
2680
|
+
const vitalName = templateUtilities.codeableConceptDisplay(obs.code, "display");
|
|
2681
|
+
if (vitalName?.toLowerCase() === "unknown") {
|
|
2682
|
+
continue;
|
|
2683
|
+
}
|
|
2571
2684
|
html += `
|
|
2572
2685
|
<tr>
|
|
2573
|
-
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(
|
|
2686
|
+
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(vitalName))}</td>
|
|
2574
2687
|
<td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
|
|
2575
2688
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
2576
2689
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
@@ -2578,7 +2691,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2578
2691
|
<td>${templateUtilities.renderComponent(obs.component)}</td>
|
|
2579
2692
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
2580
2693
|
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
2581
|
-
<td>${templateUtilities.getOwnerTag(obs)}</td>
|
|
2582
2694
|
</tr>`;
|
|
2583
2695
|
}
|
|
2584
2696
|
html += `
|
|
@@ -2625,10 +2737,14 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
|
|
|
2625
2737
|
});
|
|
2626
2738
|
let isDeviceAdded = false;
|
|
2627
2739
|
for (const dus of deviceStatements) {
|
|
2740
|
+
const deviceName = templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device));
|
|
2741
|
+
if (deviceName?.toLowerCase() === "unknown") {
|
|
2742
|
+
continue;
|
|
2743
|
+
}
|
|
2628
2744
|
isDeviceAdded = true;
|
|
2629
2745
|
html += `
|
|
2630
2746
|
<tr>
|
|
2631
|
-
<td>${templateUtilities.capitalizeFirstLetter(
|
|
2747
|
+
<td>${templateUtilities.capitalizeFirstLetter(deviceName)}</td>
|
|
2632
2748
|
<td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
|
|
2633
2749
|
<td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
|
|
2634
2750
|
<td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
|
|
@@ -3002,7 +3118,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3002
3118
|
<th>Result</th>
|
|
3003
3119
|
<th>Reference Range</th>
|
|
3004
3120
|
<th>Date</th>
|
|
3005
|
-
<th>Source</th>
|
|
3006
3121
|
</tr>
|
|
3007
3122
|
</thead>
|
|
3008
3123
|
<tbody>`;
|
|
@@ -3016,7 +3131,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3016
3131
|
<th>Report</th>
|
|
3017
3132
|
<th>Performer</th>
|
|
3018
3133
|
<th>Issued</th>
|
|
3019
|
-
<th>Source</th>
|
|
3020
3134
|
</tr>
|
|
3021
3135
|
</thead>
|
|
3022
3136
|
<tbody>`;
|
|
@@ -3063,8 +3177,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3063
3177
|
case "Status":
|
|
3064
3178
|
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3065
3179
|
break;
|
|
3066
|
-
case "Source":
|
|
3067
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3068
3180
|
break;
|
|
3069
3181
|
default:
|
|
3070
3182
|
break;
|
|
@@ -3090,6 +3202,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3090
3202
|
for (const component of components) {
|
|
3091
3203
|
const componentCode = `${groupName}${component["code"] ?? ""}`;
|
|
3092
3204
|
if (componentCode && !observationAdded.has(componentCode)) {
|
|
3205
|
+
if (component["code"]?.toLowerCase() === "unknown") {
|
|
3206
|
+
continue;
|
|
3207
|
+
}
|
|
3093
3208
|
observationAdded.add(componentCode);
|
|
3094
3209
|
this.formatSummaryObservationData(component);
|
|
3095
3210
|
observationhtml += `
|
|
@@ -3099,7 +3214,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3099
3214
|
<td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? ""}</td>
|
|
3100
3215
|
<td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? ""}</td>
|
|
3101
3216
|
<td>${date ?? ""}</td>
|
|
3102
|
-
<td>${data["source"] ?? ""}</td>
|
|
3103
3217
|
</tr>`;
|
|
3104
3218
|
}
|
|
3105
3219
|
}
|
|
@@ -3107,6 +3221,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3107
3221
|
if (obsDate && obsDate >= twoYearsAgo) {
|
|
3108
3222
|
const code = data["code"] ?? "";
|
|
3109
3223
|
if (code && !observationAdded.has(code)) {
|
|
3224
|
+
if (code.toLowerCase() === "unknown") {
|
|
3225
|
+
continue;
|
|
3226
|
+
}
|
|
3110
3227
|
observationAdded.add(code);
|
|
3111
3228
|
this.formatSummaryObservationData(data);
|
|
3112
3229
|
observationhtml += `
|
|
@@ -3116,7 +3233,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3116
3233
|
<td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? ""}</td>
|
|
3117
3234
|
<td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? ""}</td>
|
|
3118
3235
|
<td>${date ?? ""}</td>
|
|
3119
|
-
<td>${data["source"] ?? ""}</td>
|
|
3120
3236
|
</tr>`;
|
|
3121
3237
|
}
|
|
3122
3238
|
}
|
|
@@ -3129,13 +3245,15 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3129
3245
|
if (data["status"] === "final" && issuedDate && issuedDate >= twoYearsAgo) {
|
|
3130
3246
|
const reportName = data["report"] ?? "";
|
|
3131
3247
|
if (reportName && !diagnosticReportAdded.has(reportName)) {
|
|
3248
|
+
if (reportName.toLowerCase() === "unknown") {
|
|
3249
|
+
continue;
|
|
3250
|
+
}
|
|
3132
3251
|
diagnosticReportAdded.add(reportName);
|
|
3133
3252
|
diagnosticReporthtml += `
|
|
3134
3253
|
<tr>
|
|
3135
3254
|
<td>${templateUtilities.capitalizeFirstLetter(data["report"] ?? "")}</td>
|
|
3136
3255
|
<td>${data["performer"] ?? ""}</td>
|
|
3137
3256
|
<td>${templateUtilities.renderTime(data["issued"], timezone) ?? ""}</td>
|
|
3138
|
-
<td>${data["source"] ?? ""}</td>
|
|
3139
3257
|
</tr>`;
|
|
3140
3258
|
}
|
|
3141
3259
|
}
|
|
@@ -3320,7 +3438,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3320
3438
|
<th>Result</th>
|
|
3321
3439
|
<th>Reference Range</th>
|
|
3322
3440
|
<th>Date</th>
|
|
3323
|
-
<th>Source</th>
|
|
3324
3441
|
</tr>
|
|
3325
3442
|
</thead>
|
|
3326
3443
|
<tbody>`;
|
|
@@ -3329,6 +3446,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3329
3446
|
const obsCodeDisplay = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
|
|
3330
3447
|
const obsCodeAndSystem = templateUtilities.codeableConceptCoding(obs.code);
|
|
3331
3448
|
if (!observationAdded.has(obsCodeDisplay) && !observationAdded.has(obsCodeAndSystem)) {
|
|
3449
|
+
if (obsCodeDisplay?.toLowerCase() === "unknown") {
|
|
3450
|
+
continue;
|
|
3451
|
+
}
|
|
3332
3452
|
observationAdded.add(obsCodeDisplay);
|
|
3333
3453
|
observationAdded.add(obsCodeAndSystem);
|
|
3334
3454
|
html += `
|
|
@@ -3338,7 +3458,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3338
3458
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
3339
3459
|
<td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
|
|
3340
3460
|
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
3341
|
-
<td>${templateUtilities.getOwnerTag(obs)}</td>
|
|
3342
3461
|
</tr>`;
|
|
3343
3462
|
}
|
|
3344
3463
|
}
|
|
@@ -3365,7 +3484,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3365
3484
|
<th>Category</th>
|
|
3366
3485
|
<th>Result</th>
|
|
3367
3486
|
<th>Issued</th>
|
|
3368
|
-
<th>Source</th>
|
|
3369
3487
|
</tr>
|
|
3370
3488
|
</thead>
|
|
3371
3489
|
<tbody>`;
|
|
@@ -3374,6 +3492,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3374
3492
|
const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(report.code));
|
|
3375
3493
|
const codeAndSystem = templateUtilities.codeableConceptCoding(report.code);
|
|
3376
3494
|
if (!diagnosticReportAdded.has(reportName) && !diagnosticReportAdded.has(codeAndSystem)) {
|
|
3495
|
+
if (reportName?.toLowerCase() === "unknown") {
|
|
3496
|
+
continue;
|
|
3497
|
+
}
|
|
3377
3498
|
diagnosticReportAdded.add(reportName);
|
|
3378
3499
|
diagnosticReportAdded.add(codeAndSystem);
|
|
3379
3500
|
let resultCount = "";
|
|
@@ -3387,7 +3508,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3387
3508
|
<td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
|
|
3388
3509
|
<td>${resultCount}</td>
|
|
3389
3510
|
<td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
|
|
3390
|
-
<td>${templateUtilities.getOwnerTag(report)}</td>
|
|
3391
3511
|
</tr>`;
|
|
3392
3512
|
}
|
|
3393
3513
|
}
|
|
@@ -3454,7 +3574,6 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3454
3574
|
<th>Code (System)</th>
|
|
3455
3575
|
<th>Performer</th>
|
|
3456
3576
|
<th>Date</th>
|
|
3457
|
-
<th>Source</th>
|
|
3458
3577
|
</tr>
|
|
3459
3578
|
</thead>
|
|
3460
3579
|
<tbody>`;
|
|
@@ -3474,13 +3593,14 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3474
3593
|
case "Performed Date":
|
|
3475
3594
|
data["date"] = columnData.text?.div ?? "";
|
|
3476
3595
|
break;
|
|
3477
|
-
case "Source":
|
|
3478
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3479
3596
|
break;
|
|
3480
3597
|
default:
|
|
3481
3598
|
break;
|
|
3482
3599
|
}
|
|
3483
3600
|
}
|
|
3601
|
+
if (data["procedure"]?.toLowerCase() === "unknown") {
|
|
3602
|
+
continue;
|
|
3603
|
+
}
|
|
3484
3604
|
isSummaryCreated = true;
|
|
3485
3605
|
html += `
|
|
3486
3606
|
<tr>
|
|
@@ -3488,7 +3608,6 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3488
3608
|
<td>${data["codeSystem"] ?? ""}</td>
|
|
3489
3609
|
<td>${data["performer"] ?? ""}</td>
|
|
3490
3610
|
<td>${templateUtilities.renderTime(data["date"], timezone) ?? ""}</td>
|
|
3491
|
-
<td>${data["source"] ?? ""}</td>
|
|
3492
3611
|
</tr>`;
|
|
3493
3612
|
}
|
|
3494
3613
|
}
|
|
@@ -3516,19 +3635,21 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3516
3635
|
<th>Code (System)</th>
|
|
3517
3636
|
<th>Comments</th>
|
|
3518
3637
|
<th>Date</th>
|
|
3519
|
-
<th>Source</th>
|
|
3520
3638
|
</tr>
|
|
3521
3639
|
</thead>
|
|
3522
3640
|
<tbody>`;
|
|
3523
3641
|
for (const resourceItem of resources) {
|
|
3524
3642
|
const proc = resourceItem;
|
|
3643
|
+
const procedureName = templateUtilities.codeableConceptDisplay(proc.code, "display");
|
|
3644
|
+
if (procedureName?.toLowerCase() === "unknown") {
|
|
3645
|
+
continue;
|
|
3646
|
+
}
|
|
3525
3647
|
html += `
|
|
3526
3648
|
<tr>
|
|
3527
|
-
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(
|
|
3649
|
+
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(procedureName))}</td>
|
|
3528
3650
|
<td>${templateUtilities.codeableConceptCoding(proc.code)}</td>
|
|
3529
3651
|
<td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
|
|
3530
3652
|
<td>${templateUtilities.renderTime(proc.performedDateTime || proc.performedPeriod?.start, timezone)}</td>
|
|
3531
|
-
<td>${templateUtilities.getOwnerTag(proc)}</td>
|
|
3532
3653
|
</tr>`;
|
|
3533
3654
|
}
|
|
3534
3655
|
html += `
|
|
@@ -3575,7 +3696,6 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3575
3696
|
<th>Unit</th>
|
|
3576
3697
|
<th>Comments</th>
|
|
3577
3698
|
<th>Date</th>
|
|
3578
|
-
<th>Source</th>
|
|
3579
3699
|
</tr>
|
|
3580
3700
|
</thead>
|
|
3581
3701
|
<tbody>`;
|
|
@@ -3583,6 +3703,9 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3583
3703
|
for (const obs of observations) {
|
|
3584
3704
|
const obsName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
|
|
3585
3705
|
if (!addedObservations.has(obsName)) {
|
|
3706
|
+
if (obsName?.toLowerCase() === "unknown") {
|
|
3707
|
+
continue;
|
|
3708
|
+
}
|
|
3586
3709
|
addedObservations.add(obsName);
|
|
3587
3710
|
html += `
|
|
3588
3711
|
<tr>
|
|
@@ -3592,7 +3715,6 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3592
3715
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
3593
3716
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
3594
3717
|
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
3595
|
-
<td>${templateUtilities.getOwnerTag(obs)}</td>
|
|
3596
3718
|
</tr>`;
|
|
3597
3719
|
}
|
|
3598
3720
|
}
|
|
@@ -3643,7 +3765,6 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3643
3765
|
<th>Onset Date</th>
|
|
3644
3766
|
<th>Recorded Date</th>
|
|
3645
3767
|
<th>Resolved Date</th>
|
|
3646
|
-
<th>Source</th>
|
|
3647
3768
|
</tr>
|
|
3648
3769
|
</thead>
|
|
3649
3770
|
<tbody>`;
|
|
@@ -3651,6 +3772,9 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3651
3772
|
for (const cond of filteredConditions) {
|
|
3652
3773
|
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(cond.code));
|
|
3653
3774
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
3775
|
+
if (conditionCode?.toLowerCase() === "unknown") {
|
|
3776
|
+
continue;
|
|
3777
|
+
}
|
|
3654
3778
|
addedConditionCodes.add(conditionCode);
|
|
3655
3779
|
html += `<tr>
|
|
3656
3780
|
<td class="Name">${templateUtilities.capitalizeFirstLetter(conditionCode)}</td>
|
|
@@ -3658,7 +3782,6 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3658
3782
|
<td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
|
|
3659
3783
|
<td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
|
|
3660
3784
|
<td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
|
|
3661
|
-
<td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
|
|
3662
3785
|
</tr>`;
|
|
3663
3786
|
}
|
|
3664
3787
|
}
|
|
@@ -3670,6 +3793,73 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3670
3793
|
}
|
|
3671
3794
|
return html;
|
|
3672
3795
|
}
|
|
3796
|
+
/**
|
|
3797
|
+
* Generate HTML narrative for Condition resources using summary
|
|
3798
|
+
* @param resources - FHIR Composition resources
|
|
3799
|
+
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3800
|
+
* @returns HTML string for rendering
|
|
3801
|
+
*/
|
|
3802
|
+
generateSummaryNarrative(resources, timezone, now) {
|
|
3803
|
+
const templateUtilities = new TemplateUtilities(resources);
|
|
3804
|
+
let isSummaryCreated = false;
|
|
3805
|
+
const currentDate = now || /* @__PURE__ */ new Date();
|
|
3806
|
+
const fiveYearsAgo = new Date(currentDate);
|
|
3807
|
+
fiveYearsAgo.setFullYear(currentDate.getFullYear() - 5);
|
|
3808
|
+
let skippedConditions = 0;
|
|
3809
|
+
let html = `<p>This list includes past problems for the patient with a recorded date within the last 5 years, sorted by recorded date (most recent first).</p>
|
|
3810
|
+
<div>
|
|
3811
|
+
<table>
|
|
3812
|
+
<thead>
|
|
3813
|
+
<tr>
|
|
3814
|
+
<th>Problem</th>
|
|
3815
|
+
<th>Code (System)</th>
|
|
3816
|
+
<th>Is Chronic</th>
|
|
3817
|
+
<th>Onset Date</th>
|
|
3818
|
+
<th>Last Confirmed Date</th>
|
|
3819
|
+
<th>Resolved Date</th>
|
|
3820
|
+
</tr>
|
|
3821
|
+
</thead>
|
|
3822
|
+
<tbody>`;
|
|
3823
|
+
for (const resourceItem of resources) {
|
|
3824
|
+
for (const rowData of resourceItem.section ?? []) {
|
|
3825
|
+
const sectionCodeableConcept = rowData.code;
|
|
3826
|
+
const data = {};
|
|
3827
|
+
for (const columnData of rowData.section ?? []) {
|
|
3828
|
+
if (columnData.title) {
|
|
3829
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3830
|
+
}
|
|
3831
|
+
}
|
|
3832
|
+
if (data["Condition Name"]?.toLowerCase() === "unknown") {
|
|
3833
|
+
continue;
|
|
3834
|
+
}
|
|
3835
|
+
if (data["Status"] === "inactive") {
|
|
3836
|
+
if (data["Last Confirmed Date"] && new Date(data["Last Confirmed Date"]) < fiveYearsAgo) {
|
|
3837
|
+
skippedConditions++;
|
|
3838
|
+
continue;
|
|
3839
|
+
}
|
|
3840
|
+
isSummaryCreated = true;
|
|
3841
|
+
html += `
|
|
3842
|
+
<tr>
|
|
3843
|
+
<td>${templateUtilities.capitalizeFirstLetter(data["Condition Name"] ?? "")}</td>
|
|
3844
|
+
<td>${templateUtilities.codeableConceptCoding(sectionCodeableConcept)}</td>
|
|
3845
|
+
<td>${data["Is Chronic"] ?? ""}</td>
|
|
3846
|
+
<td>${templateUtilities.renderTime(data["Onset Date"], timezone) ?? ""}</td>
|
|
3847
|
+
<td>${templateUtilities.renderTime(data["Last Confirmed Date"], timezone) ?? ""}</td>
|
|
3848
|
+
<td>${templateUtilities.renderTime(data["Resolved Date"], timezone) ?? ""}</td>
|
|
3849
|
+
</tr>`;
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3853
|
+
html += `
|
|
3854
|
+
</tbody>
|
|
3855
|
+
</table>`;
|
|
3856
|
+
if (skippedConditions > 0) {
|
|
3857
|
+
html += `
|
|
3858
|
+
<p><em>${skippedConditions} additional past illnesses older than 5 years ago are present</em></p>`;
|
|
3859
|
+
}
|
|
3860
|
+
html += `</div>`;
|
|
3861
|
+
return isSummaryCreated ? html : void 0;
|
|
3862
|
+
}
|
|
3673
3863
|
};
|
|
3674
3864
|
|
|
3675
3865
|
// src/narratives/templates/typescript/PlanOfCareTemplate.ts
|
|
@@ -3699,19 +3889,21 @@ var PlanOfCareTemplate = class {
|
|
|
3699
3889
|
<th>Comments</th>
|
|
3700
3890
|
<th>Planned Start</th>
|
|
3701
3891
|
<th>Planned End</th>
|
|
3702
|
-
<th>Source</th>
|
|
3703
3892
|
</tr>
|
|
3704
3893
|
</thead>
|
|
3705
3894
|
<tbody>`;
|
|
3706
3895
|
for (const cp of carePlans) {
|
|
3896
|
+
const carePlanName = cp.description || cp.title || "";
|
|
3897
|
+
if (carePlanName.toLowerCase() === "unknown") {
|
|
3898
|
+
continue;
|
|
3899
|
+
}
|
|
3707
3900
|
html += `
|
|
3708
3901
|
<tr>
|
|
3709
|
-
<td>${templateUtilities.capitalizeFirstLetter(
|
|
3902
|
+
<td>${templateUtilities.capitalizeFirstLetter(carePlanName)}</td>
|
|
3710
3903
|
<td>${cp.intent || ""}</td>
|
|
3711
3904
|
<td>${templateUtilities.concat(cp.note, "text")}</td>
|
|
3712
3905
|
<td>${cp.period?.start ? templateUtilities.renderTime(cp.period?.start, timezone) : ""}</td>
|
|
3713
3906
|
<td>${cp.period?.end ? templateUtilities.renderTime(cp.period?.end, timezone) : ""}</td>
|
|
3714
|
-
<td>${templateUtilities.getOwnerTag(cp)}</td>
|
|
3715
3907
|
</tr>`;
|
|
3716
3908
|
}
|
|
3717
3909
|
html += `
|
|
@@ -3739,7 +3931,6 @@ var PlanOfCareTemplate = class {
|
|
|
3739
3931
|
<th>Created</th>
|
|
3740
3932
|
<th>Planned Start</th>
|
|
3741
3933
|
<th>Planned End</th>
|
|
3742
|
-
<th>Source</th>
|
|
3743
3934
|
</tr>
|
|
3744
3935
|
</thead>
|
|
3745
3936
|
<tbody>`;
|
|
@@ -3754,6 +3945,9 @@ var PlanOfCareTemplate = class {
|
|
|
3754
3945
|
if (data["status"] !== "active") {
|
|
3755
3946
|
continue;
|
|
3756
3947
|
}
|
|
3948
|
+
if (data["CarePlan Name"]?.toLowerCase() === "unknown") {
|
|
3949
|
+
continue;
|
|
3950
|
+
}
|
|
3757
3951
|
isSummaryCreated = true;
|
|
3758
3952
|
html += `
|
|
3759
3953
|
<tr>
|
|
@@ -3761,7 +3955,6 @@ var PlanOfCareTemplate = class {
|
|
|
3761
3955
|
<td>${templateUtilities.renderTime(data["created"], timezone) ?? ""}</td>
|
|
3762
3956
|
<td>${templateUtilities.renderTime(data["period.start"], timezone) ?? ""}</td>
|
|
3763
3957
|
<td>${templateUtilities.renderTime(data["period.end"], timezone) ?? ""}</td>
|
|
3764
|
-
<td>${data["source"] ?? ""}</td>
|
|
3765
3958
|
</tr>`;
|
|
3766
3959
|
}
|
|
3767
3960
|
}
|
|
@@ -3818,6 +4011,9 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
|
|
|
3818
4011
|
for (const obs of functionalObservations) {
|
|
3819
4012
|
const observation = obs;
|
|
3820
4013
|
const obsName = templateUtilities.codeableConceptDisplay(observation.code);
|
|
4014
|
+
if (obsName?.toLowerCase() === "unknown") {
|
|
4015
|
+
continue;
|
|
4016
|
+
}
|
|
3821
4017
|
const value = templateUtilities.extractObservationValue(observation);
|
|
3822
4018
|
const date = observation.effectiveDateTime ? templateUtilities.renderDate(observation.effectiveDateTime) : observation.issued ? templateUtilities.renderDate(observation.issued) : "";
|
|
3823
4019
|
const interpretation = observation.interpretation ? templateUtilities.codeableConceptDisplay(observation.interpretation[0]) : "";
|
|
@@ -3925,18 +4121,19 @@ var PregnancyTemplate = class _PregnancyTemplate {
|
|
|
3925
4121
|
<th>Code (System)</th>
|
|
3926
4122
|
<th>Comments</th>
|
|
3927
4123
|
<th>Date</th>
|
|
3928
|
-
<th>Source</th>
|
|
3929
4124
|
</tr>
|
|
3930
4125
|
</thead>
|
|
3931
4126
|
<tbody>`;
|
|
3932
|
-
function renderRow({ result, comments, date, codeSystem
|
|
4127
|
+
function renderRow({ result, comments, date, codeSystem }) {
|
|
4128
|
+
if (result?.toLowerCase() === "unknown") {
|
|
4129
|
+
return;
|
|
4130
|
+
}
|
|
3933
4131
|
html += `
|
|
3934
4132
|
<tr>
|
|
3935
4133
|
<td class="Result">${templateUtilities.capitalizeFirstLetter(result)}</td>
|
|
3936
4134
|
<td class="CodeSystem">${codeSystem}</td>
|
|
3937
4135
|
<td class="Comments">${comments}</td>
|
|
3938
4136
|
<td class="Date">${date}</td>
|
|
3939
|
-
<td class="Source">${owner}</td>
|
|
3940
4137
|
</tr>`;
|
|
3941
4138
|
}
|
|
3942
4139
|
const rowResources = [];
|
|
@@ -3990,8 +4187,7 @@ var PregnancyTemplate = class _PregnancyTemplate {
|
|
|
3990
4187
|
const rowKey = `${result}|${codeSystem}`;
|
|
3991
4188
|
if (!addedRows.has(rowKey)) {
|
|
3992
4189
|
addedRows.add(rowKey);
|
|
3993
|
-
|
|
3994
|
-
renderRow({ result, comments, date: dateStr, codeSystem, owner });
|
|
4190
|
+
renderRow({ result, comments, date: dateStr, codeSystem });
|
|
3995
4191
|
}
|
|
3996
4192
|
}
|
|
3997
4193
|
html += `
|
|
@@ -4038,11 +4234,17 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
|
|
|
4038
4234
|
</tr>
|
|
4039
4235
|
</thead>
|
|
4040
4236
|
<tbody>`;
|
|
4237
|
+
let isConsentAdded = false;
|
|
4041
4238
|
for (const resourceItem of resources) {
|
|
4042
4239
|
const consent = resourceItem;
|
|
4240
|
+
const consentScope = templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(consent.scope, "display")));
|
|
4241
|
+
if (!consentScope || consentScope.toLowerCase() === "unknown") {
|
|
4242
|
+
continue;
|
|
4243
|
+
}
|
|
4244
|
+
isConsentAdded = true;
|
|
4043
4245
|
html += `
|
|
4044
4246
|
<tr>
|
|
4045
|
-
<td>${
|
|
4247
|
+
<td>${consentScope}</td>
|
|
4046
4248
|
<td>${consent.status || ""}</td>
|
|
4047
4249
|
<td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
|
|
4048
4250
|
<td>${consent.dateTime || ""}</td>
|
|
@@ -4051,7 +4253,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
|
|
|
4051
4253
|
html += `
|
|
4052
4254
|
</tbody>
|
|
4053
4255
|
</table>`;
|
|
4054
|
-
return html;
|
|
4256
|
+
return isConsentAdded ? html : void 0;
|
|
4055
4257
|
}
|
|
4056
4258
|
};
|
|
4057
4259
|
|
|
@@ -4246,6 +4448,10 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4246
4448
|
* @param validResources - Array of domain resources
|
|
4247
4449
|
*/
|
|
4248
4450
|
addSectionAsync(narrative, sectionType, validResources) {
|
|
4451
|
+
if (sectionType === "Patient" /* PATIENT */) {
|
|
4452
|
+
this.patientSummary = narrative;
|
|
4453
|
+
return this;
|
|
4454
|
+
}
|
|
4249
4455
|
const sectionEntry = {
|
|
4250
4456
|
title: IPS_SECTION_DISPLAY_NAMES[sectionType] || sectionType,
|
|
4251
4457
|
code: {
|
|
@@ -4275,26 +4481,24 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4275
4481
|
for (const resource of validResources) {
|
|
4276
4482
|
this.resources.add(resource);
|
|
4277
4483
|
}
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
return this;
|
|
4295
|
-
}
|
|
4296
|
-
this.addSectionAsync(narrative, sectionType, validResources);
|
|
4484
|
+
let narrative = void 0;
|
|
4485
|
+
if (validResources.length > 0) {
|
|
4486
|
+
narrative = await NarrativeGenerator.generateNarrativeAsync(
|
|
4487
|
+
sectionType,
|
|
4488
|
+
validResources,
|
|
4489
|
+
timezone,
|
|
4490
|
+
true
|
|
4491
|
+
);
|
|
4492
|
+
}
|
|
4493
|
+
if (!narrative && sectionType in IPSMandatorySections) {
|
|
4494
|
+
narrative = await NarrativeGenerator.createNarrativeAsync(
|
|
4495
|
+
IPSMissingMandatorySectionContent[sectionType]
|
|
4496
|
+
);
|
|
4497
|
+
}
|
|
4498
|
+
if (!narrative) {
|
|
4499
|
+
return this;
|
|
4297
4500
|
}
|
|
4501
|
+
this.addSectionAsync(narrative, sectionType, validResources);
|
|
4298
4502
|
return this;
|
|
4299
4503
|
}
|
|
4300
4504
|
async makeSectionFromSummaryAsync(sectionType, summaryCompositions, resources, timezone) {
|
|
@@ -4332,17 +4536,18 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4332
4536
|
* @param timezone - Optional timezone to use for date formatting
|
|
4333
4537
|
* @param useSummaryCompositions - Whether to use summary compositions (default: false)
|
|
4334
4538
|
*/
|
|
4335
|
-
async readBundleAsync(bundle, timezone, useSummaryCompositions = false) {
|
|
4539
|
+
async readBundleAsync(bundle, timezone, useSummaryCompositions = false, consoleLogger = console) {
|
|
4336
4540
|
if (!bundle.entry) {
|
|
4337
4541
|
return this;
|
|
4338
4542
|
}
|
|
4339
4543
|
const patientEntries = [];
|
|
4340
4544
|
const resources = [];
|
|
4341
4545
|
bundle.entry.forEach((e) => {
|
|
4342
|
-
if (e.resource
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4546
|
+
if (e.resource) {
|
|
4547
|
+
if (e.resource.resourceType === "Patient") {
|
|
4548
|
+
patientEntries.push(e.resource);
|
|
4549
|
+
this.resources.add(e.resource);
|
|
4550
|
+
}
|
|
4346
4551
|
resources.push(e.resource);
|
|
4347
4552
|
}
|
|
4348
4553
|
});
|
|
@@ -4351,23 +4556,20 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4351
4556
|
}
|
|
4352
4557
|
this.patients = patientEntries;
|
|
4353
4558
|
for (const sectionType of Object.values(IPSSections)) {
|
|
4354
|
-
if (sectionType === "Patient" /* PATIENT */) {
|
|
4355
|
-
continue;
|
|
4356
|
-
}
|
|
4357
4559
|
const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
|
|
4358
4560
|
const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
|
|
4359
4561
|
if (sectionIPSSummary.length > 0) {
|
|
4360
|
-
|
|
4562
|
+
consoleLogger.info(`Using IPS summary composition for section: ${sectionType}`);
|
|
4361
4563
|
await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
|
|
4362
4564
|
continue;
|
|
4363
4565
|
}
|
|
4364
4566
|
const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
|
|
4365
4567
|
const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
|
|
4366
4568
|
if (sectionSummary.length > 0) {
|
|
4367
|
-
|
|
4569
|
+
consoleLogger.info(`Using summary composition for section: ${sectionType}`);
|
|
4368
4570
|
await this.makeSectionFromSummaryAsync(sectionType, sectionSummary, resources, timezone);
|
|
4369
4571
|
} else {
|
|
4370
|
-
|
|
4572
|
+
consoleLogger.info(`Using individual resources for section: ${sectionType}`);
|
|
4371
4573
|
const sectionFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
|
|
4372
4574
|
const sectionResources = resources.filter((resource) => sectionFilter(resource));
|
|
4373
4575
|
await this.makeSectionAsync(sectionType, sectionResources, timezone);
|
|
@@ -4391,6 +4593,9 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4391
4593
|
if (!this.patients) {
|
|
4392
4594
|
throw new Error("Patient resource must be set before building the bundle");
|
|
4393
4595
|
}
|
|
4596
|
+
if (!this.patientSummary) {
|
|
4597
|
+
throw new Error("Patient summary narrative must be set before building the bundle");
|
|
4598
|
+
}
|
|
4394
4599
|
const primaryPatientId = patientId ?? this.patients[0].id;
|
|
4395
4600
|
const composition = {
|
|
4396
4601
|
id: `Composition-${primaryPatientId}`,
|
|
@@ -4414,14 +4619,7 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4414
4619
|
date: (now || /* @__PURE__ */ new Date()).toISOString(),
|
|
4415
4620
|
title: "International Patient Summary",
|
|
4416
4621
|
section: this.sections,
|
|
4417
|
-
text:
|
|
4418
|
-
"Patient" /* PATIENT */,
|
|
4419
|
-
this.patients,
|
|
4420
|
-
timezone,
|
|
4421
|
-
true,
|
|
4422
|
-
false,
|
|
4423
|
-
now
|
|
4424
|
-
)
|
|
4622
|
+
text: this.patientSummary
|
|
4425
4623
|
};
|
|
4426
4624
|
const bundle = {
|
|
4427
4625
|
resourceType: "Bundle",
|