From 945d3003ff3c816a3ef377ae79e8c4298449c65e Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Thu, 24 Aug 2023 11:33:09 -0400 Subject: [PATCH 01/20] added .idea to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index a5a6574ad0..a28a470d1a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,9 +9,10 @@ bin/** /.gradle/ /bin/ - +/.idea/ /failed_exports/ /output/ + /out/ **/*.log From 76e05f3e790a9356ceeaa2ce46a4fab0d89f6eea Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Thu, 24 Aug 2023 14:05:29 -0400 Subject: [PATCH 02/20] added a dummy appt resource --- .../java/org/mitre/synthea/export/FhirR4.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index fe6771d7e1..3ba8e09eba 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -505,6 +505,11 @@ public static Bundle convertToFHIR(Person person, long stopTime) { encounterClaim, encounter, encounter.claim); } } + + // add appointment to every encounter as well + if (shouldExport(org.hl7.fhir.r4.model.Appointment.class)) { + BundleEntryComponent apptEncounter = encounterAppointment(person, personEntry, bundle, encounter, encounterEntry); + } } if (USE_US_CORE_IG && shouldExport(Provenance.class)) { @@ -514,6 +519,16 @@ public static Bundle convertToFHIR(Person person, long stopTime) { return bundle; } + private static BundleEntryComponent encounterAppointment(Person person, BundleEntryComponent personEntry, + Bundle bundle, Encounter encounter, + BundleEntryComponent encounterEntry) { + + org.hl7.fhir.r4.model.Appointment apptResource = new org.hl7.fhir.r4.model.Appointment(); + apptResource.setId("appt_id"); + return newEntry(bundle, apptResource, apptResource.getId()); + + } + /** * Convert the given Person into a JSON String, containing a FHIR Bundle of the Person and the * associated entries from their health record. From 46f5bc06834c91c8158b998b642f854f6faef5e2 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Thu, 24 Aug 2023 17:30:44 -0400 Subject: [PATCH 03/20] added changes to report Appointments based on Encounters --- .../java/org/mitre/synthea/export/FhirR4.java | 115 ++++++++++-------- 1 file changed, 66 insertions(+), 49 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index 3ba8e09eba..bac22fecb9 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -24,13 +24,10 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; -import org.hl7.fhir.r4.model.Address; -import org.hl7.fhir.r4.model.AllergyIntolerance; +import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.AllergyIntolerance.AllergyIntoleranceCategory; import org.hl7.fhir.r4.model.AllergyIntolerance.AllergyIntoleranceCriticality; import org.hl7.fhir.r4.model.AllergyIntolerance.AllergyIntoleranceType; -import org.hl7.fhir.r4.model.BooleanType; -import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Bundle.BundleEntryRequestComponent; import org.hl7.fhir.r4.model.Bundle.BundleType; @@ -40,7 +37,6 @@ import org.hl7.fhir.r4.model.CarePlan.CarePlanActivityStatus; import org.hl7.fhir.r4.model.CarePlan.CarePlanIntent; import org.hl7.fhir.r4.model.CarePlan.CarePlanStatus; -import org.hl7.fhir.r4.model.CareTeam; import org.hl7.fhir.r4.model.CareTeam.CareTeamParticipantComponent; import org.hl7.fhir.r4.model.CareTeam.CareTeamStatus; import org.hl7.fhir.r4.model.Claim.ClaimStatus; @@ -49,88 +45,45 @@ import org.hl7.fhir.r4.model.Claim.ItemComponent; import org.hl7.fhir.r4.model.Claim.ProcedureComponent; import org.hl7.fhir.r4.model.Claim.SupportingInformationComponent; -import org.hl7.fhir.r4.model.CodeType; -import org.hl7.fhir.r4.model.CodeableConcept; -import org.hl7.fhir.r4.model.Coding; -import org.hl7.fhir.r4.model.Condition; -import org.hl7.fhir.r4.model.ContactPoint; import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; import org.hl7.fhir.r4.model.ContactPoint.ContactPointUse; -import org.hl7.fhir.r4.model.Coverage; import org.hl7.fhir.r4.model.Coverage.CoverageStatus; -import org.hl7.fhir.r4.model.DateTimeType; -import org.hl7.fhir.r4.model.DateType; -import org.hl7.fhir.r4.model.DecimalType; -import org.hl7.fhir.r4.model.Device; import org.hl7.fhir.r4.model.Device.DeviceNameType; import org.hl7.fhir.r4.model.Device.FHIRDeviceStatus; -import org.hl7.fhir.r4.model.DiagnosticReport; import org.hl7.fhir.r4.model.DiagnosticReport.DiagnosticReportStatus; -import org.hl7.fhir.r4.model.DocumentReference; import org.hl7.fhir.r4.model.DocumentReference.DocumentReferenceContextComponent; -import org.hl7.fhir.r4.model.Dosage; import org.hl7.fhir.r4.model.Dosage.DosageDoseAndRateComponent; import org.hl7.fhir.r4.model.Encounter.EncounterHospitalizationComponent; import org.hl7.fhir.r4.model.Encounter.EncounterStatus; import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; import org.hl7.fhir.r4.model.Enumerations.DocumentReferenceStatus; -import org.hl7.fhir.r4.model.ExplanationOfBenefit; import org.hl7.fhir.r4.model.ExplanationOfBenefit.RemittanceOutcome; import org.hl7.fhir.r4.model.ExplanationOfBenefit.TotalComponent; import org.hl7.fhir.r4.model.ExplanationOfBenefit.Use; -import org.hl7.fhir.r4.model.Extension; -import org.hl7.fhir.r4.model.Goal; import org.hl7.fhir.r4.model.Goal.GoalLifecycleStatus; -import org.hl7.fhir.r4.model.HumanName; -import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Identifier.IdentifierUse; import org.hl7.fhir.r4.model.ImagingStudy.ImagingStudySeriesComponent; import org.hl7.fhir.r4.model.ImagingStudy.ImagingStudySeriesInstanceComponent; import org.hl7.fhir.r4.model.ImagingStudy.ImagingStudyStatus; import org.hl7.fhir.r4.model.Immunization.ImmunizationStatus; -import org.hl7.fhir.r4.model.Immunization; -import org.hl7.fhir.r4.model.IntegerType; import org.hl7.fhir.r4.model.Location.LocationPositionComponent; import org.hl7.fhir.r4.model.Location.LocationStatus; -import org.hl7.fhir.r4.model.Media; import org.hl7.fhir.r4.model.Media.MediaStatus; import org.hl7.fhir.r4.model.Medication.MedicationStatus; -import org.hl7.fhir.r4.model.MedicationAdministration; import org.hl7.fhir.r4.model.MedicationAdministration.MedicationAdministrationDosageComponent; -import org.hl7.fhir.r4.model.MedicationRequest; import org.hl7.fhir.r4.model.MedicationRequest.MedicationRequestIntent; import org.hl7.fhir.r4.model.MedicationRequest.MedicationRequestStatus; -import org.hl7.fhir.r4.model.Meta; -import org.hl7.fhir.r4.model.Money; -import org.hl7.fhir.r4.model.Narrative; import org.hl7.fhir.r4.model.Narrative.NarrativeStatus; import org.hl7.fhir.r4.model.Observation.ObservationComponentComponent; import org.hl7.fhir.r4.model.Observation.ObservationStatus; -import org.hl7.fhir.r4.model.Organization; -import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Patient.ContactComponent; import org.hl7.fhir.r4.model.Patient.PatientCommunicationComponent; -import org.hl7.fhir.r4.model.Period; -import org.hl7.fhir.r4.model.PositiveIntType; -import org.hl7.fhir.r4.model.Practitioner; -import org.hl7.fhir.r4.model.PractitionerRole; import org.hl7.fhir.r4.model.Procedure.ProcedureStatus; -import org.hl7.fhir.r4.model.Property; -import org.hl7.fhir.r4.model.Provenance; import org.hl7.fhir.r4.model.Provenance.ProvenanceAgentComponent; -import org.hl7.fhir.r4.model.Quantity; -import org.hl7.fhir.r4.model.Reference; -import org.hl7.fhir.r4.model.Resource; -import org.hl7.fhir.r4.model.ServiceRequest; -import org.hl7.fhir.r4.model.SimpleQuantity; -import org.hl7.fhir.r4.model.StringType; -import org.hl7.fhir.r4.model.SupplyDelivery; import org.hl7.fhir.r4.model.SupplyDelivery.SupplyDeliveryStatus; import org.hl7.fhir.r4.model.SupplyDelivery.SupplyDeliverySuppliedItemComponent; -import org.hl7.fhir.r4.model.Timing; import org.hl7.fhir.r4.model.Timing.TimingRepeatComponent; import org.hl7.fhir.r4.model.Timing.UnitsOfTime; -import org.hl7.fhir.r4.model.Type; import org.hl7.fhir.r4.model.codesystems.DoseRateType; import org.hl7.fhir.utilities.xhtml.NodeType; @@ -524,7 +477,71 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn BundleEntryComponent encounterEntry) { org.hl7.fhir.r4.model.Appointment apptResource = new org.hl7.fhir.r4.model.Appointment(); - apptResource.setId("appt_id"); + apptResource.setId("appt:" + encounter.uuid.toString()); + + // convert participant + org.hl7.fhir.r4.model.Encounter encounterResource = + (org.hl7.fhir.r4.model.Encounter) encounterEntry.getResource(); + + //status + apptResource.setStatus(Appointment.AppointmentStatus.FULFILLED); + + // appt type + + CodeableConcept aTypeCC = new CodeableConcept(); + aTypeCC.setText("Appt Type"); + Coding apptTypeCoding = aTypeCC.addCoding().setCode("apptType") + .setDisplay("Appt Type display").setSystem("appt Type System"); + + apptResource.setAppointmentType(aTypeCC); + + // serviceCategory + List categories = new ArrayList<>(); + CodeableConcept cc = new CodeableConcept(); + cc.setText("category 1"); + Coding serviceCatCoding = cc.addCoding(); + serviceCatCoding.setDisplay("cat 1 display"); + serviceCatCoding.setSystem("cat 1 system"); + serviceCatCoding.setCode("cat1"); + + categories.add(cc); + apptResource.setServiceCategory(categories); + + // serviceType + List types = new ArrayList<>(); + CodeableConcept stcc = new CodeableConcept(); + stcc.setText("type 1"); + Coding serviceTypesCoding = stcc.addCoding(); + serviceTypesCoding.setDisplay("type 1 display"); + serviceTypesCoding.setSystem("type 1 system"); + serviceTypesCoding.setCode("type1"); + + types.add(stcc); + apptResource.setServiceType(types); + + + // add all participants + List aPList = new ArrayList<>(); + for (org.hl7.fhir.r4.model.Encounter.EncounterParticipantComponent eParticipant : encounterResource.getParticipant()) { + Appointment.AppointmentParticipantComponent aProvider = new Appointment.AppointmentParticipantComponent(); + // Add provider + aProvider.setPeriod(eParticipant.getPeriod()); + aProvider.setActor(eParticipant.getIndividual()); + + aPList.add(aProvider); + + + // Add location + Appointment.AppointmentParticipantComponent aLoc = new Appointment.AppointmentParticipantComponent(); + aLoc.setActor(encounterResource.getLocation().get(0).getLocation()); + aPList.add(aLoc); + + + + } + apptResource.setParticipant(aPList); + + return newEntry(bundle, apptResource, apptResource.getId()); } From 4b27b09c12d749beaaaf3692dd46ae9117687d0d Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Fri, 25 Aug 2023 12:49:51 -0400 Subject: [PATCH 04/20] fixed some appointment related execute bundle errors --- src/main/java/org/mitre/synthea/export/FhirR4.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index bac22fecb9..8b7cb2477e 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -114,6 +114,8 @@ import org.mitre.synthea.world.concepts.HealthRecord.Report; import org.mitre.synthea.world.geography.Location; +import static com.oracle.truffle.js.builtins.math.MathBuiltins.Math.random; + public class FhirR4 { // HAPI FHIR warns that the context creation is expensive, and should be performed // per-application, not per-record @@ -477,14 +479,14 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn BundleEntryComponent encounterEntry) { org.hl7.fhir.r4.model.Appointment apptResource = new org.hl7.fhir.r4.model.Appointment(); - apptResource.setId("appt:" + encounter.uuid.toString()); + apptResource.setId(String.valueOf(UUID.randomUUID())); // convert participant org.hl7.fhir.r4.model.Encounter encounterResource = (org.hl7.fhir.r4.model.Encounter) encounterEntry.getResource(); //status - apptResource.setStatus(Appointment.AppointmentStatus.FULFILLED); + apptResource.setStatus(Appointment.AppointmentStatus.PROPOSED); // appt type @@ -527,6 +529,7 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn // Add provider aProvider.setPeriod(eParticipant.getPeriod()); aProvider.setActor(eParticipant.getIndividual()); + aProvider.setStatus(Appointment.ParticipationStatus.ACCEPTED); aPList.add(aProvider); @@ -534,6 +537,7 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn // Add location Appointment.AppointmentParticipantComponent aLoc = new Appointment.AppointmentParticipantComponent(); aLoc.setActor(encounterResource.getLocation().get(0).getLocation()); + aLoc.setStatus(Appointment.ParticipationStatus.ACCEPTED); aPList.add(aLoc); From 7207bc2572e40046c779b9c31e8336becaefcf8e Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Fri, 25 Aug 2023 14:25:25 -0400 Subject: [PATCH 05/20] add patient in appt --- src/main/java/org/mitre/synthea/export/FhirR4.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index 8b7cb2477e..ca18202e48 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -540,6 +540,11 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn aLoc.setStatus(Appointment.ParticipationStatus.ACCEPTED); aPList.add(aLoc); + //Add patient + Appointment.AppointmentParticipantComponent aPatient = new Appointment.AppointmentParticipantComponent(); + aPatient.setActor(encounterResource.getSubject()); + aPatient.setStatus(Appointment.ParticipationStatus.ACCEPTED); + aPList.add(aPatient); } From 3114575a0ed558c73adb16732a06bc41ea6479b1 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Wed, 30 Aug 2023 11:06:16 -0400 Subject: [PATCH 06/20] added identifier to the appt --- src/main/java/org/mitre/synthea/export/FhirR4.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index ca18202e48..234b0aa936 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -488,6 +488,14 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn //status apptResource.setStatus(Appointment.AppointmentStatus.PROPOSED); + // identifier + List identifierList = new ArrayList<>(); + identifierList.add(new Identifier() + .setSystem("http://fhir.league.com/r4/LeagueUserProfiles/NamingSystem/league-user-id") + .setValue((String) person.attributes.get(Person.ID))); + + apptResource.setIdentifier(identifierList); + // appt type CodeableConcept aTypeCC = new CodeableConcept(); @@ -546,8 +554,8 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn aPatient.setStatus(Appointment.ParticipationStatus.ACCEPTED); aPList.add(aPatient); - } + apptResource.setParticipant(aPList); From 3d75c6e260a128176ed7b7f0a5f6c50b1131c7a4 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Wed, 30 Aug 2023 12:21:05 -0400 Subject: [PATCH 07/20] added custom extension stringValue --- src/main/java/org/mitre/synthea/export/FhirR4.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index 234b0aa936..b3fbf78be0 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -529,6 +529,14 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn types.add(stcc); apptResource.setServiceType(types); + //adding a custom extension + List extnList = new ArrayList<>(); + Coding extnCoding = new Coding().setCode("extn code 1").setDisplay("extn display code"); + extnList.add(new Extension() + .setUrl("http://fhir.league.com/r4/LeagueCareServiceBookings/StructureDefinition/custom-extension") + .setValue(new StringType("custom-exn-val"))); + apptResource.setExtension(extnList); + // add all participants List aPList = new ArrayList<>(); From ee9bee31ff11bfc8be7ebcd1ec9b2434ba8c4918 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Wed, 6 Sep 2023 11:14:02 -0400 Subject: [PATCH 08/20] removed unused variable --- src/main/java/org/mitre/synthea/export/FhirR4.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index b3fbf78be0..a234f14e00 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -463,7 +463,7 @@ public static Bundle convertToFHIR(Person person, long stopTime) { // add appointment to every encounter as well if (shouldExport(org.hl7.fhir.r4.model.Appointment.class)) { - BundleEntryComponent apptEncounter = encounterAppointment(person, personEntry, bundle, encounter, encounterEntry); + encounterAppointment(person, personEntry, bundle, encounter, encounterEntry); } } From e94889aa8a6500e73409563b30b21d675ef8bcac Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Wed, 6 Sep 2023 14:16:56 -0400 Subject: [PATCH 09/20] add valid attribs for Consent --- .../java/org/mitre/synthea/export/FhirR4.java | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index a234f14e00..ecbf19353f 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -10,6 +10,8 @@ import java.awt.geom.Point2D; import java.io.IOException; +import java.time.Instant; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -113,8 +115,7 @@ import org.mitre.synthea.world.concepts.HealthRecord.Procedure; import org.mitre.synthea.world.concepts.HealthRecord.Report; import org.mitre.synthea.world.geography.Location; - -import static com.oracle.truffle.js.builtins.math.MathBuiltins.Math.random; +import org.opencds.cqf.cql.engine.runtime.DateTime; public class FhirR4 { // HAPI FHIR warns that the context creation is expensive, and should be performed @@ -358,6 +359,11 @@ public static Bundle convertToFHIR(Person person, long stopTime) { BundleEntryComponent personEntry = basicInfo(person, bundle, stopTime); + if (shouldExport(Consent.class)) { + consentByPerson(person, bundle, personEntry,""); + consentByPerson(person, bundle, personEntry,"gina"); + } + for (Encounter encounter : person.record.encounters) { BundleEntryComponent encounterEntry = encounter(person, personEntry, bundle, encounter); @@ -474,6 +480,74 @@ public static Bundle convertToFHIR(Person person, long stopTime) { return bundle; } + private static BundleEntryComponent consentByPerson(Person person, Bundle bundle, BundleEntryComponent personEntry, String type) { + org.hl7.fhir.r4.model.Consent consent = new Consent(); + + consent.setPatient(new Reference() + .setReference(personEntry.getFullUrl()) + .setDisplay(person.attributes + .get(Person.FIRST_NAME).toString() + + + person.attributes.get(Person.LAST_NAME).toString())); + List codingList = new ArrayList<>(); +// set category + if (type.equals(new String(""))) { + CodeableConcept termsAndConditionsCC = new CodeableConcept(); + termsAndConditionsCC.addCoding().setCode("terms_and_conditions") + .setDisplay("Terms and Conditions") + .setSystem("terms and conditions"); + codingList.add(termsAndConditionsCC); + } else { + CodeableConcept ginaCC = new CodeableConcept(); + ginaCC.addCoding().setCode("gina") + .setDisplay("GINA") + .setSystem("gina"); + codingList.add(ginaCC); + } + + + consent.setCategory(codingList); + + // status set + consent.setStatus(Consent.ConsentState.ACTIVE); + + // date time + consent.setDateTime(Date.from(Instant.now())); + + consent.setId(String.valueOf(UUID.randomUUID())); + if (type.equals(new String(""))) { + consent.setProvision(new Consent.provisionComponent().setType(Consent.ConsentProvisionType.PERMIT)); + } else { + LocalDateTime now = LocalDateTime.now(); + LocalDateTime end = now.plusDays(365); + + + + consent.setProvision(new Consent.provisionComponent().setType(Consent.ConsentProvisionType.PERMIT) + .setPeriod( + new Period() + .setStart(java.sql.Timestamp.valueOf(now)) + .setEnd(java.sql.Timestamp.valueOf(end)) + ) + ); + } + + // adding scope + CodeableConcept scopeCC = new CodeableConcept(); + scopeCC.addCoding().setCode("active"); + consent.setScope(scopeCC); + + // policy rule Codeable Concept addition + CodeableConcept policyRuleCC = new CodeableConcept(); + policyRuleCC.addCoding().setCode("policy rule").setDisplay("Policy Rule"); + consent.setPolicyRule(policyRuleCC); + + + + return newEntry(bundle, consent, consent.getId()); + } + + private static BundleEntryComponent encounterAppointment(Person person, BundleEntryComponent personEntry, Bundle bundle, Encounter encounter, BundleEntryComponent encounterEntry) { From 9dc7bcb271a6118088bdf2c64547c8ec695fd987 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Fri, 8 Sep 2023 10:20:42 -0400 Subject: [PATCH 10/20] add consent generation for every encounter --- .../java/org/mitre/synthea/export/FhirR4.java | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index ecbf19353f..e0000e0093 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -471,6 +471,10 @@ public static Bundle convertToFHIR(Person person, long stopTime) { if (shouldExport(org.hl7.fhir.r4.model.Appointment.class)) { encounterAppointment(person, personEntry, bundle, encounter, encounterEntry); } + + if (shouldExport(org.hl7.fhir.r4.model.Consent.class)) { + consentByEncounter(person, bundle,personEntry,encounter, encounterEntry); + } } if (USE_US_CORE_IG && shouldExport(Provenance.class)) { @@ -505,7 +509,6 @@ private static BundleEntryComponent consentByPerson(Person person, Bundle bundle codingList.add(ginaCC); } - consent.setCategory(codingList); // status set @@ -547,6 +550,55 @@ private static BundleEntryComponent consentByPerson(Person person, Bundle bundle return newEntry(bundle, consent, consent.getId()); } + private static BundleEntryComponent consentByEncounter(Person person, Bundle bundle, + BundleEntryComponent personEntry, Encounter encounter, + BundleEntryComponent encounterEntry) { + org.hl7.fhir.r4.model.Consent consent = new Consent(); + + // convert participant + org.hl7.fhir.r4.model.Encounter encounterResource = + (org.hl7.fhir.r4.model.Encounter) encounterEntry.getResource(); + + consent.setPatient(new Reference() + .setReference(personEntry.getFullUrl()) + .setDisplay(person.attributes + .get(Person.FIRST_NAME).toString() + + + person.attributes.get(Person.LAST_NAME).toString())); + + List codingList = new ArrayList<>(); + CodeableConcept encounterCC = new CodeableConcept(); + encounterCC.addCoding().setCode("encounter:" + encounterResource.getId()) + .setDisplay("encounter:" + encounterResource.getId()) + .setSystem("encounter:" + encounterResource.getId()); + codingList.add(encounterCC); + consent.setCategory(codingList); + + // status set + consent.setStatus(Consent.ConsentState.ACTIVE); + + // date time + consent.setDateTime(Date.from(Instant.now())); + + consent.setId(String.valueOf(UUID.randomUUID())); + + consent.setProvision( + new Consent.provisionComponent().setType(Consent.ConsentProvisionType.PERMIT) + ); + + // adding scope + CodeableConcept scopeCC = new CodeableConcept(); + scopeCC.addCoding().setCode("active"); + consent.setScope(scopeCC); + + // policy rule Codeable Concept addition + CodeableConcept policyRuleCC = new CodeableConcept(); + policyRuleCC.addCoding().setCode("policy rule").setDisplay("Policy Rule"); + consent.setPolicyRule(policyRuleCC); + + return newEntry(bundle, consent, consent.getId()); + + } private static BundleEntryComponent encounterAppointment(Person person, BundleEntryComponent personEntry, Bundle bundle, Encounter encounter, From 33dfe3fc0e99bac944d15776610c60e69c1ea02f Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Mon, 11 Sep 2023 15:07:27 -0400 Subject: [PATCH 11/20] Changed the code to a sha256 hex string for better searchability --- .../java/org/mitre/synthea/export/FhirR4.java | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index e0000e0093..a4cd69e0a7 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -10,6 +10,9 @@ import java.awt.geom.Point2D; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.time.LocalDateTime; import java.util.ArrayList; @@ -25,6 +28,7 @@ import java.util.UUID; import java.util.stream.Collectors; +import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.hl7.fhir.r4.model.*; import org.hl7.fhir.r4.model.AllergyIntolerance.AllergyIntoleranceCategory; @@ -473,7 +477,9 @@ public static Bundle convertToFHIR(Person person, long stopTime) { } if (shouldExport(org.hl7.fhir.r4.model.Consent.class)) { - consentByEncounter(person, bundle,personEntry,encounter, encounterEntry); + + consentByEncounter(person, bundle,personEntry,encounter, encounterEntry); + } } @@ -566,11 +572,19 @@ private static BundleEntryComponent consentByEncounter(Person person, Bundle bun + person.attributes.get(Person.LAST_NAME).toString())); + //filter out practitioner + org.hl7.fhir.r4.model.Encounter.EncounterParticipantComponent practitioner + = encounterResource.getParticipant().get(0); + List codingList = new ArrayList<>(); CodeableConcept encounterCC = new CodeableConcept(); - encounterCC.addCoding().setCode("encounter:" + encounterResource.getId()) - .setDisplay("encounter:" + encounterResource.getId()) - .setSystem("encounter:" + encounterResource.getId()); + + String consentCode = "encounter:" + encounterResource.getId() + ":" + practitioner.getIndividual().getReference(); + String CodeInSha256Hex = DigestUtils.sha256Hex(consentCode); + encounterCC.addCoding() + .setCode(CodeInSha256Hex) + .setDisplay("encounter:" + encounterResource.getId() + ":" + practitioner.getIndividual().getReference()) + .setSystem("encounter:" + encounterResource.getId() + ":" + practitioner.getIndividual().getReference()); codingList.add(encounterCC); consent.setCategory(codingList); From 39f1045189c953a63cbe1a08bd98dd5bb2d2626e Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Mon, 11 Sep 2023 15:09:20 -0400 Subject: [PATCH 12/20] cleaned up a few imports --- src/main/java/org/mitre/synthea/export/FhirR4.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index a4cd69e0a7..dbdcc8f417 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -10,9 +10,6 @@ import java.awt.geom.Point2D; import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import java.time.Instant; import java.time.LocalDateTime; import java.util.ArrayList; @@ -119,7 +116,7 @@ import org.mitre.synthea.world.concepts.HealthRecord.Procedure; import org.mitre.synthea.world.concepts.HealthRecord.Report; import org.mitre.synthea.world.geography.Location; -import org.opencds.cqf.cql.engine.runtime.DateTime; + public class FhirR4 { // HAPI FHIR warns that the context creation is expensive, and should be performed From 02e1952bc2f04581beed5a7023767eed8d0727e3 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Tue, 12 Sep 2023 15:46:02 -0400 Subject: [PATCH 13/20] add a custom extn to inject custom ids --- .../java/org/mitre/synthea/export/FhirR4.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index dbdcc8f417..981bb5558a 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -576,12 +576,13 @@ private static BundleEntryComponent consentByEncounter(Person person, Bundle bun List codingList = new ArrayList<>(); CodeableConcept encounterCC = new CodeableConcept(); + // say we want appointment id and practitioner ref to generate a hash String consentCode = "encounter:" + encounterResource.getId() + ":" + practitioner.getIndividual().getReference(); String CodeInSha256Hex = DigestUtils.sha256Hex(consentCode); encounterCC.addCoding() - .setCode(CodeInSha256Hex) - .setDisplay("encounter:" + encounterResource.getId() + ":" + practitioner.getIndividual().getReference()) - .setSystem("encounter:" + encounterResource.getId() + ":" + practitioner.getIndividual().getReference()); + .setCode("appointment-booking") + .setDisplay("Appointment Booking") + .setSystem("url/coding-system-consents"); codingList.add(encounterCC); consent.setCategory(codingList); @@ -607,6 +608,16 @@ private static BundleEntryComponent consentByEncounter(Person person, Bundle bun policyRuleCC.addCoding().setCode("policy rule").setDisplay("Policy Rule"); consent.setPolicyRule(policyRuleCC); + + //adding a custom extension + List extnList = new ArrayList<>(); + Coding extnCoding = new Coding().setCode("extn code 1").setDisplay("extn display code"); + extnList.add(new Extension() + .setUrl("http://example.com/fhir/extensions#appointment-id-token") + .setValue(new Identifier().setValue(CodeInSha256Hex)) + ); + consent.setExtension(extnList); + return newEntry(bundle, consent, consent.getId()); } From 01acac6984fb8bac505de98d05bb8bfcb02c381a Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Wed, 13 Sep 2023 13:46:51 -0400 Subject: [PATCH 14/20] add multiple extension to consent --- .../java/org/mitre/synthea/export/FhirR4.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index 981bb5558a..7cc30b6395 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -612,9 +612,26 @@ private static BundleEntryComponent consentByEncounter(Person person, Bundle bun //adding a custom extension List extnList = new ArrayList<>(); Coding extnCoding = new Coding().setCode("extn code 1").setDisplay("extn display code"); + // searchable extension string extnList.add(new Extension() .setUrl("http://example.com/fhir/extensions#appointment-id-token") - .setValue(new Identifier().setValue(CodeInSha256Hex)) + .setValue(new StringType(CodeInSha256Hex)) + + ); + + // identifier extn + extnList.add(new Extension() + .setUrl("http://example.com/fhir/extensions#appointment-valueIdentifier") + .setValue(new Identifier() + .setValue("value-identifier") + .setSystem("http://example.com/token-system") + .setUse(IdentifierUse.OFFICIAL)) + ); + + // bool extn + extnList.add(new Extension() + .setUrl("http://example.com/fhir/extensions#appointment-valueBoolean") + .setValue(new BooleanType().setValue(true)) ); consent.setExtension(extnList); From f97815cfb05675c8569906742c3ffbe23bb6ac10 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Wed, 20 Sep 2023 15:50:46 -0400 Subject: [PATCH 15/20] added changes to create careplan tree based topology --- .../java/org/mitre/synthea/export/FhirR4.java | 68 ++++++++++++++++++- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index 7cc30b6395..ff4b703c58 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -359,6 +359,8 @@ public static Bundle convertToFHIR(Person person, long stopTime) { } BundleEntryComponent personEntry = basicInfo(person, bundle, stopTime); + // create one root careplan up top + BundleEntryComponent rootCarePlanEntry = rootCarePlan(person,personEntry,bundle); if (shouldExport(Consent.class)) { consentByPerson(person, bundle, personEntry,""); @@ -433,15 +435,22 @@ public static Bundle convertToFHIR(Person person, long stopTime) { if (shouldExport(org.hl7.fhir.r4.model.CarePlan.class)) { final boolean shouldExportCareTeam = shouldExport(CareTeam.class); + for (CarePlan careplan : encounter.careplans) { BundleEntryComponent careTeamEntry = null; if (shouldExportCareTeam) { careTeamEntry = careTeam(person, personEntry, bundle, encounterEntry, careplan); } - carePlan(person, personEntry, bundle, encounterEntry, encounter.provider, careTeamEntry, - careplan); + BundleEntryComponent carePlanEntry = carePlan(person, personEntry, bundle, encounterEntry, encounter.provider, careTeamEntry, + careplan, rootCarePlanEntry); + + BundleEntryComponent carePlanChild1 = childCarePlan(person, personEntry, bundle, carePlanEntry, rootCarePlanEntry, "child1"); + BundleEntryComponent carePlanChild2 = childCarePlan(person, personEntry, bundle, carePlanEntry, rootCarePlanEntry, "child2"); + BundleEntryComponent carePlanChild3 = childCarePlan(person, personEntry, bundle, carePlanEntry, rootCarePlanEntry, "child3"); + } + } if (shouldExport(org.hl7.fhir.r4.model.ImagingStudy.class)) { @@ -480,6 +489,8 @@ public static Bundle convertToFHIR(Person person, long stopTime) { } } + + if (USE_US_CORE_IG && shouldExport(Provenance.class)) { // Add Provenance to the Bundle provenance(bundle, person, stopTime); @@ -2922,6 +2933,51 @@ private static void clinicalNote(Person person, } } + private static BundleEntryComponent rootCarePlan(Person person, + BundleEntryComponent personEntry, Bundle bundle) { + + org.hl7.fhir.r4.model.CarePlan careplanResource = new org.hl7.fhir.r4.model.CarePlan(); + careplanResource.setIntent(CarePlanIntent.PLAN); + careplanResource.setSubject(new Reference(personEntry.getFullUrl())); + + careplanResource.setStatus(CarePlanStatus.ACTIVE); + + careplanResource.addCategory(mapCodeToCodeableConcept( + new Code("http://hl7.org/fhir/us/core/CodeSystem/careplan-category", "root-assess-plan", + null), null)); + + + return newEntry(bundle, careplanResource, String.valueOf(UUID.randomUUID())); + } + + private static BundleEntryComponent childCarePlan(Person person, + BundleEntryComponent personEntry, Bundle bundle, + BundleEntryComponent parentCarePlan, + BundleEntryComponent rootCarePlan, + String childCode) { + + org.hl7.fhir.r4.model.CarePlan careplanResource = new org.hl7.fhir.r4.model.CarePlan(); + careplanResource.setIntent(CarePlanIntent.PROPOSAL); + careplanResource.setSubject(new Reference(personEntry.getFullUrl())); + + careplanResource.addCategory(mapCodeToCodeableConcept( + new Code("http://hl7.org/fhir/us/core/CodeSystem/careplan-category", childCode +"-assess-plan", + null), null)); + + careplanResource.setStatus(CarePlanStatus.COMPLETED); + + List partOfCarePlans = new ArrayList<>(); + partOfCarePlans.add(new Reference(parentCarePlan.getFullUrl())); + careplanResource.setPartOf(partOfCarePlans); + + List basedOfCarePlans = new ArrayList<>(); + basedOfCarePlans.add(new Reference(rootCarePlan.getFullUrl())); + + careplanResource.setBasedOn(basedOfCarePlans); + + + return newEntry(bundle, careplanResource, String.valueOf(UUID.randomUUID())); + } /** * Map the given CarePlan to a FHIR CarePlan resource, and add it to the given Bundle. * @@ -2935,7 +2991,7 @@ private static void clinicalNote(Person person, */ private static BundleEntryComponent carePlan(Person person, BundleEntryComponent personEntry, Bundle bundle, BundleEntryComponent encounterEntry, - Provider provider, BundleEntryComponent careTeamEntry, CarePlan carePlan) { + Provider provider, BundleEntryComponent careTeamEntry, CarePlan carePlan, BundleEntryComponent rootCarePlanEntry) { org.hl7.fhir.r4.model.CarePlan careplanResource = new org.hl7.fhir.r4.model.CarePlan(); if (USE_US_CORE_IG) { @@ -3031,6 +3087,12 @@ private static BundleEntryComponent carePlan(Person person, careplanResource.setText(new Narrative().setStatus(NarrativeStatus.GENERATED) .setDiv(new XhtmlNode(NodeType.Element).setValue(narrative))); + // set basedon + List basedOnRefs = new ArrayList<>(); + basedOnRefs.add(new Reference(rootCarePlanEntry.getFullUrl())); + careplanResource.setBasedOn(basedOnRefs); + careplanResource.setPartOf(basedOnRefs); + return newEntry(bundle, careplanResource, carePlan.uuid.toString()); } From d3788108d3ab27a02a80746aa21b16150780377a Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Mon, 25 Sep 2023 15:37:51 -0400 Subject: [PATCH 16/20] adding Task generation which is tied to a CarePlan --- .../java/org/mitre/synthea/export/FhirR4.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index ff4b703c58..c8d7a8eae6 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -449,6 +449,8 @@ public static Bundle convertToFHIR(Person person, long stopTime) { BundleEntryComponent carePlanChild2 = childCarePlan(person, personEntry, bundle, carePlanEntry, rootCarePlanEntry, "child2"); BundleEntryComponent carePlanChild3 = childCarePlan(person, personEntry, bundle, carePlanEntry, rootCarePlanEntry, "child3"); + //create a task and reverse link to root careplan + task(person,personEntry,bundle, rootCarePlanEntry); } } @@ -2978,6 +2980,29 @@ private static BundleEntryComponent childCarePlan(Person person, return newEntry(bundle, careplanResource, String.valueOf(UUID.randomUUID())); } + + private static BundleEntryComponent task(Person person, + BundleEntryComponent personEntry, + Bundle bundle, BundleEntryComponent rootCarePlanEntry) { + + org.hl7.fhir.r4.model.Task taskResource = new Task(); + + // add status + taskResource.setStatus(Task.TaskStatus.ACCEPTED); + + //add intent + taskResource.setIntent(Task.TaskIntent.PLAN); + + // add priority + taskResource.setPriority(Task.TaskPriority.ROUTINE); + + // add references to root care plan + List basedOnReferences = new ArrayList<>(); + basedOnReferences.add(new Reference(rootCarePlanEntry.getFullUrl())); + taskResource.setBasedOn(basedOnReferences); + + return newEntry(bundle, taskResource, String.valueOf(UUID.randomUUID())); + } /** * Map the given CarePlan to a FHIR CarePlan resource, and add it to the given Bundle. * From 8cb93fa7a557dee4f80a71ae34869c4a922baec3 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Tue, 26 Sep 2023 12:03:03 -0400 Subject: [PATCH 17/20] Added changes to reverse link ServiceRequest to the root-care-plan --- .../java/org/mitre/synthea/export/FhirR4.java | 55 +++++++++++++++---- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index c8d7a8eae6..936f42ece3 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -451,6 +451,9 @@ public static Bundle convertToFHIR(Person person, long stopTime) { //create a task and reverse link to root careplan task(person,personEntry,bundle, rootCarePlanEntry); + + //create a service request and reversse link to root care plan + serviceRequest(person, personEntry, bundle, rootCarePlanEntry); } } @@ -3001,19 +3004,49 @@ private static BundleEntryComponent task(Person person, basedOnReferences.add(new Reference(rootCarePlanEntry.getFullUrl())); taskResource.setBasedOn(basedOnReferences); + // set owner + taskResource.setOwner(new Reference(personEntry.getFullUrl())); + + return newEntry(bundle, taskResource, String.valueOf(UUID.randomUUID())); } - /** - * Map the given CarePlan to a FHIR CarePlan resource, and add it to the given Bundle. - * - * @param person The Person - * @param personEntry The Entry for the Person - * @param bundle Bundle to add the CarePlan to - * @param encounterEntry Current Encounter entry - * @param provider The current provider - * @param carePlan The CarePlan to map to FHIR and add to the bundle - * @return The added Entry - */ + + private static BundleEntryComponent serviceRequest(Person person, + BundleEntryComponent personEntry, + Bundle bundle, BundleEntryComponent rootCarePlanEntry) { + org.hl7.fhir.r4.model.ServiceRequest serviceRequestResource = new ServiceRequest(); + + // set status + serviceRequestResource.setStatus(ServiceRequest.ServiceRequestStatus.ACTIVE); + + // set priority + serviceRequestResource.setPriority(ServiceRequest.ServiceRequestPriority.ROUTINE); + + // set intent + serviceRequestResource.setIntent(ServiceRequest.ServiceRequestIntent.PLAN); + + // add references to root care plan + List basedOnReferences = new ArrayList<>(); + basedOnReferences.add(new Reference(rootCarePlanEntry.getFullUrl())); + serviceRequestResource.setBasedOn(basedOnReferences); + + // set subject + serviceRequestResource.setSubject(new Reference(personEntry.getFullUrl())); + + + return newEntry(bundle, serviceRequestResource, String.valueOf(UUID.randomUUID())); + } + /** + * Map the given CarePlan to a FHIR CarePlan resource, and add it to the given Bundle. + * + * @param person The Person + * @param personEntry The Entry for the Person + * @param bundle Bundle to add the CarePlan to + * @param encounterEntry Current Encounter entry + * @param provider The current provider + * @param carePlan The CarePlan to map to FHIR and add to the bundle + * @return The added Entry + */ private static BundleEntryComponent carePlan(Person person, BundleEntryComponent personEntry, Bundle bundle, BundleEntryComponent encounterEntry, Provider provider, BundleEntryComponent careTeamEntry, CarePlan carePlan, BundleEntryComponent rootCarePlanEntry) { From 5ec445d7b59a294f2221e9cf1191b67a83517397 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Tue, 26 Sep 2023 17:50:47 -0400 Subject: [PATCH 18/20] add questionnaire-response and link them to consents --- .../java/org/mitre/synthea/export/FhirR4.java | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index 936f42ece3..8f019ad043 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -489,7 +489,9 @@ public static Bundle convertToFHIR(Person person, long stopTime) { if (shouldExport(org.hl7.fhir.r4.model.Consent.class)) { - consentByEncounter(person, bundle,personEntry,encounter, encounterEntry); + BundleEntryComponent qr = questionnaireResponse(bundle, encounterEntry); + consentByEncounter(person, bundle,personEntry,encounter, encounterEntry, qr); + } } @@ -503,6 +505,32 @@ public static Bundle convertToFHIR(Person person, long stopTime) { return bundle; } + private static BundleEntryComponent questionnaireResponse(Bundle bundle, BundleEntryComponent encounterEntry) { + org.hl7.fhir.r4.model.QuestionnaireResponse qrResource = new QuestionnaireResponse(); + org.hl7.fhir.r4.model.Encounter encounter = (org.hl7.fhir.r4.model.Encounter) encounterEntry.getResource(); + + qrResource.setStatus(QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED); + + qrResource.setEncounter(new Reference(encounterEntry.getFullUrl())); + + List items = new ArrayList<>(); + List answers = new ArrayList<>(); + answers.add( + new QuestionnaireResponse.QuestionnaireResponseItemAnswerComponent() + .setValue(new BooleanType(true)) + ); + items.add( + new QuestionnaireResponse.QuestionnaireResponseItemComponent() + .setAnswer(answers).setLinkId("1.0").setText("Do u consent to this chat?") + ); + qrResource.setItem(items); + qrResource.setSubject(encounter.getSubject()); + qrResource.setEncounter(new Reference(encounterEntry.getFullUrl())); + + return newEntry(bundle, qrResource, String.valueOf(UUID.randomUUID())); + + } + private static BundleEntryComponent consentByPerson(Person person, Bundle bundle, BundleEntryComponent personEntry, String type) { org.hl7.fhir.r4.model.Consent consent = new Consent(); @@ -571,7 +599,8 @@ private static BundleEntryComponent consentByPerson(Person person, Bundle bundle private static BundleEntryComponent consentByEncounter(Person person, Bundle bundle, BundleEntryComponent personEntry, Encounter encounter, - BundleEntryComponent encounterEntry) { + BundleEntryComponent encounterEntry, + BundleEntryComponent questionnaireResponseEntry) { org.hl7.fhir.r4.model.Consent consent = new Consent(); // convert participant @@ -602,6 +631,9 @@ private static BundleEntryComponent consentByEncounter(Person person, Bundle bun codingList.add(encounterCC); consent.setCategory(codingList); + // set source as questionnaireResponse + consent.setSource(new Reference(questionnaireResponseEntry.getFullUrl())); + // status set consent.setStatus(Consent.ConsentState.ACTIVE); From 6e3e4c4652d4c5d8555ceb156e358e5fb9d18ce0 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Tue, 26 Sep 2023 17:55:52 -0400 Subject: [PATCH 19/20] add comments and remv extra consent ref link --- src/main/java/org/mitre/synthea/export/FhirR4.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index 8f019ad043..26f2ee5a53 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -509,10 +509,13 @@ private static BundleEntryComponent questionnaireResponse(Bundle bundle, BundleE org.hl7.fhir.r4.model.QuestionnaireResponse qrResource = new QuestionnaireResponse(); org.hl7.fhir.r4.model.Encounter encounter = (org.hl7.fhir.r4.model.Encounter) encounterEntry.getResource(); + // add status qrResource.setStatus(QuestionnaireResponse.QuestionnaireResponseStatus.COMPLETED); + // connect to an encounter qrResource.setEncounter(new Reference(encounterEntry.getFullUrl())); + // add answers and text for the collected consent List items = new ArrayList<>(); List answers = new ArrayList<>(); answers.add( @@ -524,8 +527,9 @@ private static BundleEntryComponent questionnaireResponse(Bundle bundle, BundleE .setAnswer(answers).setLinkId("1.0").setText("Do u consent to this chat?") ); qrResource.setItem(items); + + // set subject (aka patient) qrResource.setSubject(encounter.getSubject()); - qrResource.setEncounter(new Reference(encounterEntry.getFullUrl())); return newEntry(bundle, qrResource, String.valueOf(UUID.randomUUID())); From fac181615249be0f3cd0f3bb011db3a4d851c5d4 Mon Sep 17 00:00:00 2001 From: Bibin Thomas Date: Fri, 13 Oct 2023 16:52:00 -0400 Subject: [PATCH 20/20] adding start and end times to appt resource --- src/main/java/org/mitre/synthea/export/FhirR4.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/org/mitre/synthea/export/FhirR4.java b/src/main/java/org/mitre/synthea/export/FhirR4.java index 26f2ee5a53..21430bac30 100644 --- a/src/main/java/org/mitre/synthea/export/FhirR4.java +++ b/src/main/java/org/mitre/synthea/export/FhirR4.java @@ -11,6 +11,7 @@ import java.awt.geom.Point2D; import java.io.IOException; import java.time.Instant; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; @@ -23,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; import org.apache.commons.codec.digest.DigestUtils; @@ -781,6 +783,13 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn } + //start and end + LocalDateTime start = LocalDateTime.now().minusHours((long) (Math.random() * (10))); + LocalDateTime end = start.plusHours(1); + + apptResource.setStart(java.sql.Timestamp.valueOf(start)); + apptResource.setEnd(java.sql.Timestamp.valueOf(end)); + apptResource.setParticipant(aPList); @@ -788,6 +797,8 @@ private static BundleEntryComponent encounterAppointment(Person person, BundleEn } + + /** * Convert the given Person into a JSON String, containing a FHIR Bundle of the Person and the * associated entries from their health record.