@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.cjs CHANGED
@@ -197,7 +197,8 @@ var IPSSectionSummaryCompositionFilter = {
197
197
  ["HistoryOfProceduresSection" /* PROCEDURES */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "procedure_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
198
198
  };
199
199
  var IPSSectionSummaryIPSCompositionFilter = {
200
- ["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")
200
+ ["Patient" /* PATIENT */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_patient_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM)),
201
+ ["VitalSignsSection" /* VITAL_SIGNS */]: (resource) => resource.resourceType === "Composition" && resource.type?.coding?.some((c) => codingMatches(c, "ips_vital_summary_document", IPS_SUMMARY_COMPOSITION_TYPE_SYSTEM))
201
202
  };
202
203
  var IPSSectionResourceHelper = class {
203
204
  static getResourceFilterForSection(section) {
@@ -912,18 +913,6 @@ var TemplateUtilities = class {
912
913
  }
913
914
  return "";
914
915
  }
915
- /**
916
- * Returns the owner tag from the resource meta.security array.
917
- * @param resource - FHIR resource with meta tag
918
- * @returns The owner code if found, otherwise undefined
919
- */
920
- getOwnerTag(resource) {
921
- if (!resource?.meta?.security) return "";
922
- const ownerEntry = resource.meta.security.find(
923
- (sec) => sec.system === "https://www.icanbwell.com/owner" && !!sec.code
924
- );
925
- return ownerEntry?.code;
926
- }
927
916
  /**
928
917
  * Public method to render plain text as HTML, escaping special characters and replacing newlines with <br />.
929
918
  * This method should be used whenever displaying user-supplied or FHIR resource text in HTML to prevent XSS vulnerabilities
@@ -938,6 +927,23 @@ var TemplateUtilities = class {
938
927
  const escapedText = text.replace(/</g, "&lt;").replace(/>/g, "&gt;");
939
928
  return escapedText.replace(/\n/g, "<br />");
940
929
  }
930
+ capitalizeFirstLetter(text) {
931
+ if (!text || text.length === 0) {
932
+ return "";
933
+ }
934
+ return text.charAt(0).toUpperCase() + text.slice(1);
935
+ }
936
+ renderListSectionData(sectionData) {
937
+ if (!sectionData || !Array.isArray(sectionData) || sectionData.length === 0) {
938
+ return "";
939
+ }
940
+ const items = [];
941
+ for (const section of sectionData) {
942
+ items.push(this.renderTextAsHtml(section.text?.div || ""));
943
+ }
944
+ const listString = Array.from(items).map((item) => `<li>${item}</li>`).join("");
945
+ return `<ul>${listString}</ul>`;
946
+ }
941
947
  /**
942
948
  * Renders note elements from a FHIR resource in a standardized format
943
949
  * Can render as simple comma-separated text or as styled HTML with timestamps
@@ -1425,6 +1431,60 @@ var PatientTemplate = class _PatientTemplate {
1425
1431
  generateNarrative(resources, timezone) {
1426
1432
  return _PatientTemplate.generateStaticNarrative(resources, timezone);
1427
1433
  }
1434
+ /**
1435
+ * Generate HTML narrative for Patient resources using summary
1436
+ * @param resources - FHIR Composition resources
1437
+ * @param timezone - Optional timezone to use for date formatting (e.g., 'America/New_York', 'Europe/London')
1438
+ * @returns HTML string for rendering
1439
+ */
1440
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1441
+ generateSummaryNarrative(resources, timezone) {
1442
+ const templateUtilities = new TemplateUtilities(resources);
1443
+ const compositionResources = resources[0];
1444
+ const data = {};
1445
+ for (const rowData of compositionResources.section ?? []) {
1446
+ for (const columnData of rowData.section ?? []) {
1447
+ switch (columnData.title) {
1448
+ case "Name":
1449
+ case "Address":
1450
+ case "Communication":
1451
+ data[columnData.title] = templateUtilities.renderListSectionData(columnData.section ?? []);
1452
+ break;
1453
+ case "Telecom": {
1454
+ const telecomStringParts = [];
1455
+ for (const telecomData of columnData.section ?? []) {
1456
+ const telecomSystem = telecomData?.title;
1457
+ const telecomValue = templateUtilities.renderListSectionData(telecomData.section ?? []);
1458
+ if (telecomSystem && telecomValue) {
1459
+ telecomStringParts.push(`<li><strong>${telecomSystem}:</strong>${telecomValue}</li>`);
1460
+ }
1461
+ }
1462
+ data["Telecom"] = `<ul>${telecomStringParts.join("")}</ul>`;
1463
+ break;
1464
+ }
1465
+ default:
1466
+ if (columnData.title) {
1467
+ data[columnData.title] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1468
+ }
1469
+ break;
1470
+ }
1471
+ }
1472
+ }
1473
+ let html = `<p>This section merges all Patient resources into a single combined patient record, preferring non-empty values for each field.</p>`;
1474
+ html += `<div>
1475
+ <ul>
1476
+ <li><strong>Name(s):</strong>${data["Name"] || ""}</li>
1477
+ <li><strong>Gender:</strong>${data["Gender"] || ""}</li>
1478
+ <li><strong>Date of Birth:</strong>${data["Date of Birth"] || ""}</li>
1479
+ <li><strong>Telecom:</strong>${data["Telecom"] || ""}</li>
1480
+ <li><strong>Address(es):</strong>${data["Address"] || ""}</li>
1481
+ <li><strong>Marital Status:</strong> ${data["Marital Status"] || ""}</li>
1482
+ <li><strong>Deceased:</strong>${data["Deceased"] || ""}</li>
1483
+ <li><strong>Language(s):</strong>${data["Communication"] || ""}</li>
1484
+ </ul>
1485
+ </div>`;
1486
+ return html;
1487
+ }
1428
1488
  /**
1429
1489
  * Internal static implementation that actually generates the narrative
1430
1490
  * @param resources - FHIR Patient resources
@@ -1518,7 +1578,8 @@ var PatientTemplate = class _PatientTemplate {
1518
1578
  }
1519
1579
  }
1520
1580
  });
1521
- return Array.from(uniqueNames).map((nameText) => `<ul><li>${nameText}</li></ul>`).join("");
1581
+ const namesHtml = Array.from(uniqueNames).map((nameText) => `<li>${nameText}</li>`).join("");
1582
+ return `<ul>${namesHtml}</ul>`;
1522
1583
  }
1523
1584
  /**
1524
1585
  * Renders patient telecom information grouped by system
@@ -1622,7 +1683,8 @@ var PatientTemplate = class _PatientTemplate {
1622
1683
  }
1623
1684
  });
1624
1685
  const deduplicatedAddresses = this.deduplicateSimilarAddresses(Array.from(uniqueAddresses));
1625
- return deduplicatedAddresses.map((addressText) => `<ul><li>${addressText}</li></ul>`).join("");
1686
+ const addressesHtml = deduplicatedAddresses.map((addressText) => `<li>${addressText}</li>`).join("");
1687
+ return `<ul>${addressesHtml}</ul>`;
1626
1688
  }
1627
1689
  /**
1628
1690
  * Calculates the similarity between two strings using Levenshtein distance
@@ -1740,7 +1802,8 @@ var PatientTemplate = class _PatientTemplate {
1740
1802
  uniqueLanguages.add(language);
1741
1803
  }
1742
1804
  });
1743
- return Array.from(uniqueLanguages).map((language) => `<ul><li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li></ul>`).join("");
1805
+ const languagesHtml = Array.from(uniqueLanguages).map((language) => `<li>${language}${preferredLanguages.has(language) ? " (preferred)" : ""}</li>`).join("");
1806
+ return `<ul>${languagesHtml}</ul>`;
1744
1807
  }
1745
1808
  /**
1746
1809
  * Capitalizes first letter of a string
@@ -1784,7 +1847,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1784
1847
  <th>Code (System)</th>
1785
1848
  <th>Criticality</th>
1786
1849
  <th>Recorded Date</th>
1787
- <th>Source</th>
1788
1850
  </tr>
1789
1851
  </thead>
1790
1852
  <tbody>`;
@@ -1804,21 +1866,20 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1804
1866
  case "Recorded Date":
1805
1867
  data["recordedDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1806
1868
  break;
1807
- case "Source":
1808
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
1809
- break;
1810
1869
  default:
1811
1870
  break;
1812
1871
  }
1813
1872
  }
1873
+ if (data["allergen"]?.toLowerCase() === "unknown") {
1874
+ continue;
1875
+ }
1814
1876
  isSummaryCreated = true;
1815
1877
  html += `
1816
1878
  <tr>
1817
- <td>${data["allergen"] ?? ""}</td>
1879
+ <td>${templateUtilities.capitalizeFirstLetter(data["allergen"] ?? "")}</td>
1818
1880
  <td>${data["codeSystem"] ?? ""}</td>
1819
1881
  <td>${data["criticality"] ?? ""}</td>
1820
1882
  <td>${templateUtilities.renderTime(data["recordedDate"], timezone) ?? ""}</td>
1821
- <td>${data["source"] ?? ""}</td>
1822
1883
  </tr>`;
1823
1884
  }
1824
1885
  }
@@ -1872,7 +1933,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1872
1933
  <th>Reaction</th>
1873
1934
  <th>Onset Date</th>
1874
1935
  <th>Comments</th>
1875
- <th>Source</th>
1876
1936
  </tr>
1877
1937
  </thead>
1878
1938
  <tbody>`;
@@ -1902,7 +1962,6 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1902
1962
  <th>Onset Date</th>
1903
1963
  <th>Comments</th>
1904
1964
  <th>Resolved Date</th>
1905
- <th>Source</th>
1906
1965
  </tr>
1907
1966
  </thead>
1908
1967
  <tbody>`;
@@ -1931,16 +1990,19 @@ var AllergyIntoleranceTemplate = class _AllergyIntoleranceTemplate {
1931
1990
  static generateAllergyRows(allergies, templateUtilities, timezone, includeResolved = false) {
1932
1991
  let html = "";
1933
1992
  for (const allergy of allergies) {
1993
+ const allergenName = templateUtilities.codeableConceptDisplay(allergy.code);
1994
+ if (allergenName?.toLowerCase() === "unknown") {
1995
+ continue;
1996
+ }
1934
1997
  html += `
1935
- <tr id="${templateUtilities.narrativeLinkId(allergy.extension)}">
1936
- <td class="Name"><span class="AllergenName">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(allergy.code))}</span></td>
1998
+ <tr>
1999
+ <td class="Name"><span class="AllergenName">${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(allergenName))}</span></td>
1937
2000
  <td class="Status">${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(allergy.clinicalStatus)) || ""}</td>
1938
2001
  <td class="CodeSystem">${templateUtilities.codeableConceptCoding(allergy.code)}</td>
1939
2002
  <td class="Category">${templateUtilities.renderTextAsHtml(templateUtilities.safeConcat(allergy.category)) || ""}</td>
1940
2003
  <td class="Reaction">${templateUtilities.renderTextAsHtml(templateUtilities.concatReactionManifestation(allergy.reaction)) || ""}</td>
1941
2004
  <td class="OnsetDate">${templateUtilities.renderTextAsHtml(templateUtilities.renderTime(allergy.onsetDateTime, timezone)) || ""}</td>
1942
- <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>
1943
- <td class="Source">${templateUtilities.getOwnerTag(allergy)}</td>`;
2005
+ <td class="Comments">${templateUtilities.renderNotes(allergy.note, timezone, { styled: true, warning: true })}</td>`;
1944
2006
  if (includeResolved) {
1945
2007
  let endDate = "";
1946
2008
  if (allergy.extension && Array.isArray(allergy.extension)) {
@@ -1995,9 +2057,7 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
1995
2057
  <th>Status</th>
1996
2058
  <th>Sig</th>
1997
2059
  <th>Days of Supply</th>
1998
- <th>Refills</th>
1999
2060
  <th>Start Date</th>
2000
- <th>Source</th>
2001
2061
  </tr>
2002
2062
  </thead>
2003
2063
  <tbody>`;
@@ -2023,15 +2083,9 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2023
2083
  case "Days Of Supply":
2024
2084
  data["daysOfSupply"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2025
2085
  break;
2026
- case "Refills Remaining":
2027
- data["refills"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2028
- break;
2029
2086
  case "Authored On Date":
2030
2087
  data["startDate"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2031
2088
  break;
2032
- case "Source":
2033
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2034
- break;
2035
2089
  default:
2036
2090
  break;
2037
2091
  }
@@ -2047,17 +2101,18 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2047
2101
  skippedMedications++;
2048
2102
  }
2049
2103
  if (data["status"] === "active" || startDateObj && startDateObj >= twoYearsAgo) {
2104
+ if (data["medication"]?.toLowerCase() === "unknown") {
2105
+ continue;
2106
+ }
2050
2107
  isSummaryCreated = true;
2051
2108
  html += `
2052
2109
  <tr>
2053
- <td>${templateUtilities.renderTextAsHtml(data["medication"])}</td>
2110
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(data["medication"]))}</td>
2054
2111
  <td>${templateUtilities.codeableConceptCoding(sectionCodeableConcept)}</td>
2055
2112
  <td>${templateUtilities.renderTextAsHtml(data["status"])}</td>
2056
2113
  <td>${templateUtilities.renderTextAsHtml(data["sig-prescriber"] || data["sig-pharmacy"])}</td>
2057
2114
  <td>${templateUtilities.renderTextAsHtml(data["daysOfSupply"])}</td>
2058
- <td>${templateUtilities.renderTextAsHtml(data["refills"])}</td>
2059
2115
  <td>${templateUtilities.renderTime(data["startDate"], timezone)}</td>
2060
- <td>${templateUtilities.renderTextAsHtml(data["source"])}</td>
2061
2116
  </tr>`;
2062
2117
  }
2063
2118
  }
@@ -2097,8 +2152,8 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2097
2152
  static generateStaticNarrative(resources, timezone, now) {
2098
2153
  const templateUtilities = new TemplateUtilities(resources);
2099
2154
  let html = "";
2100
- const medicationRequests = this.getMedicationRequests(templateUtilities, resources);
2101
- const medicationStatements = this.getMedicationStatements(templateUtilities, resources);
2155
+ const medicationRequests = resources.filter((entry) => entry.resourceType === "MedicationRequest");
2156
+ const medicationStatements = resources.filter((entry) => entry.resourceType === "MedicationStatement");
2102
2157
  const allActiveMedications = [];
2103
2158
  const currentDate = now || /* @__PURE__ */ new Date();
2104
2159
  const twoYearsAgo = new Date(currentDate);
@@ -2106,10 +2161,10 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2106
2161
  let skippedMedications = 0;
2107
2162
  const allMedications = [];
2108
2163
  medicationRequests.forEach((mr) => {
2109
- allMedications.push({ type: "request", resource: mr.resource, extension: mr.extension });
2164
+ allMedications.push({ type: "request", resource: mr });
2110
2165
  });
2111
2166
  medicationStatements.forEach((ms) => {
2112
- allMedications.push({ type: "statement", resource: ms.resource, extension: ms.extension });
2167
+ allMedications.push({ type: "statement", resource: ms });
2113
2168
  });
2114
2169
  for (const med of allMedications) {
2115
2170
  let dateString;
@@ -2166,36 +2221,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2166
2221
  }
2167
2222
  return "";
2168
2223
  }
