-
Notifications
You must be signed in to change notification settings - Fork 72
RELEASE ENG-484: Surescripts updates and improvements #4404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
…irectory metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
metriport/metriport-internal#1040 Signed-off-by: Keshav Saharia <keshav@metriport.com>
ENG-484: Surescripts updates and improvements
WalkthroughChanges span Surescripts FHIR construction, SFTP/S3 replica utilities, Surescripts schemas/types, and utils CLI. Key edits include MedicationRequest enhancements (identifier/category/reasonCode/performer), threading pharmacy through bundle building, gender domain narrowing (drop “N”), new list/read helpers for Surescripts response files, concurrency in conversion, and a new generate-csv CLI. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant BundleBuilder as getAllBundleEntries
participant MedRes as getMedicationResources
participant MedReq as getMedicationRequest
participant Pharmacy as Organization
Client->>BundleBuilder: build entries(data)
BundleBuilder->>BundleBuilder: pharmacy = getPharmacy(data)
BundleBuilder->>MedRes: getMedicationResources(..., pharmacy)
MedRes->>MedReq: getMedicationRequest(patient, prescriber, pharmacy, medication, detail)
MedReq-->>MedRes: MedicationRequest (identifier/category/reasonCode/performer?)
MedRes-->>BundleBuilder: medication + dispense + request
BundleBuilder-->>Client: Bundle entries
sequenceDiagram
participant User
participant CLI as generate-csv
participant Replica as SurescriptsReplica
participant Data as DataMapper
User->>CLI: run --cx-name --cx-id --facility-id
CLI->>Data: getPatientIds(facility)
CLI->>Replica: listResponseFiles()
CLI->>CLI: filter by patientId ∈ patientIds
loop parallel (≤10)
CLI->>Replica: getRawResponseFileByKey(key)
Replica-->>CLI: decompressed buffer
CLI->>CLI: extract transmissionId/patientId
end
CLI->>CLI: sort identifiers by transmissionId
CLI-->>User: write <cxName>-roster.csv
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (19)
packages/utils/src/surescripts/sftp-action.ts (3)
18-21
: Add PHI/PII caution to the read exampleread prints file contents to stdout (ascii). These files can contain PHI. Recommend adding a caution and a redirect example.
Apply this diff to enhance the docs:
@@ * You can read a file from the remote SFTP server with: * * npm run surescripts -- sftp read /path/to/file + * + * Caution: `read` prints the full file contents to stdout. Files may contain PHI/PII. + * Prefer redirecting output to a secure location: + * npm run surescripts -- sftp read /path/to/file > output.txt
14-17
: Document list filters (--prefix, --contains) for discoverabilityThe CLI supports --prefix and --contains but the header block doesn’t mention them. Add examples to reduce guesswork.
Apply this diff to the docs block:
@@ * You can list all files on the remote SFTP server with: * * npm run surescripts -- sftp list /path/to/directory + * + * Options: + * --prefix <prefix> Filter keys by prefix + * --contains <text> Filter keys by substring + * Examples: + * npm run surescripts -- sftp list /dir --prefix new/ + * npm run surescripts -- sftp list /dir --contains 2025-08-18Also applies to: 72-79
28-31
: Correct the @see target to the concrete file/pathIf the intended reference is the S3-backed replica implementation, point to replica/s3.ts rather than replica.ts.
Apply this diff:
- * @see @metriport/core/external/sftp/replica.ts for more details. + * @see @metriport/core/external/sftp/replica/s3.ts for more details.If the project has a replica index (e.g., replica/index.ts) that centralizes docs, use that instead.
packages/core/src/external/sftp/replica/s3.ts (1)
5-6
: Consider adding brief JSDoc on why these fields are protectedTiny clarity win for future maintainers.
Apply this diff to document intent:
export class S3Replica implements SftpReplica { - protected readonly s3: S3Utils; - protected readonly bucketName: string; + /** S3 client utils. Protected to allow subclasses to reuse low-level operations (immutable). */ + protected readonly s3: S3Utils; + /** Default bucket for this replica. Protected for subclass access (immutable). */ + protected readonly bucketName: string;packages/core/src/external/surescripts/schema/request.ts (1)
148-152
: Dropped "N" looks correct; fix the inline comment casing.Good alignment with the narrowed domain. Minor nit: the comment says "u - unknown" while the actual enum value is "U".
Apply this diff to correct the comment:
- genderAtBirth: z.enum(["M", "F", "U"]), // u - unknown + genderAtBirth: z.enum(["M", "F", "U"]), // U - unknownpackages/core/src/external/surescripts/file/file-generator.ts (1)
25-31
: Avoid duplicating SurescriptsGender; import the canonical type.Defining a local union risks drift from the source type in ../types. Import and reuse the canonical SurescriptsGender.
Apply this diff within these lines:
-type SurescriptsGender = "M" | "F" | "U"; const makeGenderDemographics = genderMapperFromDomain<SurescriptsGender>( { M: "M", F: "F", - O: "U", + O: "U", U: "U", }, "U" );And add this import at the top of the file (outside the selected range):
import type { SurescriptsGender } from "../types";packages/core/src/external/surescripts/fhir/constants.ts (1)
26-26
: Duplicate constant value with a different name may cause confusion.HL7_CODE_SYSTEM_URL duplicates the value of PLAN_NETWORK_PCN_SYSTEM ("v2-0203"). Consider unifying under a single, clearly named constant (e.g., HL7_IDENTIFIER_TYPE_SYSTEM) and deprecating the domain-specific alias.
Happy to draft a small follow-up PR to replace usages and keep a transitional alias.
packages/core/src/external/surescripts/codes.ts (1)
70-75
: Simplify alias resolution and avoid String#match; prefer normalization with RegExp#testMicro clean-up for readability and fewer branches. No behavior change.
Apply this diff:
-export function getPaymentCodeName(code: PaymentCode): PaymentCodeName { - if (code.length === 1 && code.match(/^[1-7]$/)) { - return getPaymentCodeName(("0" + code) as PaymentCode); - } - return PAYMENT_CODE_NAME[code] ?? "Other"; -} +export function getPaymentCodeName(code: PaymentCode): PaymentCodeName { + const normalized = + code.length === 1 && /^[1-7]$/.test(code) ? (("0" + code) as PaymentCode) : code; + return PAYMENT_CODE_NAME[normalized] ?? "Other"; +}packages/core/src/external/surescripts/schema/response.ts (1)
226-229
: Optional shim: Map legacy 'N' -> 'U' to prevent ingestion failures during transitionIf there’s any chance of lingering 'N' values, add a small transformer to keep ingestion resilient while upstream completes the change.
Apply this diff:
- fromSurescripts: fromSurescriptsEnum(["M", "F", "U"]), + fromSurescripts: fromSurescriptsGender,And add this helper near the top of the file (after imports):
function fromSurescriptsGender(value: string): "M" | "F" | "U" { return value === "N" ? "U" : fromSurescriptsEnum(["M", "F", "U"])(value); }packages/core/src/external/surescripts/fhir/condition.ts (2)
39-51
: Make Z-code check case-insensitive and add a brief “why” commentMinor robustness and inline rationale (to match the guideline of documenting why).
Apply this diff:
-function getClinicalStatus(detail: ResponseDetail): Condition["clinicalStatus"] { - if (detail.diagnosisICD10Code?.startsWith("Z")) { +function getClinicalStatus(detail: ResponseDetail): Condition["clinicalStatus"] { + /** Z-codes (e.g., encounters/contacts) are treated as active and confirmed for analytics. */ + if (detail.diagnosisICD10Code?.toUpperCase().startsWith("Z")) { return { coding: [ { system: CONDITION_CLINICAL_STATUS_URL, code: "active", }, ], }; } return undefined; }
53-65
: Mirror the case-insensitive Z-code check and add rationaleKeep behavior consistent across both status helpers.
Apply this diff:
-function getVerificationStatus(detail: ResponseDetail): Condition["verificationStatus"] { - if (detail.diagnosisICD10Code?.startsWith("Z")) { +function getVerificationStatus(detail: ResponseDetail): Condition["verificationStatus"] { + /** Z-codes are asserted as confirmed to improve downstream clinical signal. */ + if (detail.diagnosisICD10Code?.toUpperCase().startsWith("Z")) { return { coding: [ { system: CONDITION_VERIFICATION_STATUS_URL, code: "confirmed", }, ], }; } return undefined; }packages/core/src/external/surescripts/fhir/medication-request.ts (2)
178-190
: ReasonCode mapping is correct; consider including human-readable text if availableThe ICD-10 mapping is correct. If the source detail includes a diagnosis description, consider adding CodeableConcept.text (and/or coding.display) to improve UX and downstream readability.
Would you like me to add a guarded text/display mapping if fields like detail.diagnosisICD10Description are present?
23-37
: Add unit tests for new fields (identifier, reasonCode, pharmacy/performer)Recommend tests covering:
- identifier presence/absence based on rxReferenceNumber
- reasonCode population with ICD-10 code
- pharmacy mapped to dispenseRequest.performer (after refactor)
- intent remains "order"
I can generate targeted Jest tests for these cases if helpful.
Also applies to: 49-51, 69-71, 75-94, 178-190
packages/utils/src/surescripts/send-facility-request.ts (2)
76-77
: Check filename logging vs. actual path/extension handling.The log appends “.csv” while the function receives
csvOutput
already. IfwriteSurescriptsIdentifiersFile
also appends “.csv”, the message is correct; otherwise, it will be misleading.Consider logging the exact path you pass to the writer:
- log(`Wrote ${identifiers.length} identifiers to ${csvOutput}.csv`); + log(`Wrote ${identifiers.length} identifiers to ${csvOutput}`);
73-77
: Optional: wrap the SFTP send and write in try/catch for clearer failure visibility.As a CLI, letting errors bubble is fine, but a small try/catch improves operability and preserves the original error.
Apply this minimal diff:
- log("Sending " + requests.length + " requests"); - const identifiers = await client.sendBatchPatientRequest(requests); - log("Done writing facility requests"); - writeSurescriptsIdentifiersFile(csvOutput, identifiers); - log(`Wrote ${identifiers.length} identifiers to ${csvOutput}.csv`); + log("Sending " + requests.length + " requests"); + try { + const identifiers = await client.sendBatchPatientRequest(requests); + log("Done writing facility requests"); + writeSurescriptsIdentifiersFile(csvOutput, identifiers); + log(`Wrote ${identifiers.length} identifiers to ${csvOutput}`); + } catch (error) { + log(`Error sending facility requests: ${(error as Error).message}`); + throw error; + }packages/utils/src/surescripts/convert-customer-response.ts (1)
63-68
: Validate and radix-parse the start/end indices to avoid NaN surprises.
parseInt
without radix and no validation can yield unexpected slices (e.g., NaN → 0). Add radix and guard invalid values.Apply this diff:
- const startIndex = parseInt(start ?? "0"); - const endIndex = end != null ? parseInt(end) : undefined; + const startIndex = Number.parseInt(start ?? "0", 10); + const endIndex = end != null ? Number.parseInt(end, 10) : undefined; + if (Number.isNaN(startIndex) || (end != null && Number.isNaN(endIndex!))) { + throw new Error("start and end must be integers"); + }packages/utils/src/surescripts/generate-csv.ts (1)
67-80
: Avoid async scheduler overhead for a pure in-memory filter/map.The worker only checks membership and pushes to an array; no awaits. Using
executeAsynchronously
adds overhead without benefit. Prefer a synchronous loop for determinism and simplicity.Apply this diff:
- await executeAsynchronously( - responses, - async response => { - if (patientIdSet.has(response.patientId)) { - identifiers.push({ - transmissionId: response.transmissionId, - populationId: response.patientId, - }); - } - }, - { - numberOfParallelExecutions: 10, - } - ); + for (const response of responses) { + if (patientIdSet.has(response.patientId)) { + identifiers.push({ + transmissionId: response.transmissionId, + populationId: response.patientId, + }); + } + }packages/core/src/external/surescripts/replica.ts (2)
48-51
: Convenience read-by-key helper is sensible.Returning decompressed content matches getRawResponseFile behavior. Consider documenting that the key is expected to point to a gzipped object.
53-71
: Parsing keys by fixed indices is brittle; prefer a format-checked parse.The index math works for the current filename scheme, but a small drift (e.g., prefix change) will silently misparse. A regex against the relative key improves robustness and self-documents expectations.
Apply this refactor:
- async listResponseFiles(): Promise< - Array<{ key: string; transmissionId: string; patientId: string }> - > { - const responseFiles = await this.listFileNames(INCOMING_NAME); - const startIndex = INCOMING_NAME.length + 1; - return responseFiles - .filter(key => { - return key.charAt(startIndex + 10) === "_" && key.charAt(startIndex + 47) === "_"; - }) - .map(key => { - const transmissionId = key.substring(startIndex, startIndex + 10); - const patientId = key.substring(startIndex + 11, startIndex + 47); - return { - key, - transmissionId, - patientId, - }; - }); - } + async listResponseFiles(): Promise< + Array<{ key: string; transmissionId: string; patientId: string }> + > { + const responseFiles = await this.listFileNames(INCOMING_NAME); + const startIndex = INCOMING_NAME.length + 1; // after "from_surescripts/" + return responseFiles + .map(key => { + const relative = key.substring(startIndex); + const match = /^([A-Za-z0-9]{10})_([0-9a-fA-F-]{36})_/.exec(relative); + if (!match) return undefined; + const [, transmissionId, patientId] = match; + return { key, transmissionId, patientId }; + }) + .filter( + (x): x is { key: string; transmissionId: string; patientId: string } => x !== undefined + ); + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (19)
packages/core/src/external/sftp/replica/s3.ts
(1 hunks)packages/core/src/external/surescripts/codes.ts
(2 hunks)packages/core/src/external/surescripts/fhir/bundle-entry.ts
(1 hunks)packages/core/src/external/surescripts/fhir/bundle.ts
(1 hunks)packages/core/src/external/surescripts/fhir/condition.ts
(1 hunks)packages/core/src/external/surescripts/fhir/constants.ts
(1 hunks)packages/core/src/external/surescripts/fhir/medication-request.ts
(6 hunks)packages/core/src/external/surescripts/fhir/medication.ts
(1 hunks)packages/core/src/external/surescripts/fhir/patient.ts
(0 hunks)packages/core/src/external/surescripts/file/file-generator.ts
(1 hunks)packages/core/src/external/surescripts/replica.ts
(3 hunks)packages/core/src/external/surescripts/schema/request.ts
(2 hunks)packages/core/src/external/surescripts/schema/response.ts
(2 hunks)packages/core/src/external/surescripts/types.ts
(1 hunks)packages/utils/src/surescripts/convert-customer-response.ts
(2 hunks)packages/utils/src/surescripts/generate-csv.ts
(1 hunks)packages/utils/src/surescripts/index.ts
(2 hunks)packages/utils/src/surescripts/send-facility-request.ts
(1 hunks)packages/utils/src/surescripts/sftp-action.ts
(1 hunks)
💤 Files with no reviewable changes (1)
- packages/core/src/external/surescripts/fhir/patient.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.cursorrules)
**/*.{js,jsx,ts,tsx}
: Don’t use null inside the app, only on code interacting with external interfaces/services, like DB and HTTP; convert to undefined before sending inwards into the code
Useconst
whenever possible
Useasync/await
instead of.then()
Naming: classes, enums: PascalCase
Naming: constants, variables, functions: camelCase
Naming: file names: kebab-case
Naming: Don’t use negative names, likenotEnabled
, preferisDisabled
If possible, use decomposing objects for function parameters
Prefer Nullish Coalesce (??) than the OR operator (||) when you want to provide a default value
Avoid creating arrow functions
Use truthy syntax instead ofin
- i.e.,if (data.link)
notif ('link' in data)
While handling errors, keep the stack trace around: if you create a new Error (e.g., MetriportError), make sure to pass the original error as the new one’s cause so the stack trace is available upstream.
max column length is 100 chars
multi-line comments use/** */
top-level comments go after the import (save pre-import to basic file header, like license)
move literals to constants declared after imports when possible
Files:
packages/core/src/external/surescripts/schema/request.ts
packages/utils/src/surescripts/sftp-action.ts
packages/utils/src/surescripts/generate-csv.ts
packages/core/src/external/sftp/replica/s3.ts
packages/core/src/external/surescripts/fhir/bundle.ts
packages/core/src/external/surescripts/file/file-generator.ts
packages/utils/src/surescripts/send-facility-request.ts
packages/core/src/external/surescripts/fhir/constants.ts
packages/core/src/external/surescripts/schema/response.ts
packages/core/src/external/surescripts/types.ts
packages/core/src/external/surescripts/replica.ts
packages/core/src/external/surescripts/fhir/bundle-entry.ts
packages/utils/src/surescripts/index.ts
packages/core/src/external/surescripts/fhir/condition.ts
packages/utils/src/surescripts/convert-customer-response.ts
packages/core/src/external/surescripts/fhir/medication-request.ts
packages/core/src/external/surescripts/fhir/medication.ts
packages/core/src/external/surescripts/codes.ts
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.cursorrules)
Use types whenever possible
Files:
packages/core/src/external/surescripts/schema/request.ts
packages/utils/src/surescripts/sftp-action.ts
packages/utils/src/surescripts/generate-csv.ts
packages/core/src/external/sftp/replica/s3.ts
packages/core/src/external/surescripts/fhir/bundle.ts
packages/core/src/external/surescripts/file/file-generator.ts
packages/utils/src/surescripts/send-facility-request.ts
packages/core/src/external/surescripts/fhir/constants.ts
packages/core/src/external/surescripts/schema/response.ts
packages/core/src/external/surescripts/types.ts
packages/core/src/external/surescripts/replica.ts
packages/core/src/external/surescripts/fhir/bundle-entry.ts
packages/utils/src/surescripts/index.ts
packages/core/src/external/surescripts/fhir/condition.ts
packages/utils/src/surescripts/convert-customer-response.ts
packages/core/src/external/surescripts/fhir/medication-request.ts
packages/core/src/external/surescripts/fhir/medication.ts
packages/core/src/external/surescripts/codes.ts
**/*.ts
⚙️ CodeRabbit Configuration File
**/*.ts
: - Use the Onion Pattern to organize a package's code in layers
- Try to use immutable code and avoid sharing state across different functions, objects, and systems
- Try to build code that's idempotent whenever possible
- Prefer functional programming style functions: small, deterministic, 1 input, 1 output
- Minimize coupling / dependencies
- Avoid modifying objects received as parameter
- Only add comments to code to explain why something was done, not how it works
- Naming
- classes, enums:
PascalCase
- constants, variables, functions:
camelCase
- file names:
kebab-case
- table and column names:
snake_case
- Use meaningful names, so whoever is reading the code understands what it means
- Don’t use negative names, like
notEnabled
, preferisDisabled
- For numeric values, if the type doesn’t convey the unit, add the unit to the name
- Typescript
- Use types
- Prefer
const
instead oflet
- Avoid
any
and casting fromany
to other types- Type predicates: only applicable to narrow down the type, not to force a complete type conversion
- Prefer deconstructing parameters for functions instead of multiple parameters that might be of
the same type- Don’t use
null
inside the app, only on code interacting with external interfaces/services,
like DB and HTTP; convert toundefined
before sending inwards into the code- Use
async/await
instead of.then()
- Use the strict equality operator
===
, don’t use abstract equality operator==
- When calling a Promise-returning function asynchronously (i.e., not awaiting), use
.catch()
to
handle errors (seeprocessAsyncError
andemptyFunction
depending on the case)- Date and Time
- Always use
buildDayjs()
to createdayjs
instances- Prefer
dayjs.duration(...)
to create duration consts and keep them asduration
- Prefer Nullish Coalesce (??) than the OR operator (||) to provide a default value
- Avoid creating arrow functions
- U...
Files:
packages/core/src/external/surescripts/schema/request.ts
packages/utils/src/surescripts/sftp-action.ts
packages/utils/src/surescripts/generate-csv.ts
packages/core/src/external/sftp/replica/s3.ts
packages/core/src/external/surescripts/fhir/bundle.ts
packages/core/src/external/surescripts/file/file-generator.ts
packages/utils/src/surescripts/send-facility-request.ts
packages/core/src/external/surescripts/fhir/constants.ts
packages/core/src/external/surescripts/schema/response.ts
packages/core/src/external/surescripts/types.ts
packages/core/src/external/surescripts/replica.ts
packages/core/src/external/surescripts/fhir/bundle-entry.ts
packages/utils/src/surescripts/index.ts
packages/core/src/external/surescripts/fhir/condition.ts
packages/utils/src/surescripts/convert-customer-response.ts
packages/core/src/external/surescripts/fhir/medication-request.ts
packages/core/src/external/surescripts/fhir/medication.ts
packages/core/src/external/surescripts/codes.ts
🧠 Learnings (19)
📓 Common learnings
Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/core/src/external/surescripts/fhir/coverage.ts:0-0
Timestamp: 2025-06-18T18:34:10.489Z
Learning: Coverage resources in Surescripts FHIR conversion are currently excluded from bundles to prevent skewing data lift metrics. The team plans to examine available insurance data thoroughly before including properly structured Coverage resources with mandatory FHIR R4 elements like beneficiary and payor references.
Learnt from: keshavsaharia
PR: metriport/metriport#4370
File: packages/core/src/external/quest/id-generator.ts:5-8
Timestamp: 2025-08-15T00:20:50.840Z
Learning: User keshavsaharia highly values rigorous mathematical analysis and comprehensive technical solutions that include both problem identification and complete remediation paths, particularly appreciating when statistical claims are verified and corrected with proper calculations.
Learnt from: keshavsaharia
PR: metriport/metriport#4020
File: packages/core/src/external/fhir/adt-encounters.ts:245-253
Timestamp: 2025-08-04T17:46:17.853Z
Learning: User keshavsaharia prefers lodash chains over native JavaScript methods for readability when working with complex data transformations, even when it involves using underscore imports and might have less robust error handling.
📚 Learning: 2025-08-15T00:00:45.080Z
Learnt from: keshavsaharia
PR: metriport/metriport#4370
File: packages/shared/src/domain/patient.ts:5-5
Timestamp: 2025-08-15T00:00:45.080Z
Learning: The patientSchema in packages/shared/src/domain/patient.ts is used in a limited subsystem scope ("SS") and is not the same as other Patient schemas referenced throughout the codebase, making additive optional field changes like externalId safe and non-breaking.
Applied to files:
packages/core/src/external/surescripts/schema/request.ts
packages/core/src/external/surescripts/schema/response.ts
📚 Learning: 2025-05-30T03:42:53.380Z
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/schema/load.ts:65-71
Timestamp: 2025-05-30T03:42:53.380Z
Learning: In Surescripts schema files like `packages/core/src/external/surescripts/schema/load.ts`, the `key` property in field definitions is only used for direct one-to-one field mappings. When multiple fields are derived from the same source property but with different transformations (like extracting date vs. time portions), they should not have `key` properties as they represent transformations rather than direct mappings.
Applied to files:
packages/core/src/external/surescripts/schema/request.ts
packages/core/src/external/surescripts/schema/response.ts
📚 Learning: 2025-06-06T16:45:31.832Z
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Applied to files:
packages/core/src/external/surescripts/fhir/bundle.ts
packages/core/src/external/surescripts/schema/response.ts
packages/core/src/external/surescripts/fhir/bundle-entry.ts
packages/core/src/external/surescripts/fhir/medication-request.ts
packages/core/src/external/surescripts/fhir/medication.ts
📚 Learning: 2025-08-04T17:59:05.674Z
Learnt from: lucasdellabella
PR: metriport/metriport#4020
File: packages/fhir-sdk/src/index.ts:308-308
Timestamp: 2025-08-04T17:59:05.674Z
Learning: In packages/fhir-sdk/src/index.ts, the FhirBundleSdk constructor intentionally mutates the input bundle's total property to ensure data consistency between bundle.total and bundle.entry.length. This is an accepted exception to the "avoid modifying objects received as parameter" guideline for cleanup purposes.
Applied to files:
packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-06-25T01:55:42.627Z
Learnt from: thomasyopes
PR: metriport/metriport#4090
File: packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts:30-30
Timestamp: 2025-06-25T01:55:42.627Z
Learning: In packages/core/src/command/conversion-fhir/conversion-fhir-cloud.ts, the FHIR converter Lambda endpoint is controlled by the team and guaranteed to return valid JSON in the expected Bundle<Resource> format, so JSON.parse() error handling and type validation are not necessary for this specific endpoint.
Applied to files:
packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-04-21T17:07:30.574Z
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/core/src/external/ehr/canvas/index.ts:451-469
Timestamp: 2025-04-21T17:07:30.574Z
Learning: The `getMetriportOnlyBundleByResourceType` method in CanvasApi returns `Promise<Bundle | undefined>` because the Metriport-only bundle is a computed artifact that may not exist yet. In contrast, `getBundleByResourceType` returns `Promise<Bundle>` because it can always fetch from the EHR API if the S3 cached bundle doesn't exist.
Applied to files:
packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-05-28T19:20:47.442Z
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:0-0
Timestamp: 2025-05-28T19:20:47.442Z
Learning: In packages/core/src/external/ehr/lambdas/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Applied to files:
packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-05-08T19:41:36.533Z
Learnt from: thomasyopes
PR: metriport/metriport#3788
File: packages/api/src/external/ehr/shared/utils/bundle.ts:83-93
Timestamp: 2025-05-08T19:41:36.533Z
Learning: In the Metriport codebase, the team prefers to let errors bubble up naturally in some cases rather than adding explicit error handling at every layer, as demonstrated in the refreshEhrBundle function in the bundle.ts file.
Applied to files:
packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-05-28T19:22:09.281Z
Learnt from: thomasyopes
PR: metriport/metriport#3882
File: packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts:27-49
Timestamp: 2025-05-28T19:22:09.281Z
Learning: In packages/core/src/external/ehr/command/get-bundle-by-resource-type/ehr-get-bundle-by-resource-type-cloud.ts, the EHR get bundle by resource type Lambda endpoint is guaranteed to return valid JSON, so JSON.parse() error handling is not necessary for this specific endpoint.
Applied to files:
packages/core/src/external/surescripts/fhir/bundle.ts
📚 Learning: 2025-05-30T01:11:35.300Z
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/utils/src/surescripts/generate-patient-load-file.ts:92-94
Timestamp: 2025-05-30T01:11:35.300Z
Learning: In V0 of the Surescripts implementation (packages/utils/src/surescripts/generate-patient-load-file.ts), there is always only 1 facility ID, so the current facility_ids parsing logic with substring operations is sufficient and additional validation is not necessary.
Applied to files:
packages/utils/src/surescripts/send-facility-request.ts
packages/core/src/external/surescripts/types.ts
📚 Learning: 2025-05-28T19:23:20.179Z
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/sftp/surescripts/client.ts:1-134
Timestamp: 2025-05-28T19:23:20.179Z
Learning: In packages/core/src/external/sftp/surescripts/client.ts, the standalone getPatientLoadFileName function intentionally omits the transmission ID from the filename, which differs from the class method getPatientLoadFileName. This difference in filename generation is expected behavior.
Applied to files:
packages/utils/src/surescripts/send-facility-request.ts
packages/core/src/external/surescripts/replica.ts
📚 Learning: 2025-05-20T21:26:26.804Z
Learnt from: leite08
PR: metriport/metriport#3814
File: packages/api/src/routes/internal/medical/patient-consolidated.ts:141-174
Timestamp: 2025-05-20T21:26:26.804Z
Learning: The functionality introduced in packages/api/src/routes/internal/medical/patient-consolidated.ts is planned to be refactored in downstream PR #3857, including improvements to error handling and validation.
Applied to files:
packages/utils/src/surescripts/send-facility-request.ts
packages/utils/src/surescripts/convert-customer-response.ts
📚 Learning: 2025-04-22T00:07:37.729Z
Learnt from: RamilGaripov
PR: metriport/metriport#3686
File: docs/medical-api/fhir/extensions/chronicity.mdx:12-21
Timestamp: 2025-04-22T00:07:37.729Z
Learning: In Metriport's FHIR Condition chronicity extension, they use "http://hl7.org/fhir/StructureDefinition/condition-related" as the extension URL and "https://public.metriport.com/fhir/StructureDefinition/condition-chronicity.json" as the valueCoding.system.
Applied to files:
packages/core/src/external/surescripts/fhir/constants.ts
packages/core/src/external/surescripts/fhir/condition.ts
📚 Learning: 2025-06-17T01:51:12.930Z
Learnt from: keshavsaharia
PR: metriport/metriport#4033
File: packages/core/src/external/surescripts/fhir/patient.ts:29-36
Timestamp: 2025-06-17T01:51:12.930Z
Learning: In Surescripts response files, the patientFirstName and patientLastName fields in ResponseDetail are always set to valid strings and are required according to the specification, so defensive checks for undefined/empty values are not needed when constructing FHIR Patient names.
Applied to files:
packages/core/src/external/surescripts/schema/response.ts
📚 Learning: 2025-06-13T21:41:01.744Z
Learnt from: thomasyopes
PR: metriport/metriport#3885
File: packages/core/src/external/surescripts/client.ts:170-180
Timestamp: 2025-06-13T21:41:01.744Z
Learning: In packages/core/src/external/surescripts/client.ts, the leading slash in "/from_surescripts" used with listFileNamesWithPrefix for replica lookups is intentional, despite appearing inconsistent with other replica path references that don't use leading slashes.
Applied to files:
packages/core/src/external/surescripts/replica.ts
📚 Learning: 2025-05-28T19:23:20.179Z
Learnt from: keshavsaharia
PR: metriport/metriport#3885
File: packages/core/src/external/sftp/surescripts/client.ts:1-134
Timestamp: 2025-05-28T19:23:20.179Z
Learning: In packages/core/src/external/sftp/surescripts/client.ts, the SurescriptsSftpClient constructor intentionally uses config.publicKey as the SFTP password field and config.username as the SFTP username field. This is the expected configuration for Surescripts SFTP authentication.
Applied to files:
packages/core/src/external/surescripts/replica.ts
📚 Learning: 2025-06-25T18:42:07.231Z
Learnt from: keshavsaharia
PR: metriport/metriport#4075
File: packages/core/src/external/surescripts/fhir/medication-request.ts:76-83
Timestamp: 2025-06-25T18:42:07.231Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, the getDispenseNote and getDosageInstruction functions are intentionally identical because the dashboard requires both the note and dosageInstruction fields of MedicationRequest to be populated with detail.directions for proper note display functionality.
Applied to files:
packages/core/src/external/surescripts/fhir/bundle-entry.ts
packages/core/src/external/surescripts/fhir/medication-request.ts
packages/core/src/external/surescripts/fhir/medication.ts
📚 Learning: 2025-06-18T17:22:24.597Z
Learnt from: keshavsaharia
PR: metriport/metriport#4045
File: packages/shared/src/interface/external/surescripts/plan-code.ts:1-3
Timestamp: 2025-06-18T17:22:24.597Z
Learning: In packages/shared/src/interface/external/surescripts/plan-code.ts, the getPlanCodeName function should return undefined for invalid plan codes rather than throwing errors, as per user preference for graceful error handling.
Applied to files:
packages/core/src/external/surescripts/codes.ts
🧬 Code Graph Analysis (10)
packages/core/src/external/surescripts/schema/request.ts (1)
packages/core/src/external/surescripts/schema/shared.ts (1)
toSurescriptsEnum
(103-121)
packages/utils/src/surescripts/generate-csv.ts (5)
packages/core/src/external/surescripts/replica.ts (1)
SurescriptsReplica
(8-72)packages/core/src/external/surescripts/data-mapper.ts (1)
SurescriptsDataMapper
(19-124)packages/core/src/util/log.ts (1)
out
(30-35)packages/core/src/external/surescripts/types.ts (1)
SurescriptsFileIdentifier
(27-30)packages/utils/src/surescripts/shared.ts (1)
writeSurescriptsRunsFile
(32-40)
packages/core/src/external/sftp/replica/s3.ts (1)
packages/core/src/external/aws/s3.ts (1)
S3Utils
(140-570)
packages/core/src/external/surescripts/file/file-generator.ts (2)
packages/core/src/external/surescripts/types.ts (1)
SurescriptsGender
(6-6)packages/core/src/external/quest/codes.ts (1)
makeGenderDemographics
(10-18)
packages/core/src/external/surescripts/schema/response.ts (1)
packages/core/src/external/surescripts/schema/shared.ts (1)
fromSurescriptsEnum
(84-101)
packages/core/src/external/surescripts/replica.ts (1)
packages/core/src/external/surescripts/constants.ts (1)
INCOMING_NAME
(3-3)
packages/utils/src/surescripts/index.ts (2)
packages/commonwell-cert-runner/src/index.ts (1)
program
(36-36)packages/core/src/command/hl7v2-subscriptions/hl7v2-roster-generator.ts (1)
generateCsv
(169-172)
packages/core/src/external/surescripts/fhir/condition.ts (6)
packages/core/src/external/surescripts/schema/response.ts (1)
ResponseDetail
(158-158)packages/core/src/external/surescripts/fhir/patient.ts (1)
getPatientReference
(23-31)packages/shared/src/util/uuid-v7.ts (1)
uuidv7
(369-371)packages/core/src/external/surescripts/fhir/shared.ts (1)
getSurescriptsDataSourceExtension
(4-12)packages/commonwell-sdk/src/models/document.ts (1)
CodeableConcept
(37-37)packages/core/src/external/surescripts/fhir/constants.ts (2)
CONDITION_CLINICAL_STATUS_URL
(22-23)CONDITION_VERIFICATION_STATUS_URL
(24-25)
packages/utils/src/surescripts/convert-customer-response.ts (4)
packages/lambdas/src/surescripts/convert-batch-response.ts (1)
handler
(8-13)packages/lambdas/src/surescripts/convert-patient-response.ts (1)
handler
(8-13)packages/core/src/external/surescripts/command/convert-patient-response/convert-patient-response-direct.ts (1)
SurescriptsConvertPatientResponseHandlerDirect
(7-30)packages/core/src/external/surescripts/data-mapper.ts (1)
SurescriptsDataMapper
(19-124)
packages/core/src/external/surescripts/fhir/medication-request.ts (6)
packages/core/src/external/surescripts/schema/response.ts (1)
ResponseDetail
(158-158)packages/core/src/external/surescripts/fhir/pharmacy.ts (1)
getPharmacyReference
(28-32)packages/core/src/external/surescripts/fhir/shared.ts (1)
getSurescriptsDataSourceExtension
(4-12)packages/shared/src/util/uuid-v7.ts (1)
uuidv7
(369-371)packages/core/src/external/surescripts/fhir/constants.ts (2)
HL7_CODE_SYSTEM_URL
(26-26)MEDICATION_REQUEST_CATEGORY_URL
(27-28)packages/commonwell-sdk/src/models/document.ts (1)
CodeableConcept
(37-37)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: check-pr / lint-build-test
- GitHub Check: check-pr / lint-build-test
- GitHub Check: Analyze (javascript)
- GitHub Check: ihe_stack / deploy
- GitHub Check: infra-api-lambdas / deploy
- GitHub Check: mllp-server / deploy
- GitHub Check: api / deploy
🔇 Additional comments (34)
packages/utils/src/surescripts/sftp-action.ts (1)
7-37
: Docs addition is helpful and aligned with utils package constraintsClear, actionable CLI usage for all subcommands. Multi-line JSDoc placed after imports matches guidelines; console logging is acceptable in utils.
packages/core/src/external/sftp/replica/s3.ts (1)
5-6
: Protected + readonly on s3 and bucketName enables safe subclassingGood change. It unblocks extensions without altering runtime behavior or mutability guarantees.
packages/core/src/external/surescripts/schema/request.ts (2)
270-273
: Order mapping matches the narrowed enum.The field order and serializer now enforce ["M","F","U"], consistent with the schema and the generator’s fallback to "U".
148-152
: No remaining “N” producers detected
I ran targeted searches for"N"
in Surescripts gender enums,toSurescriptsEnum
calls, and mapper return values—no matches were found. All data now normalizes to"U"
, so serialization will succeed under the stricter enum.packages/core/src/external/surescripts/types.ts (1)
6-6
: No SurescriptsGender “N” references found – ready to mergeAll usages of
SurescriptsGender
inpackages/core
(type definition and mapper infile-generator.ts
) now only allow"M" | "F" | "U"
. There are no downstream parsers, validators or tests emitting or expecting"N"
for Surescripts data.packages/core/src/external/surescripts/fhir/medication.ts (1)
13-17
: Centralizing code system URLs is good; imports look correct.Moving NDC_URL and SNOMED_URL to @metriport/shared/medical and keeping DEA/UCUM URLs local to Surescripts FHIR constants improves consistency.
packages/core/src/external/surescripts/fhir/constants.ts (1)
22-29
: New HL7 code system constants look correct.The URLs match HL7 definitions for clinical/verification status, identifier types, and medication request category.
packages/core/src/external/surescripts/codes.ts (2)
40-56
: Expanded PAYMENT_CODES to accept 1-digit aliases — LGTMSupporting both “01–07” and “1–7” improves interoperability and keeps the type-safe union aligned with real-world inputs.
77-86
: All PAYMENT_CODE_NAME lookups go through getPaymentCodeNameNo occurrences of
PAYMENT_CODE_NAME[...]
were found outside thegetPaymentCodeName
helper (only the internal fallback at packages/core/src/external/surescripts/codes.ts:74). All external consumers invokegetPaymentCodeName
, so the partial mapping won’t cause unexpectedundefined
returns.packages/core/src/external/surescripts/fhir/bundle.ts (2)
2-2
: Centralizing NDC_URL import to @metriport/shared/medical — LGTMThis aligns constants across Surescripts FHIR modules and avoids drift.
2-2
: All NDC_URL imports are using @metriport/shared/medical
No legacy imports from anyconstants
paths were found—every occurrence ofimport { NDC_URL }
now correctly points to@metriport/shared/medical
.packages/core/src/external/surescripts/schema/response.ts (1)
87-87
: Confirmed: Surescripts gender codes are now limited to M/F/U—removing ‘N’ is correct
Per the NCPDP SCRIPT v2023011 (2023 upgrade) and the latest Surescripts specification, only M (Male), F (Female), and U (Unknown/Undifferentiated) are accepted. The ‘N’ value is deprecated and will no longer be emitted by compliant sources, so dropping it from the enum is safe.• File: packages/core/src/external/surescripts/schema/response.ts
• Line 87:patientGender: z.enum(["M", "F", "U"]),
packages/core/src/external/surescripts/fhir/bundle-entry.ts (2)
73-77
: Threading pharmacy into MedicationRequest — LGTMSignature alignment with getMedicationRequest and downstream use for performer is clean and preserves the return shape.
70-77
: Ignore parameter order forgetMedicationRequest
callSince
getMedicationRequest
accepts a single object whose properties are destructured by name, the order in which you listpatient
,prescriber
,pharmacy
,medication
,coverage
, anddetail
in the call has no effect on how they bind. No action needed here.Likely an incorrect or invalid review comment.
packages/core/src/external/surescripts/fhir/condition.ts (4)
2-8
: Use of shared ICD_10_URL and constants — LGTMConsolidating code-system URLs via shared/constants improves consistency and reduces drift risk.
11-25
: Condition construction with safe gating — LGTMReturning undefined when no ICD-10 code and attaching source extension/statuses conditionally is sound.
27-37
: CodeableConcept creation for ICD-10 — LGTMMinimal coding payload is correct; display text can be added later if needed.
44-46
: FHIR R4 CodeSystem URLs Verified
BothCONDITION_CLINICAL_STATUS_URL
(http://terminology.hl7.org/CodeSystem/condition-clinical
) andCONDITION_VERIFICATION_STATUS_URL
(http://terminology.hl7.org/CodeSystem/condition-ver-status
) match the official FHIR R4 canonical identifiers. No changes required.packages/core/src/external/surescripts/fhir/medication-request.ts (8)
10-13
: Imports and constants look correct and align with new capabilitiesType imports and constants for ICD-10, HL7, and category are appropriate for the new fields introduced (identifier, reasonCode, pharmacy/performer).
Also applies to: 18-21
39-39
: Identifier threading into the payload is good, but see identifier construction belowThe plumbing from computed identifiers into the resource via conditional spread is clean. See follow-up on the identifier’s construction to ensure FHIR-correct semantics.
Also applies to: 60-60
57-57
: Confirm status/intent pairing (status: "completed" with intent: "order")Setting intent: "order" is sensible, but combined with status: "completed" may imply a fully completed order (not active). Ensure this pairing reflects the Surescripts message semantics you’re modeling; otherwise consider status "active" or mapping dynamically from the source status.
124-135
: Category system constantization is correctUsing MEDICATION_REQUEST_CATEGORY_URL instead of a hard-coded URL aligns with consistency guidelines and improves maintainability.
Also applies to: 129-129
161-161
: No-op changeAppears to be whitespace-only; no action needed.
177-177
: No-op changeAppears to be whitespace-only; no action needed.
142-160
: Acknowledging intentional duplication for dashboard requirementsgetDosageInstruction and getDispenseNote mirroring is intentional per prior decisions to support dashboard note display. Leaving as-is is correct.
26-27
: Keep pharmacy as MedicationRequest.performer
FHIR R4 does not define aperformer
element withinMedicationRequest.dispenseRequest
. The top-levelMedicationRequest.performer
is the correct location for referencing the intended dispenser or administering organization. If you need to model the actual dispensing event, use a separateMedicationDispense
resource, which includes its ownperformer
field.Likely an incorrect or invalid review comment.
packages/utils/src/surescripts/send-facility-request.ts (1)
21-26
: Align CSV header docs with actual output orderThe docs in
send-facility-request.ts
currently state that the CSV is written as"transmission_id","patient_id"
, but the helper produces and the downstream scripts expect"patient_id","transmission_id"
. Please update the wording to match the actual header order:- * csv-output: The file to write a CSV containing transmission IDs and patient IDs + * csv-output: The file to write a CSV containing patient IDs and transmission IDs @@ - * Note: The headers of the CSV file are "transmission_id","patient_id", which are used in scripts + * Note: The headers of the CSV file are "patient_id","transmission_id", which are used in scriptspackages/utils/src/surescripts/convert-customer-response.ts (2)
70-91
: Good move to parallelize conversions with bounded concurrency.The shift to
executeAsynchronously(..., { numberOfParallelExecutions: 10, keepExecutingOnError: true })
is appropriate and should materially improve throughput while isolating failures.
11-26
: Docs are clear and consistent with generate-csv.The CSV description (“patient_id” and “transmission_id”) aligns with the new generate-csv command. Nice.
packages/utils/src/surescripts/index.ts (2)
24-27
: Helpful registry comment.Clarifies the CLI extension point; keeps command naming consistent.
22-23
: Registering generate-csv looks correct.Import and
program.addCommand(generateCsv)
are consistent with existing commands.Also applies to: 46-46
packages/utils/src/surescripts/generate-csv.ts (1)
86-93
: CSV header/order aligns with downstream consumer.Header is "patient_id","transmission_id", matching convert-customer-response documentation. Sorting by transmissionId provides deterministic output; good for diffs.
packages/core/src/external/surescripts/replica.ts (2)
19-21
: Centralizing the incoming prefix via INCOMING_NAME is a good cleanup.Removes hard-coded strings and keeps path logic consistent with constants.
39-39
: Consistent use of INCOMING_NAME in response lookup.Using the constant with
listFileNamesWithPrefix
improves maintainability.
function getMedicationRequestIdentifier(detail: ResponseDetail): Identifier[] | undefined { | ||
const identifiers: Identifier[] = []; | ||
if (detail.rxReferenceNumber) { | ||
identifiers.push({ | ||
system: HL7_CODE_SYSTEM_URL, | ||
type: { | ||
coding: [ | ||
{ | ||
system: HL7_CODE_SYSTEM_URL, | ||
code: "RXN", | ||
display: "Rx Number", | ||
}, | ||
], | ||
}, | ||
value: detail.rxReferenceNumber, | ||
}); | ||
} | ||
if (identifiers.length > 0) return identifiers; | ||
return undefined; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Fix Identifier.system misuse; it must be the identifier namespace, not a code system
In FHIR, Identifier.system is the namespace/assigning system of the value (e.g., the pharmacy’s Rx number namespace), not a code system URI. HL7 v2-0203 belongs in Identifier.type.coding.system, which you already set. Keeping HL7 in Identifier.system will fail validation and misrepresent semantics.
Apply this diff to remove the incorrect system field:
if (detail.rxReferenceNumber) {
identifiers.push({
- system: HL7_CODE_SYSTEM_URL,
type: {
coding: [
{
system: HL7_CODE_SYSTEM_URL,
- code: "RXN",
+ code: "RXN",
display: "Rx Number",
},
],
},
value: detail.rxReferenceNumber,
});
}
Additionally, please verify the code value "RXN" against HL7 v2-0203. Many implementations use "RX" for Pharmacy prescription number. If "RX" is correct for your context, update code accordingly.
🏁 Script executed:
#!/usr/bin/env bash
# Search for the definition and usage of HL7_CODE_SYSTEM_URL
rg -n "HL7_CODE_SYSTEM_URL" --glob "*.ts"
Length of output: 552
Remove incorrect Identifier.system usage
The FHIR Identifier.system must be the assigning namespace URI—not the code system URI. You’ve imported HL7_CODE_SYSTEM_URL (“http://terminology.hl7.org/CodeSystem/v2-0203”), which belongs in Identifier.type.coding.system (and you already set it there). Including it as Identifier.system will fail validation and misrepresent the assigning authority.
Please update packages/core/src/external/surescripts/fhir/medication-request.ts (lines 75–94) as follows:
if (detail.rxReferenceNumber) {
identifiers.push({
- system: HL7_CODE_SYSTEM_URL,
type: {
coding: [
{
system: HL7_CODE_SYSTEM_URL,
code: "RXN",
display: "Rx Number",
},
],
},
value: detail.rxReferenceNumber,
});
}
• If you need to specify an assigning namespace (e.g., your pharmacy’s own URI), add it to Identifier.system.
• Also confirm the correct HL7 v2-0203 code value: many use “RX” for pharmacy prescription numbers instead of “RXN.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
function getMedicationRequestIdentifier(detail: ResponseDetail): Identifier[] | undefined { | |
const identifiers: Identifier[] = []; | |
if (detail.rxReferenceNumber) { | |
identifiers.push({ | |
system: HL7_CODE_SYSTEM_URL, | |
type: { | |
coding: [ | |
{ | |
system: HL7_CODE_SYSTEM_URL, | |
code: "RXN", | |
display: "Rx Number", | |
}, | |
], | |
}, | |
value: detail.rxReferenceNumber, | |
}); | |
} | |
if (identifiers.length > 0) return identifiers; | |
return undefined; | |
} | |
function getMedicationRequestIdentifier(detail: ResponseDetail): Identifier[] | undefined { | |
const identifiers: Identifier[] = []; | |
if (detail.rxReferenceNumber) { | |
identifiers.push({ | |
type: { | |
coding: [ | |
{ | |
system: HL7_CODE_SYSTEM_URL, | |
code: "RXN", | |
display: "Rx Number", | |
}, | |
], | |
}, | |
value: detail.rxReferenceNumber, | |
}); | |
} | |
if (identifiers.length > 0) return identifiers; | |
return undefined; | |
} |
🤖 Prompt for AI Agents
In packages/core/src/external/surescripts/fhir/medication-request.ts around
lines 75 to 94, the Identifier.system is incorrectly set to HL7_CODE_SYSTEM_URL
(the v2-0203 code system URI); remove that value from Identifier.system (either
omit Identifier.system entirely or set it to your assigning namespace URI if you
have one), keep HL7_CODE_SYSTEM_URL only in Identifier.type.coding.system, and
change the v2-0203 code from "RXN" to the correct pharmacy prescription code
("RX") in the coding.code field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is odd because the HL7 guidance says the opposite. Leaving it for now and will add this to the list of things to address in the upcoming PR with updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
@keshavsaharia Thank you for the clarification. You're right that there can be nuanced guidance in HL7 implementation guides that might differ from the base FHIR R4 specification. I appreciate you noting this discrepancy for the upcoming PR - it's worth investigating the specific HL7 guidance you're referencing to ensure we're following the most appropriate pattern for Surescripts integration.
The deferral makes sense given this is part of a larger set of updates, and having all the identifier-related changes reviewed together will provide better context.
🌐 Web query:
FHIR R4 Identifier.system element specification and HL7 implementation guidance for pharmacy prescription identifiers
💡 Result:
The FHIR R4 Identifier.system element is specified as a required URI that establishes the namespace for an identifier: it uniquely identifies the system that issues and manages identifier values and enables reliable matching and interoperability for identifiers across FHIR resources[1]. For pharmacy prescription identifiers, HL7 implementation guidance recommends using recognized, authoritative URIs for the Identifier.system, often published or agreed upon at national or regional levels[4][5].
Key Specifications for Identifier.system (FHIR R4)
- Definition: The system defines the namespace for the identifier value, expressed as a URI[1].
- Type:
uri
(Uniform Resource Identifier)[1]. - Cardinality: 1..1 (required)[1].
- Purpose: Distinguishes which set of identifiers the value belongs to, supporting accurate matching and deduplication[1].
- Case Sensitivity: Identifier.system is always case sensitive[1].
- Example Format: For generic use —
http://www.acme.com/identifiers/patient
[1].
Requirements and Guidance:
- Use official URIs where available: HL7 publishes a registry of identifier systems and specifies that predefined URIs SHOULD be used when known, such as national ePrescription identifier systems[4].
- Custom/national URIs: If a system does not appear in HL7's registry, implementers should use a well-defined, stable URI controlled by a responsible organization (e.g., government health ministry, standards body)[4][1].
- Patient and prescription identifiers: In pharmacy, prescription identifiers typically use a system URI that reflects the authority or registry for prescription numbers (e.g., a national ePrescription system URI, or a proprietary pharmacy chain’s system URI)[3][4][5].
HL7 Implementation Guidance for Pharmacy Prescription Identifiers
-
MedicationRequest.identifier: The Identifier type is used for business identifiers for prescriptions/orders[5][8].
-
System Selection:
- Use national, regional, or organizational URIs, registered and published for interoperability[4].
- For national health systems (e.g., US, Australia), these URIs may be specified in local FHIR implementation guides.
- Example: Australia’s local prescription identifier profile[1].
-
Use of Extensions: Where specialized identifier systems or instructions are needed (e.g., linking multiple medications to a single pharmaceutical treatment), FHIR supports use of custom extensions. These must declare their URL and ideally be registered or referenced in documentation[2][3].
Example: Identifier for Pharmacy Prescription
{
"identifier": [
{
"system": "https://health.gov/prescriptions/id", // system URI, authoritative
"value": "RX-20250812-1234567", // unique prescription number
"use": "official",
"assigner": {
"display": "National E-Prescription Registry"
}
}
]
}
- system: An authoritative URI for prescription identifiers, ideally published by the relevant health authority or organization[1][4].
- value: The prescription number, unique in the given system.
Best Practice References
- Obtain system URIs from HL7’s [identifier registry][4].
- Refer to national HL7 pharmacy IGs for current list of prescribed system URIs (see [HL7 SMP IG][5], [Australian Profile][1], specialty Rx IGs[6]).
- Ensure identifier consistency and traceability by aligning with jurisdictional conventions and documented implementation guides[1][5].
Summary Table: Core Attributes for Pharmacy Prescription Identifier
Attribute | Description | FHIR Element |
---|---|---|
system | Authoritative URI for prescription number namespace | Identifier.system[1][4] |
value | Uniquely assigned prescription identifier | Identifier.value |
use | Purpose of the identifier (e.g., “official”, “secondary”) | Identifier.use[1] |
assigner | Organization issuing the identifier (name or Organization reference) | Identifier.assigner[1] |
If you need the exact URI for your country’s or organization’s prescription identifier system, consult official HL7 FHIR implementation guides or identifier registries, and ensure the URI used is controlled, documented, and stable[1][4][5].
Citations:
- 1: http://hl7.org.au/fhir/4.0.0/StructureDefinition-au-localprescriptionidentifier-definitions.html
- 2: https://simplifier.net/guide/SATUSEHAT-FHIR-R4-Implementation-Guide/Home/FHIRProfiles/Medication.page.md?version=current
- 3: https://informatiestandaarden.nictiz.nl/wiki/mp:V2.0.0_MedicationProcess9_FHIR
- 4: http://fhir.outburn.co.il/R4-spec/identifier-registry.html
- 5: https://build.fhir.org/ig/HL7/smp-ig/
- 6: https://build.fhir.org/ig/HL7/fhir-specialty-rx/
- 7: https://build.fhir.org/resource.html
- 8: https://hapifhir.io/hapi-fhir/apidocs/hapi-fhir-structures-r4/org/hl7/fhir/r4/model/Medication.html
- 9: https://simplifier.net/guide/ACCESSGatewayEHRSpecificationHL7FHIRImplementationGuide-v1.0.0/MedicationRequestClinicianExample
- 10: https://fire.ly/blog/element-identifiers-in-fhir/
@keshavsaharia Thank you for the additional context. Based on the FHIR R4 specification I retrieved, the standard guidance confirms that Identifier.system should be the namespace/assigning authority URI (like https://health.gov/prescriptions/id
), not a code system URI like http://terminology.hl7.org/CodeSystem/v2-0203
.
However, I acknowledge there may be specific HL7 implementation guides or Surescripts-specific profiles that recommend a different pattern than the base FHIR R4 specification. These domain-specific guides sometimes provide alternative approaches for particular use cases or integration scenarios.
Your decision to defer this to the upcoming PR makes perfect sense - it will allow for a comprehensive review of the identifier patterns alongside the specific HL7/Surescripts guidance you're referencing. This way we can ensure the implementation aligns with the most appropriate standard for your integration context.
✏️ Learnings added
Learnt from: keshavsaharia
PR: metriport/metriport#4404
File: packages/core/src/external/surescripts/fhir/medication-request.ts:75-94
Timestamp: 2025-08-18T22:03:40.549Z
Learning: User keshavsaharia indicated that HL7 guidance contradicts the standard FHIR R4 specification regarding Identifier.system usage in packages/core/src/external/surescripts/fhir/medication-request.ts, specifically that using HL7_CODE_SYSTEM_URL in Identifier.system may be correct according to HL7 guidance despite appearing to violate standard FHIR patterns.
Learnt from: keshavsaharia
PR: metriport/metriport#4404
File: packages/core/src/external/surescripts/fhir/medication-request.ts:75-94
Timestamp: 2025-08-18T22:03:40.549Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, there's a discrepancy between standard FHIR R4 specification (which recommends assigning authority URIs in Identifier.system) and specific HL7 guidance that user keshavsaharia references, which may support using code system URIs like "http://terminology.hl7.org/CodeSystem/v2-0203" in Identifier.system for Surescripts integration. This needs to be addressed in future PR with proper HL7 implementation guide references.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: keshavsaharia
PR: metriport/metriport#4075
File: packages/core/src/external/surescripts/fhir/medication-request.ts:76-83
Timestamp: 2025-06-25T18:42:07.231Z
Learning: In packages/core/src/external/surescripts/fhir/medication-request.ts, the getDispenseNote and getDosageInstruction functions are intentionally identical because the dashboard requires both the note and dosageInstruction fields of MedicationRequest to be populated with detail.directions for proper note display functionality.
Learnt from: thomasyopes
PR: metriport/metriport#3970
File: packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts:17-17
Timestamp: 2025-06-06T16:45:31.832Z
Learning: The writeMedicationToChart function in packages/api/src/external/ehr/athenahealth/command/write-back/medication.ts returns a response that is not currently used by any consumers, so changes to its return type are not breaking changes in practice.
Learnt from: keshavsaharia
PR: metriport/metriport#4370
File: packages/core/src/external/quest/id-generator.ts:5-8
Timestamp: 2025-08-15T00:20:50.840Z
Learning: User keshavsaharia highly values rigorous mathematical analysis and comprehensive technical solutions that include both problem identification and complete remediation paths, particularly appreciating when statistical claims are verified and corrected with proper calculations.
Learnt from: keshavsaharia
PR: metriport/metriport#4020
File: packages/core/src/external/fhir/adt-encounters.ts:245-253
Timestamp: 2025-08-04T17:46:17.853Z
Learning: User keshavsaharia prefers lodash chains over native JavaScript methods for readability when working with complex data transformations, even when it involves using underscore imports and might have less robust error handling.
* You can sync a directory in the SFTP server to an S3 bucket if the associated S3 client has | ||
* been initialized with `initializeS3Replica`. | ||
* @see @metriport/core/external/sftp/replica.ts for more details. | ||
* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify @see path and symbol name referenced in docs
The comment references initializeS3Replica and @metriport/core/external/sftp/replica.ts. Please confirm:
- The symbol name is correct and exported.
- The documented path exists (current structure suggests replica/s3.ts or a replica index).
If needed, adjust the @see to the concrete file.
You can run this script to verify and locate both the file and the symbol:
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Searching for replica.ts (or close variants) to validate @see path..."
fd -a -g 'replica.ts' -g 'replica/index.ts' -g 'replica/*.ts' | sed -n '1,200p'
echo
echo "Searching for initializeS3Replica symbol..."
rg -n -C2 -P '\binitializeS3Replica\b'
Length of output: 407
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Locating 'replica' directory under core external sftp:"
fd -t d -g 'packages/core/src/external/sftp/replica' | sed -n '1,20p'
echo
echo "Listing .ts files in replica directory (if it exists):"
if [ -d packages/core/src/external/sftp/replica ]; then
ls -1 packages/core/src/external/sftp/replica/*.ts | sed -n '1,200p'
else
echo "Directory not found: packages/core/src/external/sftp/replica"
fi
echo
echo "Searching for 'initializeS3Replica' definition in the repo:"
rg -nP 'export\s+(?:async\s+)?(?:function|const)\s+initializeS3Replica' -C2 --glob '*.ts' || echo "No definition found"
echo
echo "Searching for any usage of 'initializeS3Replica' across the codebase:"
rg -nP '\binitializeS3Replica\b' -C2 --glob '*.ts' || echo "No references found"
Length of output: 674
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "1) Finding all 'replica' directories under packages:"
fd -t d replica packages | sed -n '1,50p' || echo "No 'replica' dirs found"
echo
echo "2) Listing .ts files in packages/core/src/external/sftp/replica (if it exists):"
if [ -d packages/core/src/external/sftp/replica ]; then
fd '' packages/core/src/external/sftp/replica --extension ts | sed -n '1,200p'
else
echo "Directory not found: packages/core/src/external/sftp/replica"
fi
echo
echo "3) Searching for initializeS3Replica across all .ts files in packages:"
rg -nP '\binitializeS3Replica\b' --glob 'packages/**/*.ts' -C2 || echo "No occurrences of initializeS3Replica found"
Length of output: 2063
Update the @see reference in sftp‐action documentation
The initializeS3Replica
symbol is correct, but there is no replica.ts
file under @metriport/core/external/sftp
. To link to the S3 replica implementation, update the @see
tag to point at replica/s3.ts
:
• File: packages/utils/src/surescripts/sftp-action.ts
Lines 28–31
* You can sync a directory in the SFTP server to an S3 bucket if the associated SFTP client has
* been initialized with `initializeS3Replica`.
- * @see @metriport/core/external/sftp/replica.ts for more details.
+ * @see @metriport/core/external/sftp/replica/s3.ts for more details.
*
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
* You can sync a directory in the SFTP server to an S3 bucket if the associated S3 client has | |
* been initialized with `initializeS3Replica`. | |
* @see @metriport/core/external/sftp/replica.ts for more details. | |
* | |
* You can sync a directory in the SFTP server to an S3 bucket if the associated SFTP client has | |
* been initialized with `initializeS3Replica`. | |
* @see @metriport/core/external/sftp/replica/s3.ts for more details. | |
* |
🤖 Prompt for AI Agents
In packages/utils/src/surescripts/sftp-action.ts around lines 28 to 31, the
JSDoc @see currently points to @metriport/core/external/sftp/replica.ts which
doesn't exist; update the @see reference to point to the correct S3 replica
implementation at @metriport/core/external/sftp/replica/s3.ts so the
documentation links to the actual file.
Issues:
Dependencies
Description
Testing
Check each PR.
Release Plan
master
Summary by CodeRabbit