@imranq2/fhirpatientsummary 1.0.31 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -169,7 +169,8 @@ var IPSSectionSummaryCompositionFilter = {
169
169
  ["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "procedure_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
170
170
  };
171
171
  var IPSSectionSummaryIPSCompositionFilter = {
172
- ["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => c.system === IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM && c.code === "ips_vital_summary_document")
172
+ ["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_patient_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
173
+ ["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_vital_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
173
174
  };
174
175
  var IPSSectionResourceHelper = class {
175
176
  static getResourceFilterForSection(section) {
@@ -884,18 +885,6 @@ var TemplateUtilities = class {
884
885
  }
885
886
  return "";
886
887
  }
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
888
  /**
900
889
  * Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
901
890
  * This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
@@ -910,6 +899,23 @@ var TemplateUtilities = class {
910
899
  const escapedText = text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
911
900
  return escapedText.replace(/\n/g, "<br />");
912
901
  }
902
+ capitalizeFirstLetter(text) {
903
+ if (!text || text.length === 0) {
904
+ return "";
905
+ }
906
+ return text.charAt(0).toUpperCase() + text.slice(1);
907
+ }
908
+ renderListSectionData(sectionData) {
909
+ if (!sectionData || !Array.isArray(sectionData) || sectionData.length === 0) {
910
+ return "";
911
+ }
912
+ const items = [];
913
+ for (const section of sectionData) {
914
+ items.push(this.renderTextAsHtml(section.text?.div || ""));
915
+ }
916
+ const listString = Array.from(items).map((item) => `<li>${item}</li>`).join("");
917
+ return `<ul>${listString}</ul>`;
918
+ }
913
919
  /**
914
920
  * Renders note elements from a FHIR resource in a standardized format
915
921
  * Can render as simple comma-separated text or as styled HTML with timestamps
@@ -1397,6 +1403,60 @@ var PatientTemplate = class _PatientTemplate {
1397
1403
  generateNarrative(resources, timezone) {
1398
1404
  return _PatientTemplate.generateStaticNarrative(resources, timezone);
1399
1405
  }
1406
+ /**
1407
+ * Generate HTML narrative for Patient resources using summary
1408
+ * @param resources - FHIR Composition resources
1409
+ * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1410
+ * @returns HTML string for rendering
1411
+ */
1412
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1413
+ generateSummaryNarrative(resources, timezone) {
1414
+ const templateUtilities = new TemplateUtilities(resources);
1415
+ const compositionResources = resources[0];
1416
+ const data = {};
1417
+ for (const rowData of compositionResources.section ?? []) {
1418
+ for (const columnData of rowData.section ?? []) {
1419
+ switch (columnData.title) {
1420
+ case "Name":
1421
+ case "Address":
1422
+ case "Communication":
1423
+ data[columnData.title] = templateUtilities.renderListSectionData(columnData.section ?? []);
1424
+ break;
1425
+ case "Telecom": {
1426
+ const telecomStringParts = [];
1427
+ for (const telecomData of columnData.section ?? []) {
1428
+ const telecomSystem = telecomData?.title;
1429
+ const telecomValue = templateUtilities.renderListSectionData(telecomData.section ?? []);
1430
+ if (telecomSystem && telecomValue) {
1431
+ telecomStringParts.push(`<li><strong>${telecomSystem}:</strong>${telecomValue}</li>`);
1432
+ }
1433
+ }
1434
+ data["Telecom"] = `<ul>${telecomStringParts.join("")}</ul>`;
1435
+ break;
1436
+ }
1437
+ default:
1438
+ if (columnData.title) {
1439
+ data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1440
+ }
1441
+ break;
1442
+ }
1443
+ }
1444
+ }
1445
+ let html = `<p>This section merges all Patient resources into a single combined patient record, preferring non-empty values for each field.</p>`;
1446
+ html += `<div>
1447
+ <ul>
1448
+ <li><strong>Name(s):</strong>${data["Name"] || ""}</li>
1449
+ <li><strong>Gender:</strong>${data["Gender"] || ""}</li>
1450
+ <li><strong>Date of Birth:</strong>${data["Date of Birth"] || ""}</li>
1451
+ <li><strong>Telecom:</strong>${data["Telecom"] || ""}</li>
1452
+ <li><strong>Address(es):</strong>${data["Address"] || ""}</li>
1453
+ <li><strong>Marital Status:</strong> ${data["Marital Status"] || ""}</li>
1454
+ <li><strong>Deceased:</strong>${data["Deceased"] || ""}</li>
1455
+ <li><strong>Language(s):</strong>${data["Communication"] || ""}</li>
1456
+ </ul>
1457
+ </div>`;
1458
+ return html;
1459
+ }
1400
1460
  /**
1401
1461
  * Internal static implementation that actually generates the narrative
1402
1462
  * @param resources - FHIR Patient resources
@@ -1490,7 +1550,8 @@ var PatientTemplate = class _PatientTemplate {
1490
1550
  }
1491
1551
  }
1492
1552
  });
1493
- return Array.from(uniqueNames).map((nameText) => `<ul><li>${nameText}</li></ul>`).join("");
1553
+ const namesHtml = Array.from(uniqueNames).map((nameText) => `<li>${nameText}</li>`).join("");
1554
+ return `<ul>${namesHtml}</ul>`;
1494
1555
  }
1495
1556
  /**
1496
1557
  * Renders patient telecom information grouped by system
@@ -1594,7 +1655,8 @@ var PatientTemplate = class _PatientTemplate {
1594
1655
  }
1595
1656
  });
1596
1657
  const deduplicatedAddresses = this.deduplicateSimilarAddresses(Array.from(uniqueAddresses));
1597
- return deduplicatedAddresses.map((addressText) => `<ul><li>${addressText}</li></ul>`).join("");
1658
+ const addressesHtml = deduplicatedAddresses.map((addressText) => `<li>${addressText}</li>`).join("");
1659
+ return `<ul>${addressesHtml}</ul>`;
1598
1660
  }
1599
1661
  /**
1600
1662
  * Calculates the similarity between two strings using Levenshtein distance
@@ -1712,7 +1774,8 @@ var PatientTemplate = class _PatientTemplate {
1712
1774
  uniqueLanguages.add(language);
1713
1775
  }
1714
1776
  });
1715
- return Array.from(uniqueLanguages).map((language) => `<ul><li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li></ul>`).join("");
1777
+ const languagesHtml = Array.from(uniqueLanguages).map((language) => `<li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li>`).join("");
1778
+ return `<ul>${languagesHtml}</ul>`;
1716
1779
  }
1717
1780
  /**
1718
1781
  * Capitalizes first letter of a string
@@ -1756,7 +1819,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1756
1819
  <th>Code (System)</th>
1757
1820
  <th>Criticality</th>
1758
1821
  <th>Recorded Date</th>
1759
- <th>Source</th>
1760
1822
  </tr>
1761
1823
  </thead>
1762
1824
  <tbody>`;
@@ -1776,21 +1838,20 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1776
1838
  case "Recorded Date":
1777
1839
  data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1778
1840
  break;
1779
- case "Source":
1780
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1781
- break;
1782
1841
  default:
1783
1842
  break;
1784
1843
  }
1785
1844
  }
1845
+ if (data["allergen"]?.toLowerCase() === "unknown") {
1846
+ continue;
1847
+ }
1786
1848
  isSummaryCreated = true;
1787
1849
  html += `
1788
1850
  <tr>
1789
- <td>${data["allergen"] ?? ""}</td>
1851
+ <td>${templateUtilities.capitalizeFirstLetter(data["allergen"] ?? "")}</td>
1790
1852
  <td>${data["codeSystem"] ?? ""}</td>
1791
1853
  <td>${data["criticality"] ?? ""}</td>
1792
1854
  <td>${templateUtilities.renderTime(data["recordedDate"], timezone) ?? ""}</td>
1793
- <td>${data["source"] ?? ""}</td>
1794
1855
  </tr>`;
1795
1856
  }
1796
1857
  }
@@ -1844,7 +1905,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1844
1905
  <th>Reaction</th>
1845
1906
  <th>Onset Date</th>
1846
1907
  <th>Comments</th>
1847
- <th>Source</th>
1848
1908
  </tr>
1849
1909
  </thead>
1850
1910
  <tbody>`;
@@ -1874,7 +1934,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1874
1934
  <th>Onset Date</th>
1875
1935
  <th>Comments</th>
1876
1936
  <th>Resolved Date</th>
1877
- <th>Source</th>
1878
1937
  </tr>
1879
1938
  </thead>
1880
1939
  <tbody>`;
@@ -1903,16 +1962,19 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1903
1962
  static generateAllergyRows(allergies, templateUtilities, timezone, includeResolved = false) {
1904
1963
  let html = "";
1905
1964
  for (const allergy of allergies) {
1965
+ const allergenName = templateUtilities.codeableConceptDisplay(allergy.code);
1966
+ if (allergenName?.toLowerCase() === "unknown") {
1967
+ continue;
1968
+ }
1906
1969
  html += `
1907
- <tr id="${templateUtilities.narrativeLinkId(allergy.extension)}">
1908
- <td class="Name"><span class="AllergenName">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(allergy.code))}</span></td>
1970
+ <tr>
1971
+ <td class="Name"><span class="AllergenName">${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(allergenName))}</span></td>
1909
1972
  <td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(allergy.clinicalStatus)) || ""}</td>
1910
1973
  <td class="CodeSystem">${templateUtilities.codeableConceptCoding(allergy.code)}</td>
1911
1974
  <td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || ""}</td>
1912
1975
  <td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || ""}</td>
1913
1976
  <td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || ""}</td>
1914
- <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>
1915
- <td class="Source">${templateUtilities.getOwnerTag(allergy)}</td>`;
1977
+ <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
1916
1978
  if (includeResolved) {
1917
1979
  let endDate = "";
1918
1980
  if (allergy.extension && Array.isArray(allergy.extension)) {
@@ -1967,9 +2029,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1967
2029
  <th>Status</th>
1968
2030
  <th>Sig</th>
1969
2031
  <th>Days of Supply</th>
1970
- <th>Refills</th>
1971
2032
  <th>Start Date</th>
1972
- <th>Source</th>
1973
2033
  </tr>
1974
2034
  </thead>
1975
2035
  <tbody>`;
@@ -1995,15 +2055,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1995
2055
  case "Days Of Supply":
1996
2056
  data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1997
2057
  break;
1998
- case "Refills Remaining":
1999
- data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2000
- break;
2001
2058
  case "Authored On Date":
2002
2059
  data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2003
2060
  break;
2004
- case "Source":
2005
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2006
- break;
2007
2061
  default:
2008
2062
  break;
2009
2063
  }
@@ -2019,17 +2073,18 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2019
2073
  skippedMedications++;
2020
2074
  }
2021
2075
  if (data["status"] === "active" || startDateObj && startDateObj >= twoYearsAgo) {
2076
+ if (data["medication"]?.toLowerCase() === "unknown") {
2077
+ continue;
2078
+ }
2022
2079
  isSummaryCreated = true;
2023
2080
  html += `
2024
2081
  <tr>
2025
- <td>${templateUtilities.renderTextAsHtml(data["medication"])}</td>
2082
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(data["medication"]))}</td>
2026
2083
  <td>${templateUtilities.codeableConceptCoding(sectionCodeableConcept)}</td>
2027
2084
  <td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
2028
2085
  <td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
2029
2086
  <td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
2030
- <td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
2031
2087
  <td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
2032
- <td>${templateUtilities.renderTextAsHtml(data["source"])}</td>
2033
2088
  </tr>`;
2034
2089
  }
2035
2090
  }
@@ -2069,8 +2124,8 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2069
2124
  static generateStaticNarrative(resources, timezone, now) {
2070
2125
  const templateUtilities = new TemplateUtilities(resources);
2071
2126
  let html = "";
2072
- const medicationRequests = this.getMedicationRequests(templateUtilities, resources);
2073
- const medicationStatements = this.getMedicationStatements(templateUtilities, resources);
2127
+ const medicationRequests = resources.filter((entry) => entry.resourceType === "MedicationRequest");
2128
+ const medicationStatements = resources.filter((entry) => entry.resourceType === "MedicationStatement");
2074
2129
  const allActiveMedications = [];
2075
2130
  const currentDate = now || /* @__PURE__ */ new Date();
2076
2131
  const twoYearsAgo = new Date(currentDate);
@@ -2078,10 +2133,10 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2078
2133
  let skippedMedications = 0;
2079
2134
  const allMedications = [];
2080
2135
  medicationRequests.forEach((mr) => {
2081
- allMedications.push({ type: "request", resource: mr.resource, extension: mr.extension });
2136
+ allMedications.push({ type: "request", resource: mr });
2082
2137
  });
2083
2138
  medicationStatements.forEach((ms) => {
2084
- allMedications.push({ type: "statement", resource: ms.resource, extension: ms.extension });
2139
+ allMedications.push({ type: "statement", resource: ms });
2085
2140
  });
2086
2141
  for (const med of allMedications) {
2087
2142
  let dateString;
@@ -2138,36 +2193,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2138
2193
  }
2139
2194
  return "";
2140
2195
  }
2141
- /**
2142
- * Extract MedicationRequest resources
2143
- * @param templateUtilities - Instance of TemplateUtilities for utility functions
2144
- * @param resources - FHIR Medication resources
2145
- * @returns Array of MedicationRequest resources
2146
- */
2147
- static getMedicationRequests(templateUtilities, resources) {
2148
- if (resources.length === 0) {
2149
- return [];
2150
- }
2151
- return resources.filter((entry) => entry.resourceType === "MedicationRequest").map((entry) => ({
2152
- resource: entry,
2153
- extension: templateUtilities.narrativeLinkExtension(entry)
2154
- }));
2155
- }
2156
- /**
2157
- * Extract MedicationStatement resources
2158
- * @param templateUtilities - Instance of TemplateUtilities for utility functions
2159
- * @param resources - FHIR Medication resources
2160
- * @returns Array of MedicationStatement resources
2161
- */
2162
- static getMedicationStatements(templateUtilities, resources) {
2163
- if (resources.length === 0) {
2164
- return [];
2165
- }
2166
- return resources.filter((entry) => entry.resourceType === "MedicationStatement").map((entry) => ({
2167
- resource: entry,
2168
- extension: templateUtilities.narrativeLinkExtension(entry)
2169
- }));
2170
- }
2171
2196
  /**
2172
2197
  * Render HTML table for combined MedicationRequest and MedicationStatement resources
2173
2198
  * @param templateUtilities - Instance of TemplateUtilities for utility functions
@@ -2184,19 +2209,15 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2184
2209
  <th>Code (System)</th>
2185
2210
  <th>Sig</th>
2186
2211
  <th>Dispense Quantity</th>
2187
- <th>Refills</th>
2188
2212
  <th>Start Date</th>
2189
- <th>Source</th>
2190
2213
  </tr>
2191
2214
  </thead>
2192
2215
  <tbody>`;
2193
2216
  for (const medication of medications) {
2194
- const narrativeLinkId = templateUtilities.narrativeLinkId(medication.extension);
2195
2217
  let type;
2196
2218
  let medicationName;
2197
2219
  let sig;
2198
2220
  let dispenseQuantity = "";
2199
- let refills = "";
2200
2221
  let startDate = "";
2201
2222
  let codeSystemDisplay = "";
2202
2223
  if (medication.type === "request") {
@@ -2212,7 +2233,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2212
2233
  dispenseQuantity = `${quantity.value} ${quantity.unit || quantity.code || ""}`.trim();
2213
2234
  }
2214
2235
  }
2215
- refills = mr.dispenseRequest?.numberOfRepeatsAllowed?.toString() || "";
2216
2236
  if (mr.dispenseRequest?.validityPeriod) {
2217
2237
  startDate = mr.dispenseRequest.validityPeriod.start || "";
2218
2238
  } else {
@@ -2237,16 +2257,17 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2237
2257
  codeSystemDisplay = templateUtilities.codeableConceptCoding(ms.medicationCodeableConcept);
2238
2258
  }
2239
2259
  }
2260
+ if (medicationName?.toLowerCase() === "unknown") {
2261
+ continue;
2262
+ }
2240
2263
  html += `
2241
- <tr${narrativeLinkId ? ` id="${narrativeLinkId}"` : ""}>
2264
+ <tr>
2242
2265
  <td>${type}</td>
2243
- <td>${medicationName}<ul></ul></td>
2266
+ <td>${templateUtilities.capitalizeFirstLetter(medicationName)}</td>
2244
2267
  <td>${codeSystemDisplay}</td>
2245
2268
  <td>${sig}</td>
2246
2269
  <td>${dispenseQuantity}</td>
2247
- <td>${refills}</td>
2248
2270
  <td>${startDate}</td>
2249
- <td>${templateUtilities.getOwnerTag(medication.resource)}</td>
2250
2271
  </tr>`;
2251
2272
  }
2252
2273
  html += `
@@ -2291,7 +2312,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2291
2312
  <th>Code (System)</th>
2292
2313
  <th>Status</th>
2293
2314
  <th>Date</th>
2294
- <th>Source</th>
2295
2315
  </tr>
2296
2316
  </thead>
2297
2317
  <tbody>`;
@@ -2311,22 +2331,21 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2311
2331
  case "occurrenceDateTime":
2312
2332
  data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2313
2333
  break;
2314
- case "Source":
2315
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2316
- break;
2317
2334
  default:
2318
2335
  break;
2319
2336
  }
2320
2337
  }
2321
2338
  if (data["status"] === "completed") {
2339
+ if (data["immunization"]?.toLowerCase() === "unknown") {
2340
+ continue;
2341
+ }
2322
2342
  isSummaryCreated = true;
2323
2343
  html += `
2324
2344
  <tr>
2325
- <td>${data["immunization"] ?? ""}</td>
2345
+ <td>${templateUtilities.capitalizeFirstLetter(data["immunization"] ?? "")}</td>
2326
2346
  <td>${data["codeSystem"] ?? ""}</td>
2327
2347
  <td>${data["status"] ?? ""}</td>
2328
2348
  <td>${templateUtilities.renderTime(data["occurrenceDateTime"], timezone) ?? ""}</td>
2329
- <td>${data["source"] ?? ""}</td>
2330
2349
  </tr>`;
2331
2350
  }
2332
2351
  }
@@ -2357,7 +2376,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2357
2376
  <th>Lot Number</th>
2358
2377
  <th>Comments</th>
2359
2378
  <th>Date</th>
2360
- <th>Source</th>
2361
2379
  </tr>
2362
2380
  </thead>
2363
2381
  <tbody>`;
@@ -2365,9 +2383,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2365
2383
  if (immunizations.length > 0) {
2366
2384
  for (const resourceItem of immunizations) {
2367
2385
  const imm = resourceItem;
2386
+ const immunizationName = templateUtilities.codeableConceptDisplay(imm.vaccineCode);
2387
+ if (immunizationName?.toLowerCase() === "unknown") {
2388
+ continue;
2389
+ }
2368
2390
  html += `
2369
2391
  <tr>
2370
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(imm.vaccineCode))}</td>
2392
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(immunizationName))}</td>
2371
2393
  <td>${templateUtilities.codeableConceptCoding(imm.vaccineCode)}</td>
2372
2394
  <td>${imm.status || ""}</td>
2373
2395
  <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
@@ -2375,7 +2397,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2375
2397
  <td>${imm.lotNumber || ""}</td>
2376
2398
  <td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
2377
2399
  <td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
2378
- <td>${templateUtilities.getOwnerTag(imm)}</td>
2379
2400
  </tr>`;
2380
2401
  }
2381
2402
  }
@@ -2425,7 +2446,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
2425
2446
  <th>Code (System)</th>
2426
2447
  <th>Onset Date</th>
2427
2448
  <th>Recorded Date</th>
2428
- <th>Source</th>
2429
2449
  </tr>
2430
2450
  </thead>
2431
2451
  <tbody>`;
@@ -2436,13 +2456,15 @@ var ProblemListTemplate = class _ProblemListTemplate {
2436
2456
  if (codeAndSystem && seenCodeAndSystems.has(codeAndSystem)) {
2437
2457
  continue;
2438
2458
  }
2459
+ if (conditionDisplay?.toLowerCase() === "unknown") {
2460
+ continue;
2461
+ }
2439
2462
  seenCodeAndSystems.add(codeAndSystem);
2440
2463
  html += `<tr>
2441
- <td class="Name">${conditionDisplay}</td>
2464
+ <td class="Name">${templateUtilities.capitalizeFirstLetter(conditionDisplay)}</td>
2442
2465
  <td class="CodeSystem">${codeAndSystem}</td>
2443
2466
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2444
2467
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2445
- <td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
2446
2468
  </tr>`;
2447
2469
  }
2448
2470
  html += `</tbody>
@@ -2482,7 +2504,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2482
2504
  <th>Code (System)</th>
2483
2505
  <th>Result</th>
2484
2506
  <th>Date</th>
2485
- <th>Source</th>
2486
2507
  </tr>
2487
2508
  </thead>
2488
2509
  <tbody>`;
@@ -2515,14 +2536,16 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2515
2536
  data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2516
2537
  }
2517
2538
  }
2539
+ if (data["Vital Name"]?.toLowerCase() === "unknown") {
2540
+ continue;
2541
+ }
2518
2542
  isSummaryCreated = true;
2519
2543
  html += `
2520
2544
  <tr>
2521
- <td>${data["Vital Name"] ?? ""}</td>
2545
+ <td>${templateUtilities.capitalizeFirstLetter(data["Vital Name"] ?? "")}</td>
2522
2546
  <td>${data["codeSystem"] ?? ""}</td>
2523
2547
  <td>${templateUtilities.extractObservationSummaryValue(data, timezone) ?? ""}</td>
2524
2548
  <td>${templateUtilities.extractObservationSummaryEffectiveTime(data, timezone) ?? ""}</td>
2525
- <td>${data["Source"] ?? ""}</td>
2526
2549
  </tr>`;
2527
2550
  }
2528
2551
  }
@@ -2560,14 +2583,17 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2560
2583
  <th>Component(s)</th>
2561
2584
  <th>Comments</th>
2562
2585
  <th>Date</th>
2563
- <th>Source</th>
2564
2586
  </tr>
2565
2587
  </thead>
2566
2588
  <tbody>`;
2567
2589
  for (const obs of observations) {
2590
+ const vitalName = templateUtilities.codeableConceptDisplay(obs.code, "display");
2591
+ if (vitalName?.toLowerCase() === "unknown") {
2592
+ continue;
2593
+ }
2568
2594
  html += `
2569
2595
  <tr>
2570
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code, "display"))}</td>
2596
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(vitalName))}</td>
2571
2597
  <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
2572
2598
  <td>${templateUtilities.extractObservationValue(obs)}</td>
2573
2599
  <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
@@ -2575,7 +2601,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2575
2601
  <td>${templateUtilities.renderComponent(obs.component)}</td>
2576
2602
  <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
2577
2603
  <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
2578
- <td>${templateUtilities.getOwnerTag(obs)}</td>
2579
2604
  </tr>`;
2580
2605
  }
2581
2606
  html += `
@@ -2620,10 +2645,16 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
2620
2645
  const dateB = b.recordedOn;
2621
2646
  return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
2622
2647
  });
2648
+ let isDeviceAdded = false;
2623
2649
  for (const dus of deviceStatements) {
2650
+ const deviceName = templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device));
2651
+ if (deviceName?.toLowerCase() === "unknown") {
2652
+ continue;
2653
+ }
2654
+ isDeviceAdded = true;
2624
2655
  html += `
2625
2656
  <tr>
2626
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device))}</td>
2657
+ <td>${templateUtilities.capitalizeFirstLetter(deviceName)}</td>
2627
2658
  <td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
2628
2659
  <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
2629
2660
  <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
@@ -2632,7 +2663,7 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
2632
2663
  html += `
2633
2664
  </tbody>
2634
2665
  </table>`;
2635
- return html;
2666
+ return isDeviceAdded ? html : void 0;
2636
2667
  }
2637
2668
  };
2638
2669
 
@@ -2997,7 +3028,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
2997
3028
  <th>Result</th>
2998
3029
  <th>Reference Range</th>
2999
3030
  <th>Date</th>
3000
- <th>Source</th>
3001
3031
  </tr>
3002
3032
  </thead>
3003
3033
  <tbody>`;
@@ -3011,7 +3041,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3011
3041
  <th>Report</th>
3012
3042
  <th>Performer</th>
3013
3043
  <th>Issued</th>
3014
- <th>Source</th>
3015
3044
  </tr>
3016
3045
  </thead>
3017
3046
  <tbody>`;
@@ -3058,8 +3087,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3058
3087
  case "Status":
3059
3088
  data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3060
3089
  break;
3061
- case "Source":
3062
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3063
3090
  break;
3064
3091
  default:
3065
3092
  break;
@@ -3085,16 +3112,18 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3085
3112
  for (const component of components) {
3086
3113
  const componentCode = `${groupName}${component["code"] ?? ""}`;
3087
3114
  if (componentCode && !observationAdded.has(componentCode)) {
3115
+ if (component["code"]?.toLowerCase() === "unknown") {
3116
+ continue;
3117
+ }
3088
3118
  observationAdded.add(componentCode);
3089
3119
  this.formatSummaryObservationData(component);
3090
3120
  observationhtml += `
3091
3121
  <tr>
3092
- <td>${componentCode}</td>
3122
+ <td>${templateUtilities.capitalizeFirstLetter(componentCode)}</td>
3093
3123
  <td></td>
3094
3124
  <td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? ""}</td>
3095
3125
  <td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? ""}</td>
3096
3126
  <td>${date ?? ""}</td>
3097
- <td>${data["source"] ?? ""}</td>
3098
3127
  </tr>`;
3099
3128
  }
3100
3129
  }
@@ -3102,16 +3131,18 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3102
3131
  if (obsDate && obsDate >= twoYearsAgo) {
3103
3132
  const code = data["code"] ?? "";
3104
3133
  if (code && !observationAdded.has(code)) {
3134
+ if (code.toLowerCase() === "unknown") {
3135
+ continue;
3136
+ }
3105
3137
  observationAdded.add(code);
3106
3138
  this.formatSummaryObservationData(data);
3107
3139
  observationhtml += `
3108
3140
  <tr>
3109
- <td>${data["code"] ?? ""}</td>
3141
+ <td>${templateUtilities.capitalizeFirstLetter(data["code"] ?? "")}</td>
3110
3142
  <td>${templateUtilities.codeableConceptCoding(sectionCodeableConcept)}</td>
3111
3143
  <td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? ""}</td>
3112
3144
  <td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? ""}</td>
3113
3145
  <td>${date ?? ""}</td>
3114
- <td>${data["source"] ?? ""}</td>
3115
3146
  </tr>`;
3116
3147
  }
3117
3148
  }
@@ -3124,13 +3155,15 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3124
3155
  if (data["status"] === "final" && issuedDate && issuedDate >= twoYearsAgo) {
3125
3156
  const reportName = data["report"] ?? "";
3126
3157
  if (reportName && !diagnosticReportAdded.has(reportName)) {
3158
+ if (reportName.toLowerCase() === "unknown") {
3159
+ continue;
3160
+ }
3127
3161
  diagnosticReportAdded.add(reportName);
3128
3162
  diagnosticReporthtml += `
3129
3163
  <tr>
3130
- <td>${data["report"] ?? ""}</td>
3164
+ <td>${templateUtilities.capitalizeFirstLetter(data["report"] ?? "")}</td>
3131
3165
  <td>${data["performer"] ?? ""}</td>
3132
3166
  <td>${templateUtilities.renderTime(data["issued"], timezone) ?? ""}</td>
3133
- <td>${data["source"] ?? ""}</td>
3134
3167
  </tr>`;
3135
3168
  }
3136
3169
  }
@@ -3315,7 +3348,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3315
3348
  <th>Result</th>
3316
3349
  <th>Reference Range</th>
3317
3350
  <th>Date</th>
3318
- <th>Source</th>
3319
3351
  </tr>
3320
3352
  </thead>
3321
3353
  <tbody>`;
@@ -3324,16 +3356,18 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3324
3356
  const obsCodeDisplay = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
3325
3357
  const obsCodeAndSystem = templateUtilities.codeableConceptCoding(obs.code);
3326
3358
  if (!observationAdded.has(obsCodeDisplay) && !observationAdded.has(obsCodeAndSystem)) {
3359
+ if (obsCodeDisplay?.toLowerCase() === "unknown") {
3360
+ continue;
3361
+ }
3327
3362
  observationAdded.add(obsCodeDisplay);
3328
3363
  observationAdded.add(obsCodeAndSystem);
3329
3364
  html += `
3330
- <tr id="${templateUtilities.narrativeLinkId(obs)}">
3331
- <td>${obsCodeDisplay}</td>
3365
+ <tr>
3366
+ <td>${templateUtilities.capitalizeFirstLetter(obsCodeDisplay)}</td>
3332
3367
  <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
3333
3368
  <td>${templateUtilities.extractObservationValue(obs)}</td>
3334
3369
  <td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
3335
3370
  <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3336
- <td>${templateUtilities.getOwnerTag(obs)}</td>
3337
3371
  </tr>`;
3338
3372
  }
3339
3373
  }
@@ -3360,7 +3394,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3360
3394
  <th>Category</th>
3361
3395
  <th>Result</th>
3362
3396
  <th>Issued</th>
3363
- <th>Source</th>
3364
3397
  </tr>
3365
3398
  </thead>
3366
3399
  <tbody>`;
@@ -3369,6 +3402,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3369
3402
  const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(report.code));
3370
3403
  const codeAndSystem = templateUtilities.codeableConceptCoding(report.code);
3371
3404
  if (!diagnosticReportAdded.has(reportName) && !diagnosticReportAdded.has(codeAndSystem)) {
3405
+ if (reportName?.toLowerCase() === "unknown") {
3406
+ continue;
3407
+ }
3372
3408
  diagnosticReportAdded.add(reportName);
3373
3409
  diagnosticReportAdded.add(codeAndSystem);
3374
3410
  let resultCount = "";
@@ -3376,13 +3412,12 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3376
3412
  resultCount = `${report.result.length} result${report.result.length !== 1 ? "s" : ""}`;
3377
3413
  }
3378
3414
  html += `
3379
- <tr id="${templateUtilities.narrativeLinkId(report)}">
3380
- <td>${reportName}</td>
3415
+ <tr>
3416
+ <td>${templateUtilities.capitalizeFirstLetter(reportName)}</td>
3381
3417
  <td>${codeAndSystem}</td>
3382
3418
  <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
3383
3419
  <td>${resultCount}</td>
3384
3420
  <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
3385
- <td>${templateUtilities.getOwnerTag(report)}</td>
3386
3421
  </tr>`;
3387
3422
  }
3388
3423
  }
@@ -3449,7 +3484,6 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3449
3484
  <th>Code (System)</th>
3450
3485
  <th>Performer</th>
3451
3486
  <th>Date</th>
3452
- <th>Source</th>
3453
3487
  </tr>
3454
3488
  </thead>
3455
3489
  <tbody>`;
@@ -3469,21 +3503,21 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3469
3503
  case "Performed Date":
3470
3504
  data["date"] = columnData.text?.div ?? "";
3471
3505
  break;
3472
- case "Source":
3473
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3474
3506
  break;
3475
3507
  default:
3476
3508
  break;
3477
3509
  }
3478
3510
  }
3511
+ if (data["procedure"]?.toLowerCase() === "unknown") {
3512
+ continue;
3513
+ }
3479
3514
  isSummaryCreated = true;
3480
3515
  html += `
3481
3516
  <tr>
3482
- <td>${data["procedure"] ?? ""}</td>
3517
+ <td>${templateUtilities.capitalizeFirstLetter(data["procedure"] ?? "")}</td>
3483
3518
  <td>${data["codeSystem"] ?? ""}</td>
3484
3519
  <td>${data["performer"] ?? ""}</td>
3485
3520
  <td>${templateUtilities.renderTime(data["date"], timezone) ?? ""}</td>
3486
- <td>${data["source"] ?? ""}</td>
3487
3521
  </tr>`;
3488
3522
  }
3489
3523
  }
@@ -3511,19 +3545,21 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3511
3545
  <th>Code (System)</th>
3512
3546
  <th>Comments</th>
3513
3547
  <th>Date</th>
3514
- <th>Source</th>
3515
3548
  </tr>
3516
3549
  </thead>
3517
3550
  <tbody>`;
3518
3551
  for (const resourceItem of resources) {
3519
3552
  const proc = resourceItem;
3553
+ const procedureName = templateUtilities.codeableConceptDisplay(proc.code, "display");
3554
+ if (procedureName?.toLowerCase() === "unknown") {
3555
+ continue;
3556
+ }
3520
3557
  html += `
3521
3558
  <tr>
3522
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(proc.code, "display"))}</td>
3559
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(procedureName))}</td>
3523
3560
  <td>${templateUtilities.codeableConceptCoding(proc.code)}</td>
3524
3561
  <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
3525
3562
  <td>${templateUtilities.renderTime(proc.performedDateTime || proc.performedPeriod?.start, timezone)}</td>
3526
- <td>${templateUtilities.getOwnerTag(proc)}</td>
3527
3563
  </tr>`;
3528
3564
  }
3529
3565
  html += `
@@ -3570,21 +3606,27 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
3570
3606
  <th>Unit</th>
3571
3607
  <th>Comments</th>
3572
3608
  <th>Date</th>
3573
- <th>Source</th>
3574
3609
  </tr>
3575
3610
  </thead>
3576
3611
  <tbody>`;
3612
+ const addedObservations = /* @__PURE__ */ new Set();
3577
3613
  for (const obs of observations) {
3578
- html += `
3579
- <tr>
3580
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code))}</td>
3581
- <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
3582
- <td>${templateUtilities.extractObservationValue(obs)}</td>
3583
- <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
3584
- <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
3585
- <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3586
- <td>${templateUtilities.getOwnerTag(obs)}</td>
3587
- </tr>`;
3614
+ const obsName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
3615
+ if (!addedObservations.has(obsName)) {
3616
+ if (obsName?.toLowerCase() === "unknown") {
3617
+ continue;
3618
+ }
3619
+ addedObservations.add(obsName);
3620
+ html += `
3621
+ <tr>
3622
+ <td>${templateUtilities.capitalizeFirstLetter(obsName)}</td>
3623
+ <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
3624
+ <td>${templateUtilities.extractObservationValue(obs)}</td>
3625
+ <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
3626
+ <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
3627
+ <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3628
+ </tr>`;
3629
+ }
3588
3630
  }
3589
3631
  html += `
3590
3632
  </tbody>
@@ -3633,7 +3675,6 @@ var PastHistoryOfIllnessTemplate = class {
3633
3675
  <th>Onset Date</th>
3634
3676
  <th>Recorded Date</th>
3635
3677
  <th>Resolved Date</th>
3636
- <th>Source</th>
3637
3678
  </tr>
3638
3679
  </thead>
3639
3680
  <tbody>`;
@@ -3641,14 +3682,16 @@ var PastHistoryOfIllnessTemplate = class {
3641
3682
  for (const cond of filteredConditions) {
3642
3683
  const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(cond.code));
3643
3684
  if (!addedConditionCodes.has(conditionCode)) {
3685
+ if (conditionCode?.toLowerCase() === "unknown") {
3686
+ continue;
3687
+ }
3644
3688
  addedConditionCodes.add(conditionCode);
3645
3689
  html += `<tr>
3646
- <td class="Name">${conditionCode}</td>
3690
+ <td class="Name">${templateUtilities.capitalizeFirstLetter(conditionCode)}</td>
3647
3691
  <td class="CodeSystem">${templateUtilities.codeableConceptCoding(cond.code)}</td>
3648
3692
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
3649
3693
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
3650
3694
  <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
3651
- <td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
3652
3695
  </tr>`;
3653
3696
  }
3654
3697
  }
@@ -3689,19 +3732,21 @@ var PlanOfCareTemplate = class {
3689
3732
  <th>Comments</th>
3690
3733
  <th>Planned Start</th>
3691
3734
  <th>Planned End</th>
3692
- <th>Source</th>
3693
3735
  </tr>
3694
3736
  </thead>
3695
3737
  <tbody>`;
3696
3738
  for (const cp of carePlans) {
3739
+ const carePlanName = cp.description || cp.title || "";
3740
+ if (carePlanName.toLowerCase() === "unknown") {
3741
+ continue;
3742
+ }
3697
3743
  html += `
3698
- <tr id="${templateUtilities.narrativeLinkId(cp)}">
3699
- <td>${cp.description || cp.title || ""}</td>
3744
+ <tr>
3745
+ <td>${templateUtilities.capitalizeFirstLetter(carePlanName)}</td>
3700
3746
  <td>${cp.intent || ""}</td>
3701
3747
  <td>${templateUtilities.concat(cp.note, "text")}</td>
3702
3748
  <td>${cp.period?.start ? templateUtilities.renderTime(cp.period?.start, timezone) : ""}</td>
3703
3749
  <td>${cp.period?.end ? templateUtilities.renderTime(cp.period?.end, timezone) : ""}</td>
3704
- <td>${templateUtilities.getOwnerTag(cp)}</td>
3705
3750
  </tr>`;
3706
3751
  }
3707
3752
  html += `
@@ -3729,7 +3774,6 @@ var PlanOfCareTemplate = class {
3729
3774
  <th>Created</th>
3730
3775
  <th>Planned Start</th>
3731
3776
  <th>Planned End</th>
3732
- <th>Source</th>
3733
3777
  </tr>
3734
3778
  </thead>
3735
3779
  <tbody>`;
@@ -3744,14 +3788,16 @@ var PlanOfCareTemplate = class {
3744
3788
  if (data["status"] !== "active") {
3745
3789
  continue;
3746
3790
  }
3791
+ if (data["CarePlan Name"]?.toLowerCase() === "unknown") {
3792
+ continue;
3793
+ }
3747
3794
  isSummaryCreated = true;
3748
3795
  html += `
3749
3796
  <tr>
3750
- <td>${data["CarePlan Name"] ?? ""}</td>
3797
+ <td>${templateUtilities.capitalizeFirstLetter(data["CarePlan Name"] ?? "")}</td>
3751
3798
  <td>${templateUtilities.renderTime(data["created"], timezone) ?? ""}</td>
3752
3799
  <td>${templateUtilities.renderTime(data["period.start"], timezone) ?? ""}</td>
3753
3800
  <td>${templateUtilities.renderTime(data["period.end"], timezone) ?? ""}</td>
3754
- <td>${data["source"] ?? ""}</td>
3755
3801
  </tr>`;
3756
3802
  }
3757
3803
  }
@@ -3808,12 +3854,15 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3808
3854
  for (const obs of functionalObservations) {
3809
3855
  const observation = obs;
3810
3856
  const obsName = templateUtilities.codeableConceptDisplay(observation.code);
3857
+ if (obsName?.toLowerCase() === "unknown") {
3858
+ continue;
3859
+ }
3811
3860
  const value = templateUtilities.extractObservationValue(observation);
3812
3861
  const date = observation.effectiveDateTime ? templateUtilities.renderDate(observation.effectiveDateTime) : observation.issued ? templateUtilities.renderDate(observation.issued) : "";
3813
3862
  const interpretation = observation.interpretation ? templateUtilities.codeableConceptDisplay(observation.interpretation[0]) : "";
3814
3863
  const comments = observation.comment || observation.note?.map((n) => n.text).join("; ") || "";
3815
- html += `<tr id="${templateUtilities.narrativeLinkId(observation)}">
3816
- <td>${obsName}</td>
3864
+ html += `<tr>
3865
+ <td>${templateUtilities.capitalizeFirstLetter(obsName)}</td>
3817
3866
  <td>${value ?? ""}</td>
3818
3867
  <td>${date}</td>
3819
3868
  <td>${interpretation}</td>
@@ -3843,7 +3892,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3843
3892
  }
3844
3893
  findingsHtml += "</ul>";
3845
3894
  }
3846
- html += `<tr id="${templateUtilities.narrativeLinkId(impression)}">
3895
+ html += `<tr>
3847
3896
  <td>${formattedDate}</td>
3848
3897
  <td>${impression.status || ""}</td>
3849
3898
  <td>${impression.description || ""}</td>
@@ -3915,18 +3964,19 @@ var PregnancyTemplate = class _PregnancyTemplate {
3915
3964
  <th>Code (System)</th>
3916
3965
  <th>Comments</th>
3917
3966
  <th>Date</th>
3918
- <th>Source</th>
3919
3967
  </tr>
3920
3968
  </thead>
3921
3969
  <tbody>`;
3922
- function renderRow({ id, result, comments, date, codeSystem, owner }) {
3970
+ function renderRow({ result, comments, date, codeSystem }) {
3971
+ if (result?.toLowerCase() === "unknown") {
3972
+ return;
3973
+ }
3923
3974
  html += `
3924
- <tr id="${id}">
3925
- <td class="Result">${result}</td>
3975
+ <tr>
3976
+ <td class="Result">${templateUtilities.capitalizeFirstLetter(result)}</td>
3926
3977
  <td class="CodeSystem">${codeSystem}</td>
3927
3978
  <td class="Comments">${comments}</td>
3928
3979
  <td class="Date">${date}</td>
3929
- <td class="Source">${owner}</td>
3930
3980
  </tr>`;
3931
3981
  }
3932
3982
  const rowResources = [];
@@ -3953,9 +4003,9 @@ var PregnancyTemplate = class _PregnancyTemplate {
3953
4003
  if (!b.date) return -1;
3954
4004
  return new Date(b.date).getTime() - new Date(a.date).getTime();
3955
4005
  });
4006
+ const addedRows = /* @__PURE__ */ new Set();
3956
4007
  for (const { resource, date, type } of rowResources) {
3957
4008
  let result = "", comments = "", dateStr = "", codeSystem = "";
3958
- const id = templateUtilities.narrativeLinkId(resource);
3959
4009
  if (type === "status") {
3960
4010
  result = templateUtilities.renderTextAsHtml(templateUtilities.extractPregnancyStatus(resource));
3961
4011
  comments = templateUtilities.renderNotes(resource.note, timezone);
@@ -3977,8 +4027,11 @@ var PregnancyTemplate = class _PregnancyTemplate {
3977
4027
  dateStr = date ? templateUtilities.renderTextAsHtml(templateUtilities.renderTime(date, timezone)) : "";
3978
4028
  codeSystem = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptCoding(resource.code));
3979
4029
  }
3980
- const owner = templateUtilities.getOwnerTag(resource);
3981
- renderRow({ id, result, comments, date: dateStr, codeSystem, owner });
4030
+ const rowKey = `${result}|${codeSystem}`;
4031
+ if (!addedRows.has(rowKey)) {
4032
+ addedRows.add(rowKey);
4033
+ renderRow({ result, comments, date: dateStr, codeSystem });
4034
+ }
3982
4035
  }
3983
4036
  html += `
3984
4037
  </tbody>
@@ -4024,11 +4077,17 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
4024
4077
  </tr>
4025
4078
  </thead>
4026
4079
  <tbody>`;
4080
+ let isConsentAdded = false;
4027
4081
  for (const resourceItem of resources) {
4028
4082
  const consent = resourceItem;
4083
+ const consentScope = templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(consent.scope, "display")));
4084
+ if (!consentScope || consentScope.toLowerCase() === "unknown") {
4085
+ continue;
4086
+ }
4087
+ isConsentAdded = true;
4029
4088
  html += `
4030
4089
  <tr>
4031
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(consent.scope, "display"))}</td>
4090
+ <td>${consentScope}</td>
4032
4091
  <td>${consent.status || ""}</td>
4033
4092
  <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
4034
4093
  <td>${consent.dateTime || ""}</td>
@@ -4037,7 +4096,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
4037
4096
  html += `
4038
4097
  </tbody>
4039
4098
  </table>`;
4040
- return html;
4099
+ return isConsentAdded ? html : void 0;
4041
4100
  }
4042
4101
  };
4043
4102
 
@@ -4232,6 +4291,10 @@ var ComprehensiveIPSCompositionBuilder = class {
4232
4291
  * @param validResources - Array of domain resources
4233
4292
  */
4234
4293
  addSectionAsync(narrative, sectionType, validResources) {
4294
+ if (sectionType === "Patient" /* PATIENT */) {
4295
+ this.patientSummary = narrative;
4296
+ return this;
4297
+ }
4235
4298
  const sectionEntry = {
4236
4299
  title: IPS_SECTION_DISPLAY_NAMES[sectionType] || sectionType,
4237
4300
  code: {
@@ -4261,26 +4324,24 @@ var ComprehensiveIPSCompositionBuilder = class {
4261
4324
  for (const resource of validResources) {
4262
4325
  this.resources.add(resource);
4263
4326
  }
4264
- if (sectionType !== "Patient" /* PATIENT */) {
4265
- let narrative = void 0;
4266
- if (validResources.length > 0) {
4267
- narrative = await NarrativeGenerator.generateNarrativeAsync(
4268
- sectionType,
4269
- validResources,
4270
- timezone,
4271
- true
4272
- );
4273
- }
4274
- if (!narrative && sectionType in IPSMandatorySections) {
4275
- narrative = await NarrativeGenerator.createNarrativeAsync(
4276
- IPSMissingMandatorySectionContent[sectionType]
4277
- );
4278
- }
4279
- if (!narrative) {
4280
- return this;
4281
- }
4282
- this.addSectionAsync(narrative, sectionType, validResources);
4327
+ let narrative = void 0;
4328
+ if (validResources.length > 0) {
4329
+ narrative = await NarrativeGenerator.generateNarrativeAsync(
4330
+ sectionType,
4331
+ validResources,
4332
+ timezone,
4333
+ true
4334
+ );
4335
+ }
4336
+ if (!narrative && sectionType in IPSMandatorySections) {
4337
+ narrative = await NarrativeGenerator.createNarrativeAsync(
4338
+ IPSMissingMandatorySectionContent[sectionType]
4339
+ );
4283
4340
  }
4341
+ if (!narrative) {
4342
+ return this;
4343
+ }
4344
+ this.addSectionAsync(narrative, sectionType, validResources);
4284
4345
  return this;
4285
4346
  }
4286
4347
  async makeSectionFromSummaryAsync(sectionType, summaryCompositions, resources, timezone) {
@@ -4318,17 +4379,18 @@ var ComprehensiveIPSCompositionBuilder = class {
4318
4379
  * @param timezone - Optional timezone to use for date formatting
4319
4380
  * @param useSummaryCompositions - Whether to use summary compositions (default: false)
4320
4381
  */
4321
- async readBundleAsync(bundle, timezone, useSummaryCompositions = false) {
4382
+ async readBundleAsync(bundle, timezone, useSummaryCompositions = false, consoleLogger = console) {
4322
4383
  if (!bundle.entry) {
4323
4384
  return this;
4324
4385
  }
4325
4386
  const patientEntries = [];
4326
4387
  const resources = [];
4327
4388
  bundle.entry.forEach((e) => {
4328
- if (e.resource?.resourceType === "Patient") {
4329
- patientEntries.push(e.resource);
4330
- this.resources.add(e.resource);
4331
- } else if (e.resource) {
4389
+ if (e.resource) {
4390
+ if (e.resource.resourceType === "Patient") {
4391
+ patientEntries.push(e.resource);
4392
+ this.resources.add(e.resource);
4393
+ }
4332
4394
  resources.push(e.resource);
4333
4395
  }
4334
4396
  });
@@ -4337,20 +4399,20 @@ var ComprehensiveIPSCompositionBuilder = class {
4337
4399
  }
4338
4400
  this.patients = patientEntries;
4339
4401
  for (const sectionType of Object.values(IPSSections)) {
4340
- if (sectionType === "Patient" /* PATIENT */) {
4341
- continue;
4342
- }
4343
4402
  const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
4344
4403
  const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
4345
4404
  if (sectionIPSSummary.length > 0) {
4405
+ consoleLogger.info(`Using IPS summary composition for section: ${sectionType}`);
4346
4406
  await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
4347
4407
  continue;
4348
4408
  }
4349
4409
  const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
4350
4410
  const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
4351
4411
  if (sectionSummary.length > 0) {
4412
+ consoleLogger.info(`Using summary composition for section: ${sectionType}`);
4352
4413
  await this.makeSectionFromSummaryAsync(sectionType, sectionSummary, resources, timezone);
4353
4414
  } else {
4415
+ consoleLogger.info(`Using individual resources for section: ${sectionType}`);
4354
4416
  const sectionFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
4355
4417
  const sectionResources = resources.filter((resource) => sectionFilter(resource));
4356
4418
  await this.makeSectionAsync(sectionType, sectionResources, timezone);
@@ -4374,6 +4436,9 @@ var ComprehensiveIPSCompositionBuilder = class {
4374
4436
  if (!this.patients) {
4375
4437
  throw new Error("Patient resource must be set before building the bundle");
4376
4438
  }
4439
+ if (!this.patientSummary) {
4440
+ throw new Error("Patient summary narrative must be set before building the bundle");
4441
+ }
4377
4442
  const primaryPatientId = patientId ?? this.patients[0].id;
4378
4443
  const composition = {
4379
4444
  id: `Composition-${primaryPatientId}`,
@@ -4397,14 +4462,7 @@ var ComprehensiveIPSCompositionBuilder = class {
4397
4462
  date: (now || /* @__PURE__ */ new Date()).toISOString(),
4398
4463
  title: "International Patient Summary",
4399
4464
  section: this.sections,
4400
- text: await NarrativeGenerator.generateNarrativeAsync(
4401
- "Patient" /* PATIENT */,
4402
- this.patients,
4403
- timezone,
4404
- true,
4405
- false,
4406
- now
4407
- )
4465
+ text: this.patientSummary
4408
4466
  };
4409
4467
  const bundle = {
4410
4468
  resourceType: "Bundle",