2169
- /**
2170
- * Extract MedicationRequest resources
2171
- * @param templateUtilities - Instance of TemplateUtilities for utility functions
2172
- * @param resources - FHIR Medication resources
2173
- * @returns Array of MedicationRequest resources
2174
- */
2175
- static getMedicationRequests(templateUtilities, resources) {
2176
- if (resources.length === 0) {
2177
- return [];
2178
- }
2179
- return resources.filter((entry) => entry.resourceType === "MedicationRequest").map((entry) => ({
2180
- resource: entry,
2181
- extension: templateUtilities.narrativeLinkExtension(entry)
2182
- }));
2183
- }
2184
- /**
2185
- * Extract MedicationStatement resources
2186
- * @param templateUtilities - Instance of TemplateUtilities for utility functions
2187
- * @param resources - FHIR Medication resources
2188
- * @returns Array of MedicationStatement resources
2189
- */
2190
- static getMedicationStatements(templateUtilities, resources) {
2191
- if (resources.length === 0) {
2192
- return [];
2193
- }
2194
- return resources.filter((entry) => entry.resourceType === "MedicationStatement").map((entry) => ({
2195
- resource: entry,
2196
- extension: templateUtilities.narrativeLinkExtension(entry)
2197
- }));
2198
- }
2199
2224
  /**
2200
2225
  * Render HTML table for combined MedicationRequest and MedicationStatement resources
2201
2226
  * @param templateUtilities - Instance of TemplateUtilities for utility functions
@@ -2212,19 +2237,15 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2212
2237
  <th>Code (System)</th>
2213
2238
  <th>Sig</th>
2214
2239
  <th>Dispense Quantity</th>
2215
- <th>Refills</th>
2216
2240
  <th>Start Date</th>
2217
- <th>Source</th>
2218
2241
  </tr>
2219
2242
  </thead>
2220
2243
  <tbody>`;
2221
2244
  for (const medication of medications) {
2222
- const narrativeLinkId = templateUtilities.narrativeLinkId(medication.extension);
2223
2245
  let type;
2224
2246
  let medicationName;
2225
2247
  let sig;
2226
2248
  let dispenseQuantity = "";
2227
- let refills = "";
2228
2249
  let startDate = "";
2229
2250
  let codeSystemDisplay = "";
2230
2251
  if (medication.type === "request") {
@@ -2240,7 +2261,6 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2240
2261
  dispenseQuantity = `${quantity.value} ${quantity.unit || quantity.code || ""}`.trim();
2241
2262
  }
2242
2263
  }
2243
- refills = mr.dispenseRequest?.numberOfRepeatsAllowed?.toString() || "";
2244
2264
  if (mr.dispenseRequest?.validityPeriod) {
2245
2265
  startDate = mr.dispenseRequest.validityPeriod.start || "";
2246
2266
  } else {
@@ -2265,16 +2285,17 @@ var MedicationSummaryTemplate = class _MedicationSummaryTemplate {
2265
2285
  codeSystemDisplay = templateUtilities.codeableConceptCoding(ms.medicationCodeableConcept);
2266
2286
  }
2267
2287
  }
2288
+ if (medicationName?.toLowerCase() === "unknown") {
2289
+ continue;
2290
+ }
2268
2291
  html += `
2269
- <tr${narrativeLinkId ? ` id="${narrativeLinkId}"` : ""}>
2292
+ <tr>
2270
2293
  <td>${type}</td>
2271
- <td>${medicationName}<ul></ul></td>
2294
+ <td>${templateUtilities.capitalizeFirstLetter(medicationName)}</td>
2272
2295
  <td>${codeSystemDisplay}</td>
2273
2296
  <td>${sig}</td>
2274
2297
  <td>${dispenseQuantity}</td>
2275
- <td>${refills}</td>
2276
2298
  <td>${startDate}</td>
2277
- <td>${templateUtilities.getOwnerTag(medication.resource)}</td>
2278
2299
  </tr>`;
2279
2300
  }
2280
2301
  html += `
@@ -2319,7 +2340,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2319
2340
  <th>Code (System)</th>
2320
2341
  <th>Status</th>
2321
2342
  <th>Date</th>
2322
- <th>Source</th>
2323
2343
  </tr>
2324
2344
  </thead>
2325
2345
  <tbody>`;
@@ -2339,22 +2359,21 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2339
2359
  case "occurrenceDateTime":
2340
2360
  data["occurrenceDateTime"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2341
2361
  break;
2342
- case "Source":
2343
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2344
- break;
2345
2362
  default:
2346
2363
  break;
2347
2364
  }
2348
2365
  }
2349
2366
  if (data["status"] === "completed") {
2367
+ if (data["immunization"]?.toLowerCase() === "unknown") {
2368
+ continue;
2369
+ }
2350
2370
  isSummaryCreated = true;
2351
2371
  html += `
2352
2372
  <tr>
2353
- <td>${data["immunization"] ?? ""}</td>
2373
+ <td>${templateUtilities.capitalizeFirstLetter(data["immunization"] ?? "")}</td>
2354
2374
  <td>${data["codeSystem"] ?? ""}</td>
2355
2375
  <td>${data["status"] ?? ""}</td>
2356
2376
  <td>${templateUtilities.renderTime(data["occurrenceDateTime"], timezone) ?? ""}</td>
2357
- <td>${data["source"] ?? ""}</td>
2358
2377
  </tr>`;
2359
2378
  }
2360
2379
  }
@@ -2385,7 +2404,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2385
2404
  <th>Lot Number</th>
2386
2405
  <th>Comments</th>
2387
2406
  <th>Date</th>
2388
- <th>Source</th>
2389
2407
  </tr>
2390
2408
  </thead>
2391
2409
  <tbody>`;
@@ -2393,9 +2411,13 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2393
2411
  if (immunizations.length > 0) {
2394
2412
  for (const resourceItem of immunizations) {
2395
2413
  const imm = resourceItem;
2414
+ const immunizationName = templateUtilities.codeableConceptDisplay(imm.vaccineCode);
2415
+ if (immunizationName?.toLowerCase() === "unknown") {
2416
+ continue;
2417
+ }
2396
2418
  html += `
2397
2419
  <tr>
2398
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(imm.vaccineCode))}</td>
2420
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(immunizationName))}</td>
2399
2421
  <td>${templateUtilities.codeableConceptCoding(imm.vaccineCode)}</td>
2400
2422
  <td>${imm.status || ""}</td>
2401
2423
  <td>${templateUtilities.concatDoseNumber(imm.protocolApplied)}</td>
@@ -2403,7 +2425,6 @@ var ImmunizationsTemplate = class _ImmunizationsTemplate {
2403
2425
  <td>${imm.lotNumber || ""}</td>
2404
2426
  <td>${templateUtilities.renderNotes(imm.note, timezone)}</td>
2405
2427
  <td>${templateUtilities.renderTime(imm.occurrenceDateTime, timezone)}</td>
2406
- <td>${templateUtilities.getOwnerTag(imm)}</td>
2407
2428
  </tr>`;
2408
2429
  }
2409
2430
  }
@@ -2453,7 +2474,6 @@ var ProblemListTemplate = class _ProblemListTemplate {
2453
2474
  <th>Code (System)</th>
2454
2475
  <th>Onset Date</th>
2455
2476
  <th>Recorded Date</th>
2456
- <th>Source</th>
2457
2477
  </tr>
2458
2478
  </thead>
2459
2479
  <tbody>`;
@@ -2464,13 +2484,15 @@ var ProblemListTemplate = class _ProblemListTemplate {
2464
2484
  if (codeAndSystem && seenCodeAndSystems.has(codeAndSystem)) {
2465
2485
  continue;
2466
2486
  }
2487
+ if (conditionDisplay?.toLowerCase() === "unknown") {
2488
+ continue;
2489
+ }
2467
2490
  seenCodeAndSystems.add(codeAndSystem);
2468
2491
  html += `<tr>
2469
- <td class="Name">${conditionDisplay}</td>
2492
+ <td class="Name">${templateUtilities.capitalizeFirstLetter(conditionDisplay)}</td>
2470
2493
  <td class="CodeSystem">${codeAndSystem}</td>
2471
2494
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
2472
2495
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
2473
- <td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
2474
2496
  </tr>`;
2475
2497
  }
2476
2498
  html += `</tbody>
@@ -2510,7 +2532,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2510
2532
  <th>Code (System)</th>
2511
2533
  <th>Result</th>
2512
2534
  <th>Date</th>
2513
- <th>Source</th>
2514
2535
  </tr>
2515
2536
  </thead>
2516
2537
  <tbody>`;
@@ -2543,14 +2564,16 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2543
2564
  data[columnTitle] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
2544
2565
  }
2545
2566
  }
2567
+ if (data["Vital Name"]?.toLowerCase() === "unknown") {
2568
+ continue;
2569
+ }
2546
2570
  isSummaryCreated = true;
2547
2571
  html += `
2548
2572
  <tr>
2549
- <td>${data["Vital Name"] ?? ""}</td>
2573
+ <td>${templateUtilities.capitalizeFirstLetter(data["Vital Name"] ?? "")}</td>
2550
2574
  <td>${data["codeSystem"] ?? ""}</td>
2551
2575
  <td>${templateUtilities.extractObservationSummaryValue(data, timezone) ?? ""}</td>
2552
2576
  <td>${templateUtilities.extractObservationSummaryEffectiveTime(data, timezone) ?? ""}</td>
2553
- <td>${data["Source"] ?? ""}</td>
2554
2577
  </tr>`;
2555
2578
  }
2556
2579
  }
@@ -2588,14 +2611,17 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2588
2611
  <th>Component(s)</th>
2589
2612
  <th>Comments</th>
2590
2613
  <th>Date</th>
2591
- <th>Source</th>
2592
2614
  </tr>
2593
2615
  </thead>
2594
2616
  <tbody>`;
2595
2617
  for (const obs of observations) {
2618
+ const vitalName = templateUtilities.codeableConceptDisplay(obs.code, "display");
2619
+ if (vitalName?.toLowerCase() === "unknown") {
2620
+ continue;
2621
+ }
2596
2622
  html += `
2597
2623
  <tr>
2598
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code, "display"))}</td>
2624
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(vitalName))}</td>
2599
2625
  <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
2600
2626
  <td>${templateUtilities.extractObservationValue(obs)}</td>
2601
2627
  <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
@@ -2603,7 +2629,6 @@ var VitalSignsTemplate = class _VitalSignsTemplate {
2603
2629
  <td>${templateUtilities.renderComponent(obs.component)}</td>
2604
2630
  <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
2605
2631
  <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
2606
- <td>${templateUtilities.getOwnerTag(obs)}</td>
2607
2632
  </tr>`;
2608
2633
  }
2609
2634
  html += `
@@ -2648,10 +2673,16 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
2648
2673
  const dateB = b.recordedOn;
2649
2674
  return typeof dateA === "string" && typeof dateB === "string" ? new Date(dateB).getTime() - new Date(dateA).getTime() : 0;
2650
2675
  });
2676
+ let isDeviceAdded = false;
2651
2677
  for (const dus of deviceStatements) {
2678
+ const deviceName = templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device));
2679
+ if (deviceName?.toLowerCase() === "unknown") {
2680
+ continue;
2681
+ }
2682
+ isDeviceAdded = true;
2652
2683
  html += `
2653
2684
  <tr>
2654
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderDevice(dus.device))}</td>
2685
+ <td>${templateUtilities.capitalizeFirstLetter(deviceName)}</td>
2655
2686
  <td>${templateUtilities.renderTextAsHtml(dus.status || "")}</td>
2656
2687
  <td>${templateUtilities.renderNotes(dus.note, timezone)}</td>
2657
2688
  <td>${templateUtilities.renderTextAsHtml(templateUtilities.renderRecorded(dus.recordedOn, timezone))}</td>
@@ -2660,7 +2691,7 @@ var MedicalDevicesTemplate = class _MedicalDevicesTemplate {
2660
2691
  html += `
2661
2692
  </tbody>
2662
2693
  </table>`;
2663
- return html;
2694
+ return isDeviceAdded ? html : void 0;
2664
2695
  }
2665
2696
  };
2666
2697
 
@@ -3025,7 +3056,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3025
3056
  <th>Result</th>
3026
3057
  <th>Reference Range</th>
3027
3058
  <th>Date</th>
3028
- <th>Source</th>
3029
3059
  </tr>
3030
3060
  </thead>
3031
3061
  <tbody>`;
@@ -3039,7 +3069,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3039
3069
  <th>Report</th>
3040
3070
  <th>Performer</th>
3041
3071
  <th>Issued</th>
3042
- <th>Source</th>
3043
3072
  </tr>
3044
3073
  </thead>
3045
3074
  <tbody>`;
@@ -3086,8 +3115,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3086
3115
  case "Status":
3087
3116
  data["status"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3088
3117
  break;
3089
- case "Source":
3090
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3091
3118
  break;
3092
3119
  default:
3093
3120
  break;
@@ -3113,16 +3140,18 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3113
3140
  for (const component of components) {
3114
3141
  const componentCode = `${groupName}${component["code"] ?? ""}`;
3115
3142
  if (componentCode && !observationAdded.has(componentCode)) {
3143
+ if (component["code"]?.toLowerCase() === "unknown") {
3144
+ continue;
3145
+ }
3116
3146
  observationAdded.add(componentCode);
3117
3147
  this.formatSummaryObservationData(component);
3118
3148
  observationhtml += `
3119
3149
  <tr>
3120
- <td>${componentCode}</td>
3150
+ <td>${templateUtilities.capitalizeFirstLetter(componentCode)}</td>
3121
3151
  <td></td>
3122
3152
  <td>${templateUtilities.renderTextAsHtml(component["formattedValue"]) ?? ""}</td>
3123
3153
  <td>${templateUtilities.renderTextAsHtml(component["referenceRange"])?.trim() ?? ""}</td>
3124
3154
  <td>${date ?? ""}</td>
3125
- <td>${data["source"] ?? ""}</td>
3126
3155
  </tr>`;
3127
3156
  }
3128
3157
  }
@@ -3130,16 +3159,18 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3130
3159
  if (obsDate && obsDate >= twoYearsAgo) {
3131
3160
  const code = data["code"] ?? "";
3132
3161
  if (code && !observationAdded.has(code)) {
3162
+ if (code.toLowerCase() === "unknown") {
3163
+ continue;
3164
+ }
3133
3165
  observationAdded.add(code);
3134
3166
  this.formatSummaryObservationData(data);
3135
3167
  observationhtml += `
3136
3168
  <tr>
3137
- <td>${data["code"] ?? ""}</td>
3169
+ <td>${templateUtilities.capitalizeFirstLetter(data["code"] ?? "")}</td>
3138
3170
  <td>${templateUtilities.codeableConceptCoding(sectionCodeableConcept)}</td>
3139
3171
  <td>${templateUtilities.renderTextAsHtml(data["formattedValue"]) ?? ""}</td>
3140
3172
  <td>${templateUtilities.renderTextAsHtml(data["referenceRange"])?.trim() ?? ""}</td>
3141
3173
  <td>${date ?? ""}</td>
3142
- <td>${data["source"] ?? ""}</td>
3143
3174
  </tr>`;
3144
3175
  }
3145
3176
  }
@@ -3152,13 +3183,15 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3152
3183
  if (data["status"] === "final" && issuedDate && issuedDate >= twoYearsAgo) {
3153
3184
  const reportName = data["report"] ?? "";
3154
3185
  if (reportName && !diagnosticReportAdded.has(reportName)) {
3186
+ if (reportName.toLowerCase() === "unknown") {
3187
+ continue;
3188
+ }
3155
3189
  diagnosticReportAdded.add(reportName);
3156
3190
  diagnosticReporthtml += `
3157
3191
  <tr>
3158
- <td>${data["report"] ?? ""}</td>
3192
+ <td>${templateUtilities.capitalizeFirstLetter(data["report"] ?? "")}</td>
3159
3193
  <td>${data["performer"] ?? ""}</td>
3160
3194
  <td>${templateUtilities.renderTime(data["issued"], timezone) ?? ""}</td>
3161
- <td>${data["source"] ?? ""}</td>
3162
3195
  </tr>`;
3163
3196
  }
3164
3197
  }
@@ -3343,7 +3376,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3343
3376
  <th>Result</th>
3344
3377
  <th>Reference Range</th>
3345
3378
  <th>Date</th>
3346
- <th>Source</th>
3347
3379
  </tr>
3348
3380
  </thead>
3349
3381
  <tbody>`;
@@ -3352,16 +3384,18 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3352
3384
  const obsCodeDisplay = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
3353
3385
  const obsCodeAndSystem = templateUtilities.codeableConceptCoding(obs.code);
3354
3386
  if (!observationAdded.has(obsCodeDisplay) && !observationAdded.has(obsCodeAndSystem)) {
3387
+ if (obsCodeDisplay?.toLowerCase() === "unknown") {
3388
+ continue;
3389
+ }
3355
3390
  observationAdded.add(obsCodeDisplay);
3356
3391
  observationAdded.add(obsCodeAndSystem);
3357
3392
  html += `
3358
- <tr id="${templateUtilities.narrativeLinkId(obs)}">
3359
- <td>${obsCodeDisplay}</td>
3393
+ <tr>
3394
+ <td>${templateUtilities.capitalizeFirstLetter(obsCodeDisplay)}</td>
3360
3395
  <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
3361
3396
  <td>${templateUtilities.extractObservationValue(obs)}</td>
3362
3397
  <td>${templateUtilities.concatReferenceRange(obs.referenceRange)}</td>
3363
3398
  <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3364
- <td>${templateUtilities.getOwnerTag(obs)}</td>
3365
3399
  </tr>`;
3366
3400
  }
3367
3401
  }
@@ -3388,7 +3422,6 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3388
3422
  <th>Category</th>
3389
3423
  <th>Result</th>
3390
3424
  <th>Issued</th>
3391
- <th>Source</th>
3392
3425
  </tr>
3393
3426
  </thead>
3394
3427
  <tbody>`;
@@ -3397,6 +3430,9 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3397
3430
  const reportName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(report.code));
3398
3431
  const codeAndSystem = templateUtilities.codeableConceptCoding(report.code);
3399
3432
  if (!diagnosticReportAdded.has(reportName) && !diagnosticReportAdded.has(codeAndSystem)) {
3433
+ if (reportName?.toLowerCase() === "unknown") {
3434
+ continue;
3435
+ }
3400
3436
  diagnosticReportAdded.add(reportName);
3401
3437
  diagnosticReportAdded.add(codeAndSystem);
3402
3438
  let resultCount = "";
@@ -3404,13 +3440,12 @@ var DiagnosticResultsTemplate = class _DiagnosticResultsTemplate {
3404
3440
  resultCount = `${report.result.length} result${report.result.length !== 1 ? "s" : ""}`;
3405
3441
  }
3406
3442
  html += `
3407
- <tr id="${templateUtilities.narrativeLinkId(report)}">
3408
- <td>${reportName}</td>
3443
+ <tr>
3444
+ <td>${templateUtilities.capitalizeFirstLetter(reportName)}</td>
3409
3445
  <td>${codeAndSystem}</td>
3410
3446
  <td>${templateUtilities.firstFromCodeableConceptList(report.category)}</td>
3411
3447
  <td>${resultCount}</td>
3412
3448
  <td>${report.issued ? templateUtilities.renderTime(report.issued, timezone) : ""}</td>
3413
- <td>${templateUtilities.getOwnerTag(report)}</td>
3414
3449
  </tr>`;
3415
3450
  }
3416
3451
  }
@@ -3477,7 +3512,6 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3477
3512
  <th>Code (System)</th>
3478
3513
  <th>Performer</th>
3479
3514
  <th>Date</th>
3480
- <th>Source</th>
3481
3515
  </tr>
3482
3516
  </thead>
3483
3517
  <tbody>`;
@@ -3497,21 +3531,21 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3497
3531
  case "Performed Date":
3498
3532
  data["date"] = columnData.text?.div ?? "";
3499
3533
  break;
3500
- case "Source":
3501
- data["source"] = templateUtilities.renderTextAsHtml(columnData.text?.div ?? "");
3502
3534
  break;
3503
3535
  default:
3504
3536
  break;
3505
3537
  }
3506
3538
  }
3539
+ if (data["procedure"]?.toLowerCase() === "unknown") {
3540
+ continue;
3541
+ }
3507
3542
  isSummaryCreated = true;
3508
3543
  html += `
3509
3544
  <tr>
3510
- <td>${data["procedure"] ?? ""}</td>
3545
+ <td>${templateUtilities.capitalizeFirstLetter(data["procedure"] ?? "")}</td>
3511
3546
  <td>${data["codeSystem"] ?? ""}</td>
3512
3547
  <td>${data["performer"] ?? ""}</td>
3513
3548
  <td>${templateUtilities.renderTime(data["date"], timezone) ?? ""}</td>
3514
- <td>${data["source"] ?? ""}</td>
3515
3549
  </tr>`;
3516
3550
  }
3517
3551
  }
@@ -3539,19 +3573,21 @@ var HistoryOfProceduresTemplate = class _HistoryOfProceduresTemplate {
3539
3573
  <th>Code (System)</th>
3540
3574
  <th>Comments</th>
3541
3575
  <th>Date</th>
3542
- <th>Source</th>
3543
3576
  </tr>
3544
3577
  </thead>
3545
3578
  <tbody>`;
3546
3579
  for (const resourceItem of resources) {
3547
3580
  const proc = resourceItem;
3581
+ const procedureName = templateUtilities.codeableConceptDisplay(proc.code, "display");
3582
+ if (procedureName?.toLowerCase() === "unknown") {
3583
+ continue;
3584
+ }
3548
3585
  html += `
3549
3586
  <tr>
3550
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(proc.code, "display"))}</td>
3587
+ <td>${templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(procedureName))}</td>
3551
3588
  <td>${templateUtilities.codeableConceptCoding(proc.code)}</td>
3552
3589
  <td>${templateUtilities.renderNotes(proc.note, timezone)}</td>
3553
3590
  <td>${templateUtilities.renderTime(proc.performedDateTime || proc.performedPeriod?.start, timezone)}</td>
3554
- <td>${templateUtilities.getOwnerTag(proc)}</td>
3555
3591
  </tr>`;
3556
3592
  }
3557
3593
  html += `
@@ -3598,21 +3634,27 @@ var SocialHistoryTemplate = class _SocialHistoryTemplate {
3598
3634
  <th>Unit</th>
3599
3635
  <th>Comments</th>
3600
3636
  <th>Date</th>
3601
- <th>Source</th>
3602
3637
  </tr>
3603
3638
  </thead>
3604
3639
  <tbody>`;
3640
+ const addedObservations = /* @__PURE__ */ new Set();
3605
3641
  for (const obs of observations) {
3606
- html += `
3607
- <tr>
3608
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code))}</td>
3609
- <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
3610
- <td>${templateUtilities.extractObservationValue(obs)}</td>
3611
- <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
3612
- <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
3613
- <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3614
- <td>${templateUtilities.getOwnerTag(obs)}</td>
3615
- </tr>`;
3642
+ const obsName = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(obs.code));
3643
+ if (!addedObservations.has(obsName)) {
3644
+ if (obsName?.toLowerCase() === "unknown") {
3645
+ continue;
3646
+ }
3647
+ addedObservations.add(obsName);
3648
+ html += `
3649
+ <tr>
3650
+ <td>${templateUtilities.capitalizeFirstLetter(obsName)}</td>
3651
+ <td>${templateUtilities.codeableConceptCoding(obs.code)}</td>
3652
+ <td>${templateUtilities.extractObservationValue(obs)}</td>
3653
+ <td>${templateUtilities.extractObservationValueUnit(obs)}</td>
3654
+ <td>${templateUtilities.renderNotes(obs.note, timezone)}</td>
3655
+ <td>${obs.effectiveDateTime ? templateUtilities.renderTime(obs.effectiveDateTime, timezone) : obs.effectivePeriod ? templateUtilities.renderPeriod(obs.effectivePeriod, timezone) : ""}</td>
3656
+ </tr>`;
3657
+ }
3616
3658
  }
