@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.js
CHANGED
|
@@ -161,6 +161,8 @@ var IPSSectionResourceFilters = {
|
|
|
161
161
|
};
|
|
162
162
|
var IPSSectionSummaryCompositionFilter = {
|
|
163
163
|
["AllergyIntoleranceSection" /* ALLERGIES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "allergy_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
164
|
+
["ProblemSection" /* PROBLEMS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "condition_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
165
|
+
["HistoryOfPastIllnessSection" /* MEDICAL_HISTORY */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "condition_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
164
166
|
["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "vital_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
165
167
|
["PlanOfCareSection" /* CARE_PLAN */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "careplan_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
166
168
|
["ImmunizationSection" /* IMMUNIZATIONS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "immunization_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
@@ -169,7 +171,8 @@ var IPSSectionSummaryCompositionFilter = {
|
|
|
169
171
|
["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "procedure_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
|
|
170
172
|
};
|
|
171
173
|
var IPSSectionSummaryIPSCompositionFilter = {
|
|
172
|
-
["
|
|
174
|
+
["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_patient_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
|
|
175
|
+
["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_vital_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
|
|
173
176
|
};
|
|
174
177
|
var IPSSectionResourceHelper = class {
|
|
175
178
|
static getResourceFilterForSection(section) {
|
|
@@ -181,10 +184,16 @@ var IPSSectionResourceHelper = class {
|
|
|
181
184
|
return resources.filter(filter);
|
|
182
185
|
}
|
|
183
186
|
static getSummaryCompositionFilterForSection(section) {
|
|
184
|
-
|
|
187
|
+
const sectionCompositionEnabled = process.env.SUMMARY_COMPOSITION_SECTIONS ? process.env.SUMMARY_COMPOSITION_SECTIONS.split(",").some(
|
|
188
|
+
(s) => s.trim().toLowerCase() === section.toString().toLowerCase() || s.trim().toLowerCase() === "all"
|
|
189
|
+
) : false;
|
|
190
|
+
return sectionCompositionEnabled ? IPSSectionSummaryCompositionFilter[section] : void 0;
|
|
185
191
|
}
|
|
186
192
|
static getSummaryIPSCompositionFilterForSection(section) {
|
|
187
|
-
|
|
193
|
+
const sectionIPSCompositionEnabled = process.env.SUMMARY_IPS_COMPOSITION_SECTIONS ? process.env.SUMMARY_IPS_COMPOSITION_SECTIONS.split(",").some(
|
|
194
|
+
(s) => s.trim().toLowerCase() === section.toString().toLowerCase() || s.trim().toLowerCase() === "all"
|
|
195
|
+
) : false;
|
|
196
|
+
return sectionIPSCompositionEnabled ? IPSSectionSummaryIPSCompositionFilter[section] : void 0;
|
|
188
197
|
}
|
|
189
198
|
};
|
|
190
199
|
function codingMatches(coding, code, system) {
|
|
@@ -884,18 +893,6 @@ var TemplateUtilities = class {
|
|
|
884
893
|
}
|
|
885
894
|
return "";
|
|
886
895
|
}
|
|
887
|
-
/**
|
|
888
|
-
* Returns the owner tag from the resource meta.security array.
|
|
889
|
-
* @param resource - FHIR resource with meta tag
|
|
890
|
-
* @returns The owner code if found, otherwise undefined
|
|
891
|
-
*/
|
|
892
|
-
getOwnerTag(resource) {
|
|
893
|
-
if (!resource?.meta?.security) return "";
|
|
894
|
-
const ownerEntry = resource.meta.security.find(
|
|
895
|
-
(sec) => sec.system === "https://www.icanbwell.com/owner" && !!sec.code
|
|
896
|
-
);
|
|
897
|
-
return ownerEntry?.code;
|
|
898
|
-
}
|
|
899
896
|
/**
|
|
900
897
|
* Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
|
|
901
898
|
* This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
|
|
@@ -916,6 +913,17 @@ var TemplateUtilities = class {
|
|
|
916
913
|
}
|
|
917
914
|
return text.charAt(0).toUpperCase() + text.slice(1);
|
|
918
915
|
}
|
|
916
|
+
renderListSectionData(sectionData) {
|
|
917
|
+
if (!sectionData || !Array.isArray(sectionData) || sectionData.length === 0) {
|
|
918
|
+
return "";
|
|
919
|
+
}
|
|
920
|
+
const items = [];
|
|
921
|
+
for (const section of sectionData) {
|
|
922
|
+
items.push(this.renderTextAsHtml(section.text?.div || ""));
|
|
923
|
+
}
|
|
924
|
+
const listString = Array.from(items).map((item) => `<li>${item}</li>`).join("");
|
|
925
|
+
return `<ul>${listString}</ul>`;
|
|
926
|
+
}
|
|
919
927
|
/**
|
|
920
928
|
* Renders note elements from a FHIR resource in a standardized format
|
|
921
929
|
* Can render as simple comma-separated text or as styled HTML with timestamps
|
|
@@ -1403,6 +1411,60 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1403
1411
|
generateNarrative(resources, timezone) {
|
|
1404
1412
|
return _PatientTemplate.generateStaticNarrative(resources, timezone);
|
|
1405
1413
|
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Generate HTML narrative for Patient resources using summary
|
|
1416
|
+
* @param resources - FHIR Composition resources
|
|
1417
|
+
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
1418
|
+
* @returns HTML string for rendering
|
|
1419
|
+
*/
|
|
1420
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1421
|
+
generateSummaryNarrative(resources, timezone) {
|
|
1422
|
+
const templateUtilities = new TemplateUtilities(resources);
|
|
1423
|
+
const compositionResources = resources[0];
|
|
1424
|
+
const data = {};
|
|
1425
|
+
for (const rowData of compositionResources.section ?? []) {
|
|
1426
|
+
for (const columnData of rowData.section ?? []) {
|
|
1427
|
+
switch (columnData.title) {
|
|
1428
|
+
case "Name":
|
|
1429
|
+
case "Address":
|
|
1430
|
+
case "Communication":
|
|
1431
|
+
data[columnData.title] = templateUtilities.renderListSectionData(columnData.section ?? []);
|
|
1432
|
+
break;
|
|
1433
|
+
case "Telecom": {
|
|
1434
|
+
const telecomStringParts = [];
|
|
1435
|
+
for (const telecomData of columnData.section ?? []) {
|
|
1436
|
+
const telecomSystem = telecomData?.title;
|
|
1437
|
+
const telecomValue = templateUtilities.renderListSectionData(telecomData.section ?? []);
|
|
1438
|
+
if (telecomSystem && telecomValue) {
|
|
1439
|
+
telecomStringParts.push(`<li><strong>${telecomSystem}:</strong>${telecomValue}</li>`);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
data["Telecom"] = `<ul>${telecomStringParts.join("")}</ul>`;
|
|
1443
|
+
break;
|
|
1444
|
+
}
|
|
1445
|
+
default:
|
|
1446
|
+
if (columnData.title) {
|
|
1447
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1448
|
+
}
|
|
1449
|
+
break;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
let html = `<p>This section merges all Patient resources into a single combined patient record, preferring non-empty values for each field.</p>`;
|
|
1454
|
+
html += `<div>
|
|
1455
|
+
<ul>
|
|
1456
|
+
<li><strong>Name(s):</strong>${data["Name"] || ""}</li>
|
|
1457
|
+
<li><strong>Gender:</strong>${data["Gender"] || ""}</li>
|
|
1458
|
+
<li><strong>Date of Birth:</strong>${data["Date of Birth"] || ""}</li>
|
|
1459
|
+
<li><strong>Telecom:</strong>${data["Telecom"] || ""}</li>
|
|
1460
|
+
<li><strong>Address(es):</strong>${data["Address"] || ""}</li>
|
|
1461
|
+
${data["Marital Status"] ? `<li><strong>Marital Status:</strong>${data["Marital Status"]}</li>` : ""}
|
|
1462
|
+
${data["Deceased"] ? `<li><strong>Deceased:</strong>${data["Deceased"]}</li>` : ""}
|
|
1463
|
+
<li><strong>Language(s):</strong>${data["Communication"] || ""}</li>
|
|
1464
|
+
</ul>
|
|
1465
|
+
</div>`;
|
|
1466
|
+
return html;
|
|
1467
|
+
}
|
|
1406
1468
|
/**
|
|
1407
1469
|
* Internal static implementation that actually generates the narrative
|
|
1408
1470
|
* @param resources - FHIR Patient resources
|
|
@@ -1413,6 +1475,7 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1413
1475
|
static generateStaticNarrative(resources, timezone) {
|
|
1414
1476
|
const templateUtilities = new TemplateUtilities(resources);
|
|
1415
1477
|
const combinedPatient = this.combinePatients(resources);
|
|
1478
|
+
const deceasedText = this.renderDeceased(combinedPatient);
|
|
1416
1479
|
let html = `<p>This section merges all Patient resources into a single combined patient record, preferring non-empty values for each field.</p>`;
|
|
1417
1480
|
html += `<div>
|
|
1418
1481
|
<ul>
|
|
@@ -1421,8 +1484,8 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1421
1484
|
<li><strong>Date of Birth:</strong>${combinedPatient.birthDate || ""}</li>
|
|
1422
1485
|
<li><strong>Telecom:</strong><ul>${this.renderTelecom(combinedPatient)}</ul></li>
|
|
1423
1486
|
<li><strong>Address(es):</strong>${this.renderAddresses(combinedPatient)}</li>
|
|
1424
|
-
|
|
1425
|
-
|
|
1487
|
+
${combinedPatient.maritalStatus?.text ? `<li><strong>Marital Status:</strong> ${combinedPatient.maritalStatus.text}</li>` : ""}
|
|
1488
|
+
${deceasedText ? `<li><strong>Deceased:</strong>${deceasedText}</li>` : ""}
|
|
1426
1489
|
<li><strong>Language(s):</strong>${this.renderCommunication(templateUtilities, combinedPatient)}</li>
|
|
1427
1490
|
</ul>
|
|
1428
1491
|
</div>`;
|
|
@@ -1496,7 +1559,8 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1496
1559
|
}
|
|
1497
1560
|
}
|
|
1498
1561
|
});
|
|
1499
|
-
|
|
1562
|
+
const namesHtml = Array.from(uniqueNames).map((nameText) => `<li>${nameText}</li>`).join("");
|
|
1563
|
+
return `<ul>${namesHtml}</ul>`;
|
|
1500
1564
|
}
|
|
1501
1565
|
/**
|
|
1502
1566
|
* Renders patient telecom information grouped by system
|
|
@@ -1600,7 +1664,8 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1600
1664
|
}
|
|
1601
1665
|
});
|
|
1602
1666
|
const deduplicatedAddresses = this.deduplicateSimilarAddresses(Array.from(uniqueAddresses));
|
|
1603
|
-
|
|
1667
|
+
const addressesHtml = deduplicatedAddresses.map((addressText) => `<li>${addressText}</li>`).join("");
|
|
1668
|
+
return `<ul>${addressesHtml}</ul>`;
|
|
1604
1669
|
}
|
|
1605
1670
|
/**
|
|
1606
1671
|
* Calculates the similarity between two strings using Levenshtein distance
|
|
@@ -1718,7 +1783,8 @@ var PatientTemplate = class _PatientTemplate {
|
|
|
1718
1783
|
uniqueLanguages.add(language);
|
|
1719
1784
|
}
|
|
1720
1785
|
});
|
|
1721
|
-
|
|
1786
|
+
const languagesHtml = Array.from(uniqueLanguages).map((language) => `<li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li>`).join("");
|
|
1787
|
+
return `<ul>${languagesHtml}</ul>`;
|
|
1722
1788
|
}
|
|
1723
1789
|
/**
|
|
1724
1790
|
* Capitalizes first letter of a string
|
|
@@ -1762,7 +1828,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1762
1828
|
<th>Code (System)</th>
|
|
1763
1829
|
<th>Criticality</th>
|
|
1764
1830
|
<th>Recorded Date</th>
|
|
1765
|
-
<th>Source</th>
|
|
1766
1831
|
</tr>
|
|
1767
1832
|
</thead>
|
|
1768
1833
|
<tbody>`;
|
|
@@ -1782,13 +1847,13 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1782
1847
|
case "Recorded Date":
|
|
1783
1848
|
data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1784
1849
|
break;
|
|
1785
|
-
case "Source":
|
|
1786
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
1787
|
-
break;
|
|
1788
1850
|
default:
|
|
1789
1851
|
break;
|
|
1790
1852
|
}
|
|
1791
1853
|
}
|
|
1854
|
+
if (data["allergen"]?.toLowerCase() === "unknown") {
|
|
1855
|
+
continue;
|
|
1856
|
+
}
|
|
1792
1857
|
isSummaryCreated = true;
|
|
1793
1858
|
html += `
|
|
1794
1859
|
<tr>
|
|
@@ -1796,7 +1861,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1796
1861
|
<td>${data["codeSystem"] ?? ""}</td>
|
|
1797
1862
|
<td>${data["criticality"] ?? ""}</td>
|
|
1798
1863
|
<td>${templateUtilities.renderTime(data["recordedDate"], timezone) ?? ""}</td>
|
|
1799
|
-
<td>${data["source"] ?? ""}</td>
|
|
1800
1864
|
</tr>`;
|
|
1801
1865
|
}
|
|
1802
1866
|
}
|
|
@@ -1850,7 +1914,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1850
1914
|
<th>Reaction</th>
|
|
1851
1915
|
<th>Onset Date</th>
|
|
1852
1916
|
<th>Comments</th>
|
|
1853
|
-
<th>Source</th>
|
|
1854
1917
|
</tr>
|
|
1855
1918
|
</thead>
|
|
1856
1919
|
<tbody>`;
|
|
@@ -1880,7 +1943,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1880
1943
|
<th>Onset Date</th>
|
|
1881
1944
|
<th>Comments</th>
|
|
1882
1945
|
<th>Resolved Date</th>
|
|
1883
|
-
<th>Source</th>
|
|
1884
1946
|
</tr>
|
|
1885
1947
|
</thead>
|
|
1886
1948
|
<tbody>`;
|
|
@@ -1909,16 +1971,19 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
|
|
|
1909
1971
|
static generateAllergyRows(allergies, templateUtilities, timezone, includeResolved = false) {
|
|
1910
1972
|
let html = "";
|
|
1911
1973
|
for (const allergy of allergies) {
|
|
1974
|
+
const allergenName = templateUtilities.codeableConceptDisplay(allergy.code);
|
|
1975
|
+
if (allergenName?.toLowerCase() === "unknown") {
|
|
1976
|
+
continue;
|
|
1977
|
+
}
|
|
1912
1978
|
html += `
|
|
1913
1979
|
<tr>
|
|
1914
|
-
<td class="Name"><span class="AllergenName">${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(
|
|
1980
|
+
<td class="Name"><span class="AllergenName">${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(allergenName))}</span></td>
|
|
1915
1981
|
<td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(allergy.clinicalStatus)) || ""}</td>
|
|
1916
1982
|
<td class="CodeSystem">${templateUtilities.codeableConceptCoding(allergy.code)}</td>
|
|
1917
1983
|
<td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || ""}</td>
|
|
1918
1984
|
<td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || ""}</td>
|
|
1919
1985
|
<td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || ""}</td>
|
|
1920
|
-
<td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td
|
|
1921
|
-
<td class="Source">${templateUtilities.getOwnerTag(allergy)}</td>`;
|
|
1986
|
+
<td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
|
|
1922
1987
|
if (includeResolved) {
|
|
1923
1988
|
let endDate = "";
|
|
1924
1989
|
if (allergy.extension && Array.isArray(allergy.extension)) {
|
|
@@ -1973,9 +2038,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
1973
2038
|
<th>Status</th>
|
|
1974
2039
|
<th>Sig</th>
|
|
1975
2040
|
<th>Days of Supply</th>
|
|
1976
|
-
<th>Refills</th>
|
|
1977
2041
|
<th>Start Date</th>
|
|
1978
|
-
<th>Source</th>
|
|
1979
2042
|
</tr>
|
|
1980
2043
|
</thead>
|
|
1981
2044
|
<tbody>`;
|
|
@@ -2001,15 +2064,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2001
2064
|
case "Days Of Supply":
|
|
2002
2065
|
data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2003
2066
|
break;
|
|
2004
|
-
case "Refills Remaining":
|
|
2005
|
-
data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2006
|
-
break;
|
|
2007
2067
|
case "Authored On Date":
|
|
2008
2068
|
data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2009
2069
|
break;
|
|
2010
|
-
case "Source":
|
|
2011
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2012
|
-
break;
|
|
2013
2070
|
default:
|
|
2014
2071
|
break;
|
|
2015
2072
|
}
|
|
@@ -2025,6 +2082,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2025
2082
|
skippedMedications++;
|
|
2026
2083
|
}
|
|
2027
2084
|
if (data["status"] === "active" || startDateObj && startDateObj >= twoYearsAgo) {
|
|
2085
|
+
if (data["medication"]?.toLowerCase() === "unknown") {
|
|
2086
|
+
continue;
|
|
2087
|
+
}
|
|
2028
2088
|
isSummaryCreated = true;
|
|
2029
2089
|
html += `
|
|
2030
2090
|
<tr>
|
|
@@ -2033,9 +2093,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2033
2093
|
<td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
|
|
2034
2094
|
<td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
|
|
2035
2095
|
<td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
|
|
2036
|
-
<td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
|
|
2037
2096
|
<td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
|
|
2038
|
-
<td>${templateUtilities.renderTextAsHtml(data["source"])}</td>
|
|
2039
2097
|
</tr>`;
|
|
2040
2098
|
}
|
|
2041
2099
|
}
|
|
@@ -2160,9 +2218,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2160
2218
|
<th>Code (System)</th>
|
|
2161
2219
|
<th>Sig</th>
|
|
2162
2220
|
<th>Dispense Quantity</th>
|
|
2163
|
-
<th>Refills</th>
|
|
2164
2221
|
<th>Start Date</th>
|
|
2165
|
-
<th>Source</th>
|
|
2166
2222
|
</tr>
|
|
2167
2223
|
</thead>
|
|
2168
2224
|
<tbody>`;
|
|
@@ -2171,7 +2227,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2171
2227
|
let medicationName;
|
|
2172
2228
|
let sig;
|
|
2173
2229
|
let dispenseQuantity = "";
|
|
2174
|
-
let refills = "";
|
|
2175
2230
|
let startDate = "";
|
|
2176
2231
|
let codeSystemDisplay = "";
|
|
2177
2232
|
if (medication.type === "request") {
|
|
@@ -2187,7 +2242,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2187
2242
|
dispenseQuantity = `${quantity.value} ${quantity.unit || quantity.code || ""}`.trim();
|
|
2188
2243
|
}
|
|
2189
2244
|
}
|
|
2190
|
-
refills = mr.dispenseRequest?.numberOfRepeatsAllowed?.toString() || "";
|
|
2191
2245
|
if (mr.dispenseRequest?.validityPeriod) {
|
|
2192
2246
|
startDate = mr.dispenseRequest.validityPeriod.start || "";
|
|
2193
2247
|
} else {
|
|
@@ -2212,6 +2266,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2212
2266
|
codeSystemDisplay = templateUtilities.codeableConceptCoding(ms.medicationCodeableConcept);
|
|
2213
2267
|
}
|
|
2214
2268
|
}
|
|
2269
|
+
if (medicationName?.toLowerCase() === "unknown") {
|
|
2270
|
+
continue;
|
|
2271
|
+
}
|
|
2215
2272
|
html += `
|
|
2216
2273
|
<tr>
|
|
2217
2274
|
<td>${type}</td>
|
|
@@ -2219,9 +2276,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
|
|
|
2219
2276
|
<td>${codeSystemDisplay}</td>
|
|
2220
2277
|
<td>${sig}</td>
|
|
2221
2278
|
<td>${dispenseQuantity}</td>
|
|
2222
|
-
<td>${refills}</td>
|
|
2223
2279
|
<td>${startDate}</td>
|
|
2224
|
-
<td>${templateUtilities.getOwnerTag(medication.resource)}</td>
|
|
2225
2280
|
</tr>`;
|
|
2226
2281
|
}
|
|
2227
2282
|
html += `
|
|
@@ -2266,7 +2321,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2266
2321
|
<th>Code (System)</th>
|
|
2267
2322
|
<th>Status</th>
|
|
2268
2323
|
<th>Date</th>
|
|
2269
|
-
<th>Source</th>
|
|
2270
2324
|
</tr>
|
|
2271
2325
|
</thead>
|
|
2272
2326
|
<tbody>`;
|
|
@@ -2286,14 +2340,14 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2286
2340
|
case "occurrenceDateTime":
|
|
2287
2341
|
data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2288
2342
|
break;
|
|
2289
|
-
case "Source":
|
|
2290
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2291
|
-
break;
|
|
2292
2343
|
default:
|
|
2293
2344
|
break;
|
|
2294
2345
|
}
|
|
2295
2346
|
}
|
|
2296
2347
|
if (data["status"] === "completed") {
|
|
2348
|
+
if (data["immunization"]?.toLowerCase() === "unknown") {
|
|
2349
|
+
continue;
|
|
2350
|
+
}
|
|
2297
2351
|
isSummaryCreated = true;
|
|
2298
2352
|
html += `
|
|
2299
2353
|
<tr>
|
|
@@ -2301,7 +2355,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2301
2355
|
<td>${data["codeSystem"] ?? ""}</td>
|
|
2302
2356
|
<td>${data["status"] ?? ""}</td>
|
|
2303
2357
|
<td>${templateUtilities.renderTime(data["occurrenceDateTime"], timezone) ?? ""}</td>
|
|
2304
|
-
<td>${data["source"] ?? ""}</td>
|
|
2305
2358
|
</tr>`;
|
|
2306
2359
|
}
|
|
2307
2360
|
}
|
|
@@ -2332,7 +2385,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2332
2385
|
<th>Lot Number</th>
|
|
2333
2386
|
<th>Comments</th>
|
|
2334
2387
|
<th>Date</th>
|
|
2335
|
-
<th>Source</th>
|
|
2336
2388
|
</tr>
|
|
2337
2389
|
</thead>
|
|
2338
2390
|
<tbody>`;
|
|
@@ -2340,9 +2392,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2340
2392
|
if (immunizations.length > 0) {
|
|
2341
2393
|
for (const resourceItem of immunizations) {
|
|
2342
2394
|
const imm = resourceItem;
|
|
2395
|
+
const immunizationName = templateUtilities.codeableConceptDisplay(imm.vaccineCode);
|
|
2396
|
+
if (immunizationName?.toLowerCase() === "unknown") {
|
|
2397
|
+
continue;
|
|
2398
|
+
}
|
|
2343
2399
|
html += `
|
|
2344
2400
|
<tr>
|
|
2345
|
-
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(
|
|
2401
|
+
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(immunizationName))}</td>
|
|
2346
2402
|
<td>${templateUtilities.codeableConceptCoding(imm.vaccineCode)}</td>
|
|
2347
2403
|
<td>${imm.status || ""}</td>
|
|
2348
2404
|
<td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
|
|
@@ -2350,7 +2406,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
|
|
|
2350
2406
|
<td>${imm.lotNumber || ""}</td>
|
|
2351
2407
|
<td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
|
|
2352
2408
|
<td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
|
|
2353
|
-
<td>${templateUtilities.getOwnerTag(imm)}</td>
|
|
2354
2409
|
</tr>`;
|
|
2355
2410
|
}
|
|
2356
2411
|
}
|
|
@@ -2372,6 +2427,59 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2372
2427
|
generateNarrative(resources, timezone) {
|
|
2373
2428
|
return _ProblemListTemplate.generateStaticNarrative(resources, timezone);
|
|
2374
2429
|
}
|
|
2430
|
+
/**
|
|
2431
|
+
* Generate HTML narrative for Condition resources using summary
|
|
2432
|
+
* @param resources - FHIR Composition resources
|
|
2433
|
+
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
2434
|
+
* @returns HTML string for rendering
|
|
2435
|
+
*/
|
|
2436
|
+
generateSummaryNarrative(resources, timezone) {
|
|
2437
|
+
const templateUtilities = new TemplateUtilities(resources);
|
|
2438
|
+
let isSummaryCreated = false;
|
|
2439
|
+
let html = `<p>This list includes patient problems, sorted by recorded date (most recent first)</p>
|
|
2440
|
+
<div>
|
|
2441
|
+
<table>
|
|
2442
|
+
<thead>
|
|
2443
|
+
<tr>
|
|
2444
|
+
<th>Problem</th>
|
|
2445
|
+
<th>Code (System)</th>
|
|
2446
|
+
<th>Is Chronic</th>
|
|
2447
|
+
<th>Onset Date</th>
|
|
2448
|
+
<th>Last Confirmed Date</th>
|
|
2449
|
+
</tr>
|
|
2450
|
+
</thead>
|
|
2451
|
+
<tbody>`;
|
|
2452
|
+
for (const resourceItem of resources) {
|
|
2453
|
+
for (const rowData of resourceItem.section ?? []) {
|
|
2454
|
+
const sectionCodeableConcept = rowData.code;
|
|
2455
|
+
const data = {};
|
|
2456
|
+
for (const columnData of rowData.section ?? []) {
|
|
2457
|
+
if (columnData.title) {
|
|
2458
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
if (data["Condition Name"]?.toLowerCase() === "unknown") {
|
|
2462
|
+
continue;
|
|
2463
|
+
}
|
|
2464
|
+
if (data["Status"] === "active") {
|
|
2465
|
+
isSummaryCreated = true;
|
|
2466
|
+
html += `
|
|
2467
|
+
<tr>
|
|
2468
|
+
<td>${templateUtilities.capitalizeFirstLetter(data["Condition Name"] ?? "")}</td>
|
|
2469
|
+
<td>${templateUtilities.codeableConceptCoding(sectionCodeableConcept)}</td>
|
|
2470
|
+
<td>${data["Is Chronic"] ?? ""}</td>
|
|
2471
|
+
<td>${templateUtilities.renderTime(data["Onset Date"], timezone) ?? ""}</td>
|
|
2472
|
+
<td>${templateUtilities.renderTime(data["Last Confirmed Date"], timezone) ?? ""}</td>
|
|
2473
|
+
</tr>`;
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
html += `
|
|
2478
|
+
</tbody>
|
|
2479
|
+
</table>
|
|
2480
|
+
</div>`;
|
|
2481
|
+
return isSummaryCreated ? html : void 0;
|
|
2482
|
+
}
|
|
2375
2483
|
/**
|
|
2376
2484
|
* Internal static implementation that actually generates the narrative
|
|
2377
2485
|
* @param resources - FHIR Condition resources
|
|
@@ -2400,7 +2508,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2400
2508
|
<th>Code (System)</th>
|
|
2401
2509
|
<th>Onset Date</th>
|
|
2402
2510
|
<th>Recorded Date</th>
|
|
2403
|
-
<th>Source</th>
|
|
2404
2511
|
</tr>
|
|
2405
2512
|
</thead>
|
|
2406
2513
|
<tbody>`;
|
|
@@ -2411,13 +2518,15 @@ var ProblemListTemplate = class _ProblemListTemplate {
|
|
|
2411
2518
|
if (codeAndSystem && seenCodeAndSystems.has(codeAndSystem)) {
|
|
2412
2519
|
continue;
|
|
2413
2520
|
}
|
|
2521
|
+
if (conditionDisplay?.toLowerCase() === "unknown") {
|
|
2522
|
+
continue;
|
|
2523
|
+
}
|
|
2414
2524
|
seenCodeAndSystems.add(codeAndSystem);
|
|
2415
2525
|
html += `<tr>
|
|
2416
2526
|
<td class="Name">${templateUtilities.capitalizeFirstLetter(conditionDisplay)}</td>
|
|
2417
2527
|
<td class="CodeSystem">${codeAndSystem}</td>
|
|
2418
2528
|
<td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
|
|
2419
2529
|
<td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
|
|
2420
|
-
<td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
|
|
2421
2530
|
</tr>`;
|
|
2422
2531
|
}
|
|
2423
2532
|
html += `</tbody>
|
|
@@ -2457,7 +2566,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2457
2566
|
<th>Code (System)</th>
|
|
2458
2567
|
<th>Result</th>
|
|
2459
2568
|
<th>Date</th>
|
|
2460
|
-
<th>Source</th>
|
|
2461
2569
|
</tr>
|
|
2462
2570
|
</thead>
|
|
2463
2571
|
<tbody>`;
|
|
@@ -2490,6 +2598,9 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2490
2598
|
data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
2491
2599
|
}
|
|
2492
2600
|
}
|
|
2601
|
+
if (data["Vital Name"]?.toLowerCase() === "unknown") {
|
|
2602
|
+
continue;
|
|
2603
|
+
}
|
|
2493
2604
|
isSummaryCreated = true;
|
|
2494
2605
|
html += `
|
|
2495
2606
|
<tr>
|
|
@@ -2497,7 +2608,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2497
2608
|
<td>${data["codeSystem"] ?? ""}</td>
|
|
2498
2609
|
<td>${templateUtilities.extractObservationSummaryValue(data, timezone) ?? ""}</td>
|
|
2499
2610
|
<td>${templateUtilities.extractObservationSummaryEffectiveTime(data, timezone) ?? ""}</td>
|
|
2500
|
-
<td>${data["Source"] ?? ""}</td>
|
|
2501
2611
|
</tr>`;
|
|
2502
2612
|
}
|
|
2503
2613
|
}
|
|
@@ -2535,14 +2645,17 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2535
2645
|
<th>Component(s)</th>
|
|
2536
2646
|
<th>Comments</th>
|
|
2537
2647
|
<th>Date</th>
|
|
2538
|
-
<th>Source</th>
|
|
2539
2648
|
</tr>
|
|
2540
2649
|
</thead>
|
|
2541
2650
|
<tbody>`;
|
|
2542
2651
|
for (const obs of observations) {
|
|
2652
|
+
const vitalName = templateUtilities.codeableConceptDisplay(obs.code, "display");
|
|
2653
|
+
if (vitalName?.toLowerCase() === "unknown") {
|
|
2654
|
+
continue;
|
|
2655
|
+
}
|
|
2543
2656
|
html += `
|
|
2544
2657
|
<tr>
|
|
2545
|
-
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(
|
|
2658
|
+
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(vitalName))}</td>
|
|
2546
2659
|
<td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
|
|
2547
2660
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
2548
2661
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
@@ -2550,7 +2663,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
|
|
|
2550
2663
|
<td>${templateUtilities.renderComponent(obs.component)}</td>
|
|
2551
2664
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
2552
2665
|
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
2553
|
-
<td>${templateUtilities.getOwnerTag(obs)}</td>
|
|
2554
2666
|
</tr>`;
|
|
2555
2667
|
}
|
|
2556
2668
|
html += `
|
|
@@ -2597,10 +2709,14 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
|
|
|
2597
2709
|
});
|
|
2598
2710
|
let isDeviceAdded = false;
|
|
2599
2711
|
for (const dus of deviceStatements) {
|
|
2712
|
+
const deviceName = templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device));
|
|
2713
|
+
if (deviceName?.toLowerCase() === "unknown") {
|
|
2714
|
+
continue;
|
|
2715
|
+
}
|
|
2600
2716
|
isDeviceAdded = true;
|
|
2601
2717
|
html += `
|
|
2602
2718
|
<tr>
|
|
2603
|
-
<td>${templateUtilities.capitalizeFirstLetter(
|
|
2719
|
+
<td>${templateUtilities.capitalizeFirstLetter(deviceName)}</td>
|
|
2604
2720
|
<td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
|
|
2605
2721
|
<td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
|
|
2606
2722
|
<td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
|
|
@@ -2974,7 +3090,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2974
3090
|
<th>Result</th>
|
|
2975
3091
|
<th>Reference Range</th>
|
|
2976
3092
|
<th>Date</th>
|
|
2977
|
-
<th>Source</th>
|
|
2978
3093
|
</tr>
|
|
2979
3094
|
</thead>
|
|
2980
3095
|
<tbody>`;
|
|
@@ -2988,7 +3103,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
2988
3103
|
<th>Report</th>
|
|
2989
3104
|
<th>Performer</th>
|
|
2990
3105
|
<th>Issued</th>
|
|
2991
|
-
<th>Source</th>
|
|
2992
3106
|
</tr>
|
|
2993
3107
|
</thead>
|
|
2994
3108
|
<tbody>`;
|
|
@@ -3035,8 +3149,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3035
3149
|
case "Status":
|
|
3036
3150
|
data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3037
3151
|
break;
|
|
3038
|
-
case "Source":
|
|
3039
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3040
3152
|
break;
|
|
3041
3153
|
default:
|
|
3042
3154
|
break;
|
|
@@ -3062,6 +3174,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3062
3174
|
for (const component of components) {
|
|
3063
3175
|
const componentCode = `${groupName}${component["code"] ?? ""}`;
|
|
3064
3176
|
if (componentCode && !observationAdded.has(componentCode)) {
|
|
3177
|
+
if (component["code"]?.toLowerCase() === "unknown") {
|
|
3178
|
+
continue;
|
|
3179
|
+
}
|
|
3065
3180
|
observationAdded.add(componentCode);
|
|
3066
3181
|
this.formatSummaryObservationData(component);
|
|
3067
3182
|
observationhtml += `
|
|
@@ -3071,7 +3186,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3071
3186
|
<td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? ""}</td>
|
|
3072
3187
|
<td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? ""}</td>
|
|
3073
3188
|
<td>${date ?? ""}</td>
|
|
3074
|
-
<td>${data["source"] ?? ""}</td>
|
|
3075
3189
|
</tr>`;
|
|
3076
3190
|
}
|
|
3077
3191
|
}
|
|
@@ -3079,6 +3193,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3079
3193
|
if (obsDate && obsDate >= twoYearsAgo) {
|
|
3080
3194
|
const code = data["code"] ?? "";
|
|
3081
3195
|
if (code && !observationAdded.has(code)) {
|
|
3196
|
+
if (code.toLowerCase() === "unknown") {
|
|
3197
|
+
continue;
|
|
3198
|
+
}
|
|
3082
3199
|
observationAdded.add(code);
|
|
3083
3200
|
this.formatSummaryObservationData(data);
|
|
3084
3201
|
observationhtml += `
|
|
@@ -3088,7 +3205,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3088
3205
|
<td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? ""}</td>
|
|
3089
3206
|
<td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? ""}</td>
|
|
3090
3207
|
<td>${date ?? ""}</td>
|
|
3091
|
-
<td>${data["source"] ?? ""}</td>
|
|
3092
3208
|
</tr>`;
|
|
3093
3209
|
}
|
|
3094
3210
|
}
|
|
@@ -3101,13 +3217,15 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3101
3217
|
if (data["status"] === "final" && issuedDate && issuedDate >= twoYearsAgo) {
|
|
3102
3218
|
const reportName = data["report"] ?? "";
|
|
3103
3219
|
if (reportName && !diagnosticReportAdded.has(reportName)) {
|
|
3220
|
+
if (reportName.toLowerCase() === "unknown") {
|
|
3221
|
+
continue;
|
|
3222
|
+
}
|
|
3104
3223
|
diagnosticReportAdded.add(reportName);
|
|
3105
3224
|
diagnosticReporthtml += `
|
|
3106
3225
|
<tr>
|
|
3107
3226
|
<td>${templateUtilities.capitalizeFirstLetter(data["report"] ?? "")}</td>
|
|
3108
3227
|
<td>${data["performer"] ?? ""}</td>
|
|
3109
3228
|
<td>${templateUtilities.renderTime(data["issued"], timezone) ?? ""}</td>
|
|
3110
|
-
<td>${data["source"] ?? ""}</td>
|
|
3111
3229
|
</tr>`;
|
|
3112
3230
|
}
|
|
3113
3231
|
}
|
|
@@ -3292,7 +3410,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3292
3410
|
<th>Result</th>
|
|
3293
3411
|
<th>Reference Range</th>
|
|
3294
3412
|
<th>Date</th>
|
|
3295
|
-
<th>Source</th>
|
|
3296
3413
|
</tr>
|
|
3297
3414
|
</thead>
|
|
3298
3415
|
<tbody>`;
|
|
@@ -3301,6 +3418,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3301
3418
|
const obsCodeDisplay = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
|
|
3302
3419
|
const obsCodeAndSystem = templateUtilities.codeableConceptCoding(obs.code);
|
|
3303
3420
|
if (!observationAdded.has(obsCodeDisplay) && !observationAdded.has(obsCodeAndSystem)) {
|
|
3421
|
+
if (obsCodeDisplay?.toLowerCase() === "unknown") {
|
|
3422
|
+
continue;
|
|
3423
|
+
}
|
|
3304
3424
|
observationAdded.add(obsCodeDisplay);
|
|
3305
3425
|
observationAdded.add(obsCodeAndSystem);
|
|
3306
3426
|
html += `
|
|
@@ -3310,7 +3430,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3310
3430
|
<td>${templateUtilities.extractObservationValue(obs)}</td>
|
|
3311
3431
|
<td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
|
|
3312
3432
|
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
3313
|
-
<td>${templateUtilities.getOwnerTag(obs)}</td>
|
|
3314
3433
|
</tr>`;
|
|
3315
3434
|
}
|
|
3316
3435
|
}
|
|
@@ -3337,7 +3456,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3337
3456
|
<th>Category</th>
|
|
3338
3457
|
<th>Result</th>
|
|
3339
3458
|
<th>Issued</th>
|
|
3340
|
-
<th>Source</th>
|
|
3341
3459
|
</tr>
|
|
3342
3460
|
</thead>
|
|
3343
3461
|
<tbody>`;
|
|
@@ -3346,6 +3464,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3346
3464
|
const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(report.code));
|
|
3347
3465
|
const codeAndSystem = templateUtilities.codeableConceptCoding(report.code);
|
|
3348
3466
|
if (!diagnosticReportAdded.has(reportName) && !diagnosticReportAdded.has(codeAndSystem)) {
|
|
3467
|
+
if (reportName?.toLowerCase() === "unknown") {
|
|
3468
|
+
continue;
|
|
3469
|
+
}
|
|
3349
3470
|
diagnosticReportAdded.add(reportName);
|
|
3350
3471
|
diagnosticReportAdded.add(codeAndSystem);
|
|
3351
3472
|
let resultCount = "";
|
|
@@ -3359,7 +3480,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
|
|
|
3359
3480
|
<td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
|
|
3360
3481
|
<td>${resultCount}</td>
|
|
3361
3482
|
<td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
|
|
3362
|
-
<td>${templateUtilities.getOwnerTag(report)}</td>
|
|
3363
3483
|
</tr>`;
|
|
3364
3484
|
}
|
|
3365
3485
|
}
|
|
@@ -3426,7 +3546,6 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3426
3546
|
<th>Code (System)</th>
|
|
3427
3547
|
<th>Performer</th>
|
|
3428
3548
|
<th>Date</th>
|
|
3429
|
-
<th>Source</th>
|
|
3430
3549
|
</tr>
|
|
3431
3550
|
</thead>
|
|
3432
3551
|
<tbody>`;
|
|
@@ -3446,13 +3565,14 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3446
3565
|
case "Performed Date":
|
|
3447
3566
|
data["date"] = columnData.text?.div ?? "";
|
|
3448
3567
|
break;
|
|
3449
|
-
case "Source":
|
|
3450
|
-
data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3451
3568
|
break;
|
|
3452
3569
|
default:
|
|
3453
3570
|
break;
|
|
3454
3571
|
}
|
|
3455
3572
|
}
|
|
3573
|
+
if (data["procedure"]?.toLowerCase() === "unknown") {
|
|
3574
|
+
continue;
|
|
3575
|
+
}
|
|
3456
3576
|
isSummaryCreated = true;
|
|
3457
3577
|
html += `
|
|
3458
3578
|
<tr>
|
|
@@ -3460,7 +3580,6 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3460
3580
|
<td>${data["codeSystem"] ?? ""}</td>
|
|
3461
3581
|
<td>${data["performer"] ?? ""}</td>
|
|
3462
3582
|
<td>${templateUtilities.renderTime(data["date"], timezone) ?? ""}</td>
|
|
3463
|
-
<td>${data["source"] ?? ""}</td>
|
|
3464
3583
|
</tr>`;
|
|
3465
3584
|
}
|
|
3466
3585
|
}
|
|
@@ -3488,19 +3607,21 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
|
|
|
3488
3607
|
<th>Code (System)</th>
|
|
3489
3608
|
<th>Comments</th>
|
|
3490
3609
|
<th>Date</th>
|
|
3491
|
-
<th>Source</th>
|
|
3492
3610
|
</tr>
|
|
3493
3611
|
</thead>
|
|
3494
3612
|
<tbody>`;
|
|
3495
3613
|
for (const resourceItem of resources) {
|
|
3496
3614
|
const proc = resourceItem;
|
|
3615
|
+
const procedureName = templateUtilities.codeableConceptDisplay(proc.code, "display");
|
|
3616
|
+
if (procedureName?.toLowerCase() === "unknown") {
|
|
3617
|
+
continue;
|
|
3618
|
+
}
|
|
3497
3619
|
html += `
|
|
3498
3620
|
<tr>
|
|
3499
|
-
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(
|
|
3621
|
+
<td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(procedureName))}</td>
|
|
3500
3622
|
<td>${templateUtilities.codeableConceptCoding(proc.code)}</td>
|
|
3501
3623
|
<td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
|
|
3502
3624
|
<td>${templateUtilities.renderTime(proc.performedDateTime || proc.performedPeriod?.start, timezone)}</td>
|
|
3503
|
-
<td>${templateUtilities.getOwnerTag(proc)}</td>
|
|
3504
3625
|
</tr>`;
|
|
3505
3626
|
}
|
|
3506
3627
|
html += `
|
|
@@ -3547,7 +3668,6 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3547
3668
|
<th>Unit</th>
|
|
3548
3669
|
<th>Comments</th>
|
|
3549
3670
|
<th>Date</th>
|
|
3550
|
-
<th>Source</th>
|
|
3551
3671
|
</tr>
|
|
3552
3672
|
</thead>
|
|
3553
3673
|
<tbody>`;
|
|
@@ -3555,6 +3675,9 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3555
3675
|
for (const obs of observations) {
|
|
3556
3676
|
const obsName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
|
|
3557
3677
|
if (!addedObservations.has(obsName)) {
|
|
3678
|
+
if (obsName?.toLowerCase() === "unknown") {
|
|
3679
|
+
continue;
|
|
3680
|
+
}
|
|
3558
3681
|
addedObservations.add(obsName);
|
|
3559
3682
|
html += `
|
|
3560
3683
|
<tr>
|
|
@@ -3564,7 +3687,6 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
|
|
|
3564
3687
|
<td>${templateUtilities.extractObservationValueUnit(obs)}</td>
|
|
3565
3688
|
<td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
|
|
3566
3689
|
<td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
|
|
3567
|
-
<td>${templateUtilities.getOwnerTag(obs)}</td>
|
|
3568
3690
|
</tr>`;
|
|
3569
3691
|
}
|
|
3570
3692
|
}
|
|
@@ -3615,7 +3737,6 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3615
3737
|
<th>Onset Date</th>
|
|
3616
3738
|
<th>Recorded Date</th>
|
|
3617
3739
|
<th>Resolved Date</th>
|
|
3618
|
-
<th>Source</th>
|
|
3619
3740
|
</tr>
|
|
3620
3741
|
</thead>
|
|
3621
3742
|
<tbody>`;
|
|
@@ -3623,6 +3744,9 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3623
3744
|
for (const cond of filteredConditions) {
|
|
3624
3745
|
const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(cond.code));
|
|
3625
3746
|
if (!addedConditionCodes.has(conditionCode)) {
|
|
3747
|
+
if (conditionCode?.toLowerCase() === "unknown") {
|
|
3748
|
+
continue;
|
|
3749
|
+
}
|
|
3626
3750
|
addedConditionCodes.add(conditionCode);
|
|
3627
3751
|
html += `<tr>
|
|
3628
3752
|
<td class="Name">${templateUtilities.capitalizeFirstLetter(conditionCode)}</td>
|
|
@@ -3630,7 +3754,6 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3630
3754
|
<td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
|
|
3631
3755
|
<td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
|
|
3632
3756
|
<td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
|
|
3633
|
-
<td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
|
|
3634
3757
|
</tr>`;
|
|
3635
3758
|
}
|
|
3636
3759
|
}
|
|
@@ -3642,6 +3765,73 @@ var PastHistoryOfIllnessTemplate = class {
|
|
|
3642
3765
|
}
|
|
3643
3766
|
return html;
|
|
3644
3767
|
}
|
|
3768
|
+
/**
|
|
3769
|
+
* Generate HTML narrative for Condition resources using summary
|
|
3770
|
+
* @param resources - FHIR Composition resources
|
|
3771
|
+
* @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
|
|
3772
|
+
* @returns HTML string for rendering
|
|
3773
|
+
*/
|
|
3774
|
+
generateSummaryNarrative(resources, timezone, now) {
|
|
3775
|
+
const templateUtilities = new TemplateUtilities(resources);
|
|
3776
|
+
let isSummaryCreated = false;
|
|
3777
|
+
const currentDate = now || /* @__PURE__ */ new Date();
|
|
3778
|
+
const fiveYearsAgo = new Date(currentDate);
|
|
3779
|
+
fiveYearsAgo.setFullYear(currentDate.getFullYear() - 5);
|
|
3780
|
+
let skippedConditions = 0;
|
|
3781
|
+
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>
|
|
3782
|
+
<div>
|
|
3783
|
+
<table>
|
|
3784
|
+
<thead>
|
|
3785
|
+
<tr>
|
|
3786
|
+
<th>Problem</th>
|
|
3787
|
+
<th>Code (System)</th>
|
|
3788
|
+
<th>Is Chronic</th>
|
|
3789
|
+
<th>Onset Date</th>
|
|
3790
|
+
<th>Last Confirmed Date</th>
|
|
3791
|
+
<th>Resolved Date</th>
|
|
3792
|
+
</tr>
|
|
3793
|
+
</thead>
|
|
3794
|
+
<tbody>`;
|
|
3795
|
+
for (const resourceItem of resources) {
|
|
3796
|
+
for (const rowData of resourceItem.section ?? []) {
|
|
3797
|
+
const sectionCodeableConcept = rowData.code;
|
|
3798
|
+
const data = {};
|
|
3799
|
+
for (const columnData of rowData.section ?? []) {
|
|
3800
|
+
if (columnData.title) {
|
|
3801
|
+
data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
|
|
3802
|
+
}
|
|
3803
|
+
}
|
|
3804
|
+
if (data["Condition Name"]?.toLowerCase() === "unknown") {
|
|
3805
|
+
continue;
|
|
3806
|
+
}
|
|
3807
|
+
if (data["Status"] === "inactive") {
|
|
3808
|
+
if (data["Last Confirmed Date"] && new Date(data["Last Confirmed Date"]) < fiveYearsAgo) {
|
|
3809
|
+
skippedConditions++;
|
|
3810
|
+
continue;
|
|
3811
|
+
}
|
|
3812
|
+
isSummaryCreated = true;
|
|
3813
|
+
html += `
|
|
3814
|
+
<tr>
|
|
3815
|
+
<td>${templateUtilities.capitalizeFirstLetter(data["Condition Name"] ?? "")}</td>
|
|
3816
|
+
<td>${templateUtilities.codeableConceptCoding(sectionCodeableConcept)}</td>
|
|
3817
|
+
<td>${data["Is Chronic"] ?? ""}</td>
|
|
3818
|
+
<td>${templateUtilities.renderTime(data["Onset Date"], timezone) ?? ""}</td>
|
|
3819
|
+
<td>${templateUtilities.renderTime(data["Last Confirmed Date"], timezone) ?? ""}</td>
|
|
3820
|
+
<td>${templateUtilities.renderTime(data["Resolved Date"], timezone) ?? ""}</td>
|
|
3821
|
+
</tr>`;
|
|
3822
|
+
}
|
|
3823
|
+
}
|
|
3824
|
+
}
|
|
3825
|
+
html += `
|
|
3826
|
+
</tbody>
|
|
3827
|
+
</table>`;
|
|
3828
|
+
if (skippedConditions > 0) {
|
|
3829
|
+
html += `
|
|
3830
|
+
<p><em>${skippedConditions} additional past illnesses older than 5 years ago are present</em></p>`;
|
|
3831
|
+
}
|
|
3832
|
+
html += `</div>`;
|
|
3833
|
+
return isSummaryCreated ? html : void 0;
|
|
3834
|
+
}
|
|
3645
3835
|
};
|
|
3646
3836
|
|
|
3647
3837
|
// src/narratives/templates/typescript/PlanOfCareTemplate.ts
|
|
@@ -3671,19 +3861,21 @@ var PlanOfCareTemplate = class {
|
|
|
3671
3861
|
<th>Comments</th>
|
|
3672
3862
|
<th>Planned Start</th>
|
|
3673
3863
|
<th>Planned End</th>
|
|
3674
|
-
<th>Source</th>
|
|
3675
3864
|
</tr>
|
|
3676
3865
|
</thead>
|
|
3677
3866
|
<tbody>`;
|
|
3678
3867
|
for (const cp of carePlans) {
|
|
3868
|
+
const carePlanName = cp.description || cp.title || "";
|
|
3869
|
+
if (carePlanName.toLowerCase() === "unknown") {
|
|
3870
|
+
continue;
|
|
3871
|
+
}
|
|
3679
3872
|
html += `
|
|
3680
3873
|
<tr>
|
|
3681
|
-
<td>${templateUtilities.capitalizeFirstLetter(
|
|
3874
|
+
<td>${templateUtilities.capitalizeFirstLetter(carePlanName)}</td>
|
|
3682
3875
|
<td>${cp.intent || ""}</td>
|
|
3683
3876
|
<td>${templateUtilities.concat(cp.note, "text")}</td>
|
|
3684
3877
|
<td>${cp.period?.start ? templateUtilities.renderTime(cp.period?.start, timezone) : ""}</td>
|
|
3685
3878
|
<td>${cp.period?.end ? templateUtilities.renderTime(cp.period?.end, timezone) : ""}</td>
|
|
3686
|
-
<td>${templateUtilities.getOwnerTag(cp)}</td>
|
|
3687
3879
|
</tr>`;
|
|
3688
3880
|
}
|
|
3689
3881
|
html += `
|
|
@@ -3711,7 +3903,6 @@ var PlanOfCareTemplate = class {
|
|
|
3711
3903
|
<th>Created</th>
|
|
3712
3904
|
<th>Planned Start</th>
|
|
3713
3905
|
<th>Planned End</th>
|
|
3714
|
-
<th>Source</th>
|
|
3715
3906
|
</tr>
|
|
3716
3907
|
</thead>
|
|
3717
3908
|
<tbody>`;
|
|
@@ -3726,6 +3917,9 @@ var PlanOfCareTemplate = class {
|
|
|
3726
3917
|
if (data["status"] !== "active") {
|
|
3727
3918
|
continue;
|
|
3728
3919
|
}
|
|
3920
|
+
if (data["CarePlan Name"]?.toLowerCase() === "unknown") {
|
|
3921
|
+
continue;
|
|
3922
|
+
}
|
|
3729
3923
|
isSummaryCreated = true;
|
|
3730
3924
|
html += `
|
|
3731
3925
|
<tr>
|
|
@@ -3733,7 +3927,6 @@ var PlanOfCareTemplate = class {
|
|
|
3733
3927
|
<td>${templateUtilities.renderTime(data["created"], timezone) ?? ""}</td>
|
|
3734
3928
|
<td>${templateUtilities.renderTime(data["period.start"], timezone) ?? ""}</td>
|
|
3735
3929
|
<td>${templateUtilities.renderTime(data["period.end"], timezone) ?? ""}</td>
|
|
3736
|
-
<td>${data["source"] ?? ""}</td>
|
|
3737
3930
|
</tr>`;
|
|
3738
3931
|
}
|
|
3739
3932
|
}
|
|
@@ -3790,6 +3983,9 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
|
|
|
3790
3983
|
for (const obs of functionalObservations) {
|
|
3791
3984
|
const observation = obs;
|
|
3792
3985
|
const obsName = templateUtilities.codeableConceptDisplay(observation.code);
|
|
3986
|
+
if (obsName?.toLowerCase() === "unknown") {
|
|
3987
|
+
continue;
|
|
3988
|
+
}
|
|
3793
3989
|
const value = templateUtilities.extractObservationValue(observation);
|
|
3794
3990
|
const date = observation.effectiveDateTime ? templateUtilities.renderDate(observation.effectiveDateTime) : observation.issued ? templateUtilities.renderDate(observation.issued) : "";
|
|
3795
3991
|
const interpretation = observation.interpretation ? templateUtilities.codeableConceptDisplay(observation.interpretation[0]) : "";
|
|
@@ -3897,18 +4093,19 @@ var PregnancyTemplate = class _PregnancyTemplate {
|
|
|
3897
4093
|
<th>Code (System)</th>
|
|
3898
4094
|
<th>Comments</th>
|
|
3899
4095
|
<th>Date</th>
|
|
3900
|
-
<th>Source</th>
|
|
3901
4096
|
</tr>
|
|
3902
4097
|
</thead>
|
|
3903
4098
|
<tbody>`;
|
|
3904
|
-
function renderRow({ result, comments, date, codeSystem
|
|
4099
|
+
function renderRow({ result, comments, date, codeSystem }) {
|
|
4100
|
+
if (result?.toLowerCase() === "unknown") {
|
|
4101
|
+
return;
|
|
4102
|
+
}
|
|
3905
4103
|
html += `
|
|
3906
4104
|
<tr>
|
|
3907
4105
|
<td class="Result">${templateUtilities.capitalizeFirstLetter(result)}</td>
|
|
3908
4106
|
<td class="CodeSystem">${codeSystem}</td>
|
|
3909
4107
|
<td class="Comments">${comments}</td>
|
|
3910
4108
|
<td class="Date">${date}</td>
|
|
3911
|
-
<td class="Source">${owner}</td>
|
|
3912
4109
|
</tr>`;
|
|
3913
4110
|
}
|
|
3914
4111
|
const rowResources = [];
|
|
@@ -3962,8 +4159,7 @@ var PregnancyTemplate = class _PregnancyTemplate {
|
|
|
3962
4159
|
const rowKey = `${result}|${codeSystem}`;
|
|
3963
4160
|
if (!addedRows.has(rowKey)) {
|
|
3964
4161
|
addedRows.add(rowKey);
|
|
3965
|
-
|
|
3966
|
-
renderRow({ result, comments, date: dateStr, codeSystem, owner });
|
|
4162
|
+
renderRow({ result, comments, date: dateStr, codeSystem });
|
|
3967
4163
|
}
|
|
3968
4164
|
}
|
|
3969
4165
|
html += `
|
|
@@ -4010,11 +4206,17 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
|
|
|
4010
4206
|
</tr>
|
|
4011
4207
|
</thead>
|
|
4012
4208
|
<tbody>`;
|
|
4209
|
+
let isConsentAdded = false;
|
|
4013
4210
|
for (const resourceItem of resources) {
|
|
4014
4211
|
const consent = resourceItem;
|
|
4212
|
+
const consentScope = templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(consent.scope, "display")));
|
|
4213
|
+
if (!consentScope || consentScope.toLowerCase() === "unknown") {
|
|
4214
|
+
continue;
|
|
4215
|
+
}
|
|
4216
|
+
isConsentAdded = true;
|
|
4015
4217
|
html += `
|
|
4016
4218
|
<tr>
|
|
4017
|
-
<td>${
|
|
4219
|
+
<td>${consentScope}</td>
|
|
4018
4220
|
<td>${consent.status || ""}</td>
|
|
4019
4221
|
<td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
|
|
4020
4222
|
<td>${consent.dateTime || ""}</td>
|
|
@@ -4023,7 +4225,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
|
|
|
4023
4225
|
html += `
|
|
4024
4226
|
</tbody>
|
|
4025
4227
|
</table>`;
|
|
4026
|
-
return html;
|
|
4228
|
+
return isConsentAdded ? html : void 0;
|
|
4027
4229
|
}
|
|
4028
4230
|
};
|
|
4029
4231
|
|
|
@@ -4218,6 +4420,10 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4218
4420
|
* @param validResources - Array of domain resources
|
|
4219
4421
|
*/
|
|
4220
4422
|
addSectionAsync(narrative, sectionType, validResources) {
|
|
4423
|
+
if (sectionType === "Patient" /* PATIENT */) {
|
|
4424
|
+
this.patientSummary = narrative;
|
|
4425
|
+
return this;
|
|
4426
|
+
}
|
|
4221
4427
|
const sectionEntry = {
|
|
4222
4428
|
title: IPS_SECTION_DISPLAY_NAMES[sectionType] || sectionType,
|
|
4223
4429
|
code: {
|
|
@@ -4247,26 +4453,24 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4247
4453
|
for (const resource of validResources) {
|
|
4248
4454
|
this.resources.add(resource);
|
|
4249
4455
|
}
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
return this;
|
|
4267
|
-
}
|
|
4268
|
-
this.addSectionAsync(narrative, sectionType, validResources);
|
|
4456
|
+
let narrative = void 0;
|
|
4457
|
+
if (validResources.length > 0) {
|
|
4458
|
+
narrative = await NarrativeGenerator.generateNarrativeAsync(
|
|
4459
|
+
sectionType,
|
|
4460
|
+
validResources,
|
|
4461
|
+
timezone,
|
|
4462
|
+
true
|
|
4463
|
+
);
|
|
4464
|
+
}
|
|
4465
|
+
if (!narrative && sectionType in IPSMandatorySections) {
|
|
4466
|
+
narrative = await NarrativeGenerator.createNarrativeAsync(
|
|
4467
|
+
IPSMissingMandatorySectionContent[sectionType]
|
|
4468
|
+
);
|
|
4469
|
+
}
|
|
4470
|
+
if (!narrative) {
|
|
4471
|
+
return this;
|
|
4269
4472
|
}
|
|
4473
|
+
this.addSectionAsync(narrative, sectionType, validResources);
|
|
4270
4474
|
return this;
|
|
4271
4475
|
}
|
|
4272
4476
|
async makeSectionFromSummaryAsync(sectionType, summaryCompositions, resources, timezone) {
|
|
@@ -4304,17 +4508,18 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4304
4508
|
* @param timezone - Optional timezone to use for date formatting
|
|
4305
4509
|
* @param useSummaryCompositions - Whether to use summary compositions (default: false)
|
|
4306
4510
|
*/
|
|
4307
|
-
async readBundleAsync(bundle, timezone, useSummaryCompositions = false) {
|
|
4511
|
+
async readBundleAsync(bundle, timezone, useSummaryCompositions = false, consoleLogger = console) {
|
|
4308
4512
|
if (!bundle.entry) {
|
|
4309
4513
|
return this;
|
|
4310
4514
|
}
|
|
4311
4515
|
const patientEntries = [];
|
|
4312
4516
|
const resources = [];
|
|
4313
4517
|
bundle.entry.forEach((e) => {
|
|
4314
|
-
if (e.resource
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4518
|
+
if (e.resource) {
|
|
4519
|
+
if (e.resource.resourceType === "Patient") {
|
|
4520
|
+
patientEntries.push(e.resource);
|
|
4521
|
+
this.resources.add(e.resource);
|
|
4522
|
+
}
|
|
4318
4523
|
resources.push(e.resource);
|
|
4319
4524
|
}
|
|
4320
4525
|
});
|
|
@@ -4323,23 +4528,20 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4323
4528
|
}
|
|
4324
4529
|
this.patients = patientEntries;
|
|
4325
4530
|
for (const sectionType of Object.values(IPSSections)) {
|
|
4326
|
-
if (sectionType === "Patient" /* PATIENT */) {
|
|
4327
|
-
continue;
|
|
4328
|
-
}
|
|
4329
4531
|
const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
|
|
4330
4532
|
const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
|
|
4331
4533
|
if (sectionIPSSummary.length > 0) {
|
|
4332
|
-
|
|
4534
|
+
consoleLogger.info(`Using IPS summary composition for section: ${sectionType}`);
|
|
4333
4535
|
await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
|
|
4334
4536
|
continue;
|
|
4335
4537
|
}
|
|
4336
4538
|
const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
|
|
4337
4539
|
const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
|
|
4338
4540
|
if (sectionSummary.length > 0) {
|
|
4339
|
-
|
|
4541
|
+
consoleLogger.info(`Using summary composition for section: ${sectionType}`);
|
|
4340
4542
|
await this.makeSectionFromSummaryAsync(sectionType, sectionSummary, resources, timezone);
|
|
4341
4543
|
} else {
|
|
4342
|
-
|
|
4544
|
+
consoleLogger.info(`Using individual resources for section: ${sectionType}`);
|
|
4343
4545
|
const sectionFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
|
|
4344
4546
|
const sectionResources = resources.filter((resource) => sectionFilter(resource));
|
|
4345
4547
|
await this.makeSectionAsync(sectionType, sectionResources, timezone);
|
|
@@ -4363,6 +4565,9 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4363
4565
|
if (!this.patients) {
|
|
4364
4566
|
throw new Error("Patient resource must be set before building the bundle");
|
|
4365
4567
|
}
|
|
4568
|
+
if (!this.patientSummary) {
|
|
4569
|
+
throw new Error("Patient summary narrative must be set before building the bundle");
|
|
4570
|
+
}
|
|
4366
4571
|
const primaryPatientId = patientId ?? this.patients[0].id;
|
|
4367
4572
|
const composition = {
|
|
4368
4573
|
id: `Composition-${primaryPatientId}`,
|
|
@@ -4386,14 +4591,7 @@ var ComprehensiveIPSCompositionBuilder = class {
|
|
|
4386
4591
|
date: (now || /* @__PURE__ */ new Date()).toISOString(),
|
|
4387
4592
|
title: "International Patient Summary",
|
|
4388
4593
|
section: this.sections,
|
|
4389
|
-
text:
|
|
4390
|
-
"Patient" /* PATIENT */,
|
|
4391
|
-
this.patients,
|
|
4392
|
-
timezone,
|
|
4393
|
-
true,
|
|
4394
|
-
false,
|
|
4395
|
-
now
|
|
4396
|
-
)
|
|
4594
|
+
text: this.patientSummary
|
|
4397
4595
|
};
|
|
4398
4596
|
const bundle = {
|
|
4399
4597
|
resourceType: "Bundle",
|