3617
3659
  html += `
3618
3660
  </tbody>
@@ -3661,7 +3703,6 @@ var PastHistoryOfIllnessTemplate = class {
3661
3703
  <th>Onset Date</th>
3662
3704
  <th>Recorded Date</th>
3663
3705
  <th>Resolved Date</th>
3664
- <th>Source</th>
3665
3706
  </tr>
3666
3707
  </thead>
3667
3708
  <tbody>`;
@@ -3669,14 +3710,16 @@ var PastHistoryOfIllnessTemplate = class {
3669
3710
  for (const cond of filteredConditions) {
3670
3711
  const conditionCode = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(cond.code));
3671
3712
  if (!addedConditionCodes.has(conditionCode)) {
3713
+ if (conditionCode?.toLowerCase() === "unknown") {
3714
+ continue;
3715
+ }
3672
3716
  addedConditionCodes.add(conditionCode);
3673
3717
  html += `<tr>
3674
- <td class="Name">${conditionCode}</td>
3718
+ <td class="Name">${templateUtilities.capitalizeFirstLetter(conditionCode)}</td>
3675
3719
  <td class="CodeSystem">${templateUtilities.codeableConceptCoding(cond.code)}</td>
3676
3720
  <td class="OnsetDate">${templateUtilities.renderDate(cond.onsetDateTime)}</td>
3677
3721
  <td class="RecordedDate">${templateUtilities.renderDate(cond.recordedDate)}</td>
3678
3722
  <td class="ResolvedDate">${templateUtilities.renderDate(cond.abatementDateTime)}</td>
3679
- <td class="Source">${templateUtilities.getOwnerTag(cond)}</td>
3680
3723
  </tr>`;
3681
3724
  }
3682
3725
  }
@@ -3717,19 +3760,21 @@ var PlanOfCareTemplate = class {
3717
3760
  <th>Comments</th>
3718
3761
  <th>Planned Start</th>
3719
3762
  <th>Planned End</th>
3720
- <th>Source</th>
3721
3763
  </tr>
3722
3764
  </thead>
3723
3765
  <tbody>`;
3724
3766
  for (const cp of carePlans) {
3767
+ const carePlanName = cp.description || cp.title || "";
3768
+ if (carePlanName.toLowerCase() === "unknown") {
3769
+ continue;
3770
+ }
3725
3771
  html += `
3726
- <tr id="${templateUtilities.narrativeLinkId(cp)}">
3727
- <td>${cp.description || cp.title || ""}</td>
3772
+ <tr>
3773
+ <td>${templateUtilities.capitalizeFirstLetter(carePlanName)}</td>
3728
3774
  <td>${cp.intent || ""}</td>
3729
3775
  <td>${templateUtilities.concat(cp.note, "text")}</td>
3730
3776
  <td>${cp.period?.start ? templateUtilities.renderTime(cp.period?.start, timezone) : ""}</td>
3731
3777
  <td>${cp.period?.end ? templateUtilities.renderTime(cp.period?.end, timezone) : ""}</td>
3732
- <td>${templateUtilities.getOwnerTag(cp)}</td>
3733
3778
  </tr>`;
3734
3779
  }
3735
3780
  html += `
@@ -3757,7 +3802,6 @@ var PlanOfCareTemplate = class {
3757
3802
  <th>Created</th>
3758
3803
  <th>Planned Start</th>
3759
3804
  <th>Planned End</th>
3760
- <th>Source</th>
3761
3805
  </tr>
3762
3806
  </thead>
3763
3807
  <tbody>`;
@@ -3772,14 +3816,16 @@ var PlanOfCareTemplate = class {
3772
3816
  if (data["status"] !== "active") {
3773
3817
  continue;
3774
3818
  }
3819
+ if (data["CarePlan Name"]?.toLowerCase() === "unknown") {
3820
+ continue;
3821
+ }
3775
3822
  isSummaryCreated = true;
3776
3823
  html += `
3777
3824
  <tr>
3778
- <td>${data["CarePlan Name"] ?? ""}</td>
3825
+ <td>${templateUtilities.capitalizeFirstLetter(data["CarePlan Name"] ?? "")}</td>
3779
3826
  <td>${templateUtilities.renderTime(data["created"], timezone) ?? ""}</td>
3780
3827
  <td>${templateUtilities.renderTime(data["period.start"], timezone) ?? ""}</td>
3781
3828
  <td>${templateUtilities.renderTime(data["period.end"], timezone) ?? ""}</td>
3782
- <td>${data["source"] ?? ""}</td>
3783
3829
  </tr>`;
3784
3830
  }
3785
3831
  }
@@ -3836,12 +3882,15 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3836
3882
  for (const obs of functionalObservations) {
3837
3883
  const observation = obs;
3838
3884
  const obsName = templateUtilities.codeableConceptDisplay(observation.code);
3885
+ if (obsName?.toLowerCase() === "unknown") {
3886
+ continue;
3887
+ }
3839
3888
  const value = templateUtilities.extractObservationValue(observation);
3840
3889
  const date = observation.effectiveDateTime ? templateUtilities.renderDate(observation.effectiveDateTime) : observation.issued ? templateUtilities.renderDate(observation.issued) : "";
3841
3890
  const interpretation = observation.interpretation ? templateUtilities.codeableConceptDisplay(observation.interpretation[0]) : "";
3842
3891
  const comments = observation.comment || observation.note?.map((n) => n.text).join("; ") || "";
3843
- html += `<tr id="${templateUtilities.narrativeLinkId(observation)}">
3844
- <td>${obsName}</td>
3892
+ html += `<tr>
3893
+ <td>${templateUtilities.capitalizeFirstLetter(obsName)}</td>
3845
3894
  <td>${value ?? ""}</td>
3846
3895
  <td>${date}</td>
3847
3896
  <td>${interpretation}</td>
@@ -3871,7 +3920,7 @@ var FunctionalStatusTemplate = class _FunctionalStatusTemplate {
3871
3920
  }
3872
3921
  findingsHtml += "</ul>";
3873
3922
  }
3874
- html += `<tr id="${templateUtilities.narrativeLinkId(impression)}">
3923
+ html += `<tr>
3875
3924
  <td>${formattedDate}</td>
3876
3925
  <td>${impression.status || ""}</td>
3877
3926
  <td>${impression.description || ""}</td>
@@ -3943,18 +3992,19 @@ var PregnancyTemplate = class _PregnancyTemplate {
3943
3992
  <th>Code (System)</th>
3944
3993
  <th>Comments</th>
3945
3994
  <th>Date</th>
3946
- <th>Source</th>
3947
3995
  </tr>
3948
3996
  </thead>
3949
3997
  <tbody>`;
3950
- function renderRow({ id, result, comments, date, codeSystem, owner }) {
3998
+ function renderRow({ result, comments, date, codeSystem }) {
3999
+ if (result?.toLowerCase() === "unknown") {
4000
+ return;
4001
+ }
3951
4002
  html += `
3952
- <tr id="${id}">
3953
- <td class="Result">${result}</td>
4003
+ <tr>
4004
+ <td class="Result">${templateUtilities.capitalizeFirstLetter(result)}</td>
3954
4005
  <td class="CodeSystem">${codeSystem}</td>
3955
4006
  <td class="Comments">${comments}</td>
3956
4007
  <td class="Date">${date}</td>
3957
- <td class="Source">${owner}</td>
3958
4008
  </tr>`;
3959
4009
  }
3960
4010
  const rowResources = [];
@@ -3981,9 +4031,9 @@ var PregnancyTemplate = class _PregnancyTemplate {
3981
4031
  if (!b.date) return -1;
3982
4032
  return new Date(b.date).getTime() - new Date(a.date).getTime();
3983
4033
  });
4034
+ const addedRows = /* @__PURE__ */ new Set();
3984
4035
  for (const { resource, date, type } of rowResources) {
3985
4036
  let result = "", comments = "", dateStr = "", codeSystem = "";
3986
- const id = templateUtilities.narrativeLinkId(resource);
3987
4037
  if (type === "status") {
3988
4038
  result = templateUtilities.renderTextAsHtml(templateUtilities.extractPregnancyStatus(resource));
3989
4039
  comments = templateUtilities.renderNotes(resource.note, timezone);
@@ -4005,8 +4055,11 @@ var PregnancyTemplate = class _PregnancyTemplate {
4005
4055
  dateStr = date ? templateUtilities.renderTextAsHtml(templateUtilities.renderTime(date, timezone)) : "";
4006
4056
  codeSystem = templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptCoding(resource.code));
4007
4057
  }
4008
- const owner = templateUtilities.getOwnerTag(resource);
4009
- renderRow({ id, result, comments, date: dateStr, codeSystem, owner });
4058
+ const rowKey = `${result}|${codeSystem}`;
4059
+ if (!addedRows.has(rowKey)) {
4060
+ addedRows.add(rowKey);
4061
+ renderRow({ result, comments, date: dateStr, codeSystem });
4062
+ }
4010
4063
  }
4011
4064
  html += `
4012
4065
  </tbody>
@@ -4052,11 +4105,17 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
4052
4105
  </tr>
4053
4106
  </thead>
4054
4107
  <tbody>`;
4108
+ let isConsentAdded = false;
4055
4109
  for (const resourceItem of resources) {
4056
4110
  const consent = resourceItem;
4111
+ const consentScope = templateUtilities.capitalizeFirstLetter(templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(consent.scope, "display")));
4112
+ if (!consentScope || consentScope.toLowerCase() === "unknown") {
4113
+ continue;
4114
+ }
4115
+ isConsentAdded = true;
4057
4116
  html += `
4058
4117
  <tr>
4059
- <td>${templateUtilities.renderTextAsHtml(templateUtilities.codeableConceptDisplay(consent.scope, "display"))}</td>
4118
+ <td>${consentScope}</td>
4060
4119
  <td>${consent.status || ""}</td>
4061
4120
  <td>${consent.provision?.action ? templateUtilities.concatCodeableConcept(consent.provision.action) : ""}</td>
4062
4121
  <td>${consent.dateTime || ""}</td>
@@ -4065,7 +4124,7 @@ var AdvanceDirectivesTemplate = class _AdvanceDirectivesTemplate {
4065
4124
  html += `
4066
4125
  </tbody>
4067
4126
  </table>`;
4068
- return html;
4127
+ return isConsentAdded ? html : void 0;
4069
4128
  }
4070
4129
  };
4071
4130
 
@@ -4260,6 +4319,10 @@ var ComprehensiveIPSCompositionBuilder = class {
4260
4319
  * @param validResources - Array of domain resources
4261
4320
  */
4262
4321
  addSectionAsync(narrative, sectionType, validResources) {
4322
+ if (sectionType === "Patient" /* PATIENT */) {
4323
+ this.patientSummary = narrative;
4324
+ return this;
4325
+ }
4263
4326
  const sectionEntry = {
4264
4327
  title: IPS_SECTION_DISPLAY_NAMES[sectionType] || sectionType,
4265
4328
  code: {
@@ -4289,26 +4352,24 @@ var ComprehensiveIPSCompositionBuilder = class {
4289
4352
  for (const resource of validResources) {
4290
4353
  this.resources.add(resource);
4291
4354
  }
4292
- if (sectionType !== "Patient" /* PATIENT */) {
4293
- let narrative = void 0;
4294
- if (validResources.length > 0) {
4295
- narrative = await NarrativeGenerator.generateNarrativeAsync(
4296
- sectionType,
4297
- validResources,
4298
- timezone,
4299
- true
4300
- );
4301
- }
4302
- if (!narrative && sectionType in IPSMandatorySections) {
4303
- narrative = await NarrativeGenerator.createNarrativeAsync(
4304
- IPSMissingMandatorySectionContent[sectionType]
4305
- );
4306
- }
4307
- if (!narrative) {
4308
- return this;
4309
- }
4310
- this.addSectionAsync(narrative, sectionType, validResources);
4355
+ let narrative = void 0;
4356
+ if (validResources.length > 0) {
4357
+ narrative = await NarrativeGenerator.generateNarrativeAsync(
4358
+ sectionType,
4359
+ validResources,
4360
+ timezone,
4361
+ true
4362
+ );
4363
+ }
4364
+ if (!narrative && sectionType in IPSMandatorySections) {
4365
+ narrative = await NarrativeGenerator.createNarrativeAsync(
4366
+ IPSMissingMandatorySectionContent[sectionType]
4367
+ );
4311
4368
  }
4369
+ if (!narrative) {
4370
+ return this;
4371
+ }
4372
+ this.addSectionAsync(narrative, sectionType, validResources);
4312
4373
  return this;
4313
4374
  }
4314
4375
  async makeSectionFromSummaryAsync(sectionType, summaryCompositions, resources, timezone) {
@@ -4346,17 +4407,18 @@ var ComprehensiveIPSCompositionBuilder = class {
4346
4407
  * @param timezone - Optional timezone to use for date formatting
4347
4408
  * @param useSummaryCompositions - Whether to use summary compositions (default: false)
4348
4409
  */
4349
- async readBundleAsync(bundle, timezone, useSummaryCompositions = false) {
4410
+ async readBundleAsync(bundle, timezone, useSummaryCompositions = false, consoleLogger = console) {
4350
4411
  if (!bundle.entry) {
4351
4412
  return this;
4352
4413
  }
4353
4414
  const patientEntries = [];
4354
4415
  const resources = [];
4355
4416
  bundle.entry.forEach((e) => {
4356
- if (e.resource?.resourceType === "Patient") {
4357
- patientEntries.push(e.resource);
4358
- this.resources.add(e.resource);
4359
- } else if (e.resource) {
4417
+ if (e.resource) {
4418
+ if (e.resource.resourceType === "Patient") {
4419
+ patientEntries.push(e.resource);
4420
+ this.resources.add(e.resource);
4421
+ }
4360
4422
  resources.push(e.resource);
4361
4423
  }
4362
4424
  });
@@ -4365,20 +4427,20 @@ var ComprehensiveIPSCompositionBuilder = class {
4365
4427
  }
4366
4428
  this.patients = patientEntries;
4367
4429
  for (const sectionType of Object.values(IPSSections)) {
4368
- if (sectionType === "Patient" /* PATIENT */) {
4369
- continue;
4370
- }
4371
4430
  const summaryIPSCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryIPSCompositionFilterForSection(sectionType) : void 0;
4372
4431
  const sectionIPSSummary = summaryIPSCompositionFilter ? resources.filter((resource) => summaryIPSCompositionFilter(resource)) : [];
4373
4432
  if (sectionIPSSummary.length > 0) {
4433
+ consoleLogger.info(`Using IPS summary composition for section: ${sectionType}`);
4374
4434
  await this.makeSectionFromSummaryAsync(sectionType, sectionIPSSummary, resources, timezone);
4375
4435
  continue;
4376
4436
  }
4377
4437
  const summaryCompositionFilter = useSummaryCompositions ? IPSSectionResourceHelper.getSummaryCompositionFilterForSection(sectionType) : void 0;
4378
4438
  const sectionSummary = summaryCompositionFilter ? resources.filter((resource) => summaryCompositionFilter(resource)) : [];
4379
4439
  if (sectionSummary.length > 0) {
4440
+ consoleLogger.info(`Using summary composition for section: ${sectionType}`);
4380
4441
  await this.makeSectionFromSummaryAsync(sectionType, sectionSummary, resources, timezone);
4381
4442
  } else {
4443
+ consoleLogger.info(`Using individual resources for section: ${sectionType}`);
4382
4444
  const sectionFilter = IPSSectionResourceHelper.getResourceFilterForSection(sectionType);
4383
4445
  const sectionResources = resources.filter((resource) => sectionFilter(resource));
4384
4446
  await this.makeSectionAsync(sectionType, sectionResources, timezone);
@@ -4402,6 +4464,9 @@ var ComprehensiveIPSCompositionBuilder = class {
4402
4464
  if (!this.patients) {
4403
4465
  throw new Error("Patient resource must be set before building the bundle");
4404
4466
  }
4467
+ if (!this.patientSummary) {
4468
+ throw new Error("Patient summary narrative must be set before building the bundle");
4469
+ }
4405
4470
  const primaryPatientId = patientId ?? this.patients[0].id;
4406
4471
  const composition = {
4407
4472
  id: `Composition-${primaryPatientId}`,
@@ -4425,14 +4490,7 @@ var ComprehensiveIPSCompositionBuilder = class {
4425
4490
  date: (now || /* @__PURE__ */ new Date()).toISOString(),
4426
4491
  title: "International Patient Summary",
4427
4492
  section: this.sections,
4428
- text: await NarrativeGenerator.generateNarrativeAsync(
4429
- "Patient" /* PATIENT */,
4430
- this.patients,
4431
- timezone,
4432
- true,
4433
- false,
4434
- now
4435
- )
4493
+ text: this.patientSummary
4436
4494
  };
4437
4495
  const bundle = {
4438
4496
  resourceType: "Bundle",