Search in sources :

Example 31 with Resource

use of org.hl7.fhir.r4.model.Resource in project beneficiary-fhir-data by CMSgov.

the class HHAClaimTransformerV2 method transformClaim.

/**
 * @param claimGroup the CCW {@link HHAClaim} to transform
 * @return a FHIR {@link ExplanationOfBenefit} resource that represents the specified {@link
 *     HHAClaim}
 */
private static ExplanationOfBenefit transformClaim(HHAClaim claimGroup) {
    ExplanationOfBenefit eob = new ExplanationOfBenefit();
    // Required values not directly mapped
    eob.getMeta().addProfile(ProfileConstants.C4BB_EOB_NONCLINICIAN_PROFILE_URL);
    // Common group level fields between all claim types
    // Claim Type + Claim ID    => ExplanationOfBenefit.id
    // CLM_ID                   => ExplanationOfBenefit.identifier
    // CLM_GRP_ID               => ExplanationOfBenefit.identifier
    // BENE_ID + Coverage Type  => ExplanationOfBenefit.insurance.coverage
    // BENE_ID                  => ExplanationOfBenefit.patient (reference)
    // FINAL_ACTION             => ExplanationOfBenefit.status
    // CLM_FROM_DT              => ExplanationOfBenefit.billablePeriod.start
    // CLM_THRU_DT              => ExplanationOfBenefit.billablePeriod.end
    // CLM_PMT_AMT              => ExplanationOfBenefit.payment.amount
    TransformerUtilsV2.mapEobCommonClaimHeaderData(eob, claimGroup.getClaimId(), claimGroup.getBeneficiaryId(), ClaimTypeV2.HHA, claimGroup.getClaimGroupId().toPlainString(), MedicareSegment.PART_B, Optional.of(claimGroup.getDateFrom()), Optional.of(claimGroup.getDateThrough()), Optional.of(claimGroup.getPaymentAmount()), claimGroup.getFinalAction());
    // NCH_WKLY_PROC_DT => ExplanationOfBenefit.supportinginfo.timingDate
    TransformerUtilsV2.addInformation(eob, TransformerUtilsV2.createInformationRecievedDateSlice(eob, CcwCodebookVariable.NCH_WKLY_PROC_DT, Optional.of(claimGroup.getWeeklyProcessDate())));
    // map eob type codes into FHIR
    // NCH_CLM_TYPE_CD            => ExplanationOfBenefit.type.coding
    // EOB Type                   => ExplanationOfBenefit.type.coding
    // Claim Type                 => ExplanationOfBenefit.type.coding
    // NCH_NEAR_LINE_REC_IDENT_CD => ExplanationOfBenefit.extension
    TransformerUtilsV2.mapEobType(eob, ClaimTypeV2.HHA, Optional.of(claimGroup.getNearLineRecordIdCode()), Optional.of(claimGroup.getClaimTypeCode()));
    // PRVDR_NUM => ExplanationOfBenefit.provider.identifier
    TransformerUtilsV2.addProviderSlice(eob, C4BBOrganizationIdentifierType.PRN, claimGroup.getProviderNumber(), claimGroup.getLastUpdated());
    // Common group level fields between Inpatient, Outpatient Hospice, HHA and SNF
    // ORG_NPI_NUM              => ExplanationOfBenefit.provider
    // CLM_FAC_TYPE_CD          => ExplanationOfBenefit.facility.extension
    // CLM_FREQ_CD              => ExplanationOfBenefit.supportingInfo
    // CLM_MDCR_NON_PMT_RSN_CD  => ExplanationOfBenefit.extension
    // PTNT_DSCHRG_STUS_CD      => ExplanationOfBenefit.supportingInfo
    // CLM_SRVC_CLSFCTN_TYPE_CD => ExplanationOfBenefit.extension
    // NCH_PRMRY_PYR_CD         => ExplanationOfBenefit.supportingInfo
    // CLM_TOT_CHRG_AMT         => ExplanationOfBenefit.total.amount
    // NCH_PRMRY_PYR_CLM_PD_AMT => ExplanationOfBenefit.benefitBalance.financial
    TransformerUtilsV2.mapEobCommonGroupInpOutHHAHospiceSNF(eob, claimGroup.getOrganizationNpi(), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), claimGroup.getPatientDischargeStatusCode(), claimGroup.getClaimServiceClassificationTypeCode(), claimGroup.getClaimPrimaryPayerCode(), claimGroup.getTotalChargeAmount(), claimGroup.getPrimaryPayerPaidAmount(), claimGroup.getFiscalIntermediaryNumber(), claimGroup.getLastUpdated());
    // CLM_PPS_IND_CODE => ExplanationOfBenefit.supportingInfo
    TransformerUtilsV2.addInformationWithCode(eob, CcwCodebookVariable.CLM_PPS_IND_CD, CcwCodebookVariable.CLM_PPS_IND_CD, claimGroup.getProspectivePaymentCode());
    // ICD_DGNS_E_VRSN_CD(1-12) => diagnosis.diagnosisCodeableConcept
    for (Diagnosis diagnosis : DiagnosisUtilV2.extractDiagnoses(claimGroup)) {
        DiagnosisUtilV2.addDiagnosisCode(eob, diagnosis, ClaimTypeV2.HHA);
    }
    // Map care team
    // AT_PHYSN_NPI     => ExplanationOfBenefit.careTeam.provider
    // AT_PHYSN_UPIN    => ExplanationOfBenefit.careTeam.provider
    TransformerUtilsV2.mapCareTeam(eob, claimGroup.getAttendingPhysicianNpi(), Optional.empty(), Optional.empty(), claimGroup.getAttendingPhysicianUpin(), Optional.empty(), Optional.empty());
    // CLM_HHA_LUPA_IND_CD => ExplanationOfBenefit.supportinginfo.code
    claimGroup.getClaimLUPACode().ifPresent(c -> TransformerUtilsV2.addInformationWithCode(eob, CcwCodebookVariable.CLM_HHA_LUPA_IND_CD, CcwCodebookVariable.CLM_HHA_LUPA_IND_CD, c));
    // CLM_HHA_RFRL_CD => ExplanationOfBenefit.supportinginfo.code
    claimGroup.getClaimReferralCode().ifPresent(c -> TransformerUtilsV2.addInformationWithCode(eob, CcwCodebookVariable.CLM_HHA_RFRL_CD, CcwCodebookVariable.CLM_HHA_RFRL_CD, c));
    // CLM_HHA_TOT_VISIT_CNT => ExplanationOfBenefit.supportinginfo.value[x]
    TransformerUtilsV2.addInformation(eob, CcwCodebookVariable.CLM_HHA_TOT_VISIT_CNT).setValue(new Quantity(claimGroup.getTotalVisitCount().intValue()));
    // CLM_ADMSN_DT => ExplanationOfBenefit.supportingInfo:admissionperiod
    TransformerUtilsV2.addInformation(eob, TransformerUtilsV2.createInformationAdmPeriodSlice(eob, claimGroup.getCareStartDate(), Optional.empty()));
    for (HHAClaimLine line : claimGroup.getLines()) {
        ItemComponent item = eob.addItem();
        // Override the default sequence
        // CLM_LINE_NUM => item.sequence
        item.setSequence(line.getLineNumber().intValue());
        // PRVDR_STATE_CD => item.location
        TransformerUtilsV2.addLocationState(item, claimGroup.getProviderStateCode());
        // HCPCS_CD           => ExplanationOfBenefit.item.productOrService
        // HCPCS_1ST_MDFR_CD  => ExplanationOfBenefit.item.modifier
        // HCPCS_2ND_MDFR_CD  => ExplanationOfBenefit.item.modifier
        TransformerUtilsV2.mapHcpcs(eob, item, line.getHcpcsCode(), Optional.empty(), Arrays.asList(line.getHcpcsInitialModifierCode(), line.getHcpcsSecondModifierCode()));
        // REV_CNTR_1ST_ANSI_CD => ExplanationOfBenefit.item.adjudication
        TransformerUtilsV2.addAdjudication(item, TransformerUtilsV2.createAdjudicationDenialReasonSlice(eob, CcwCodebookVariable.REV_CNTR_1ST_ANSI_CD, line.getRevCntr1stAnsiCd()));
        // REV_CNTR                   => ExplanationOfBenefit.item.revenue
        // REV_CNTR_RATE_AMT          => ExplanationOfBenefit.item.adjudication
        // REV_CNTR_TOT_CHRG_AMT      => ExplanationOfBenefit.item.adjudication
        // REV_CNTR_NCVRD_CHRG_AMT    => ExplanationOfBenefit.item.adjudication
        // REV_CNTR_NDC_QTY           => ExplanationOfBenefit.item.quantity
        // REV_CNTR_NDC_QTY_QLFR_CD   => ExplanationOfBenefit.modifier
        TransformerUtilsV2.mapEobCommonItemRevenue(item, eob, line.getRevenueCenterCode(), line.getRateAmount(), line.getTotalChargeAmount(), Optional.of(line.getNonCoveredChargeAmount()), line.getNationalDrugCodeQuantity(), line.getNationalDrugCodeQualifierCode());
        // Common item level fields between Outpatient, HHA and Hospice
        // REV_CNTR_DT              => ExplanationOfBenefit.item.servicedDate
        // REV_CNTR_PMT_AMT_AMT     => ExplanationOfBenefit.item.adjudication
        TransformerUtilsV2.mapEobCommonItemRevenueOutHHAHospice(item, line.getRevenueCenterDate(), line.getPaymentAmount());
        // REV_CNTR_DDCTBL_COINSRNC_CD => item.revenue
        TransformerUtilsV2.addItemRevenue(item, eob, CcwCodebookVariable.REV_CNTR_DDCTBL_COINSRNC_CD, line.getDeductibleCoinsuranceCd());
        // RNDRNG_PHYSN_UPIN => ExplanationOfBenefit.careTeam.provider
        TransformerUtilsV2.addCareTeamMember(eob, item, C4BBPractitionerIdentifierType.UPIN, C4BBClaimProfessionalAndNonClinicianCareTeamRole.PERFORMING, line.getRevenueCenterRenderingPhysicianUPIN());
        // RNDRNG_PHYSN_NPI => ExplanationOfBenefit.careTeam.provider
        TransformerUtilsV2.addCareTeamMember(eob, item, C4BBPractitionerIdentifierType.NPI, C4BBClaimProfessionalAndNonClinicianCareTeamRole.PERFORMING, line.getRevenueCenterRenderingPhysicianNPI());
        // REV_CNTR_STUS_IND_CD => ExplanationOfBenefit.item.revenue.extension
        TransformerUtilsV2.mapEobCommonItemRevenueStatusCode(item, eob, line.getStatusCode());
    }
    TransformerUtilsV2.setLastUpdated(eob, claimGroup.getLastUpdated());
    return eob;
}
Also used : ItemComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.ItemComponent) Quantity(org.hl7.fhir.r4.model.Quantity) Diagnosis(gov.cms.bfd.server.war.commons.Diagnosis) ExplanationOfBenefit(org.hl7.fhir.r4.model.ExplanationOfBenefit) HHAClaimLine(gov.cms.bfd.model.rif.HHAClaimLine)

Example 32 with Resource

use of org.hl7.fhir.r4.model.Resource in project beneficiary-fhir-data by CMSgov.

the class TransformerUtilsV2 method addProviderSlice.

/**
 * Looks up or adds a contained {@link Organization} object to the current {@link
 * ExplanationOfBenefit}. This is used to store Identifier slices related to the Provider
 * organization.
 *
 * @param eob The {@link ExplanationOfBenefit} to provider org details to
 * @param type The {@link C4BBIdentifierType} of the identifier slice
 * @param value The value of the identifier. If empty, this call is a no-op
 */
static void addProviderSlice(ExplanationOfBenefit eob, C4BBOrganizationIdentifierType type, Optional<String> value, Optional<Instant> lastUpdated) {
    if (value.isPresent()) {
        Resource providerResource = findOrCreateContainedOrg(eob, PROVIDER_ORG_ID);
        // We are assuming that the contained resource with an id of "provider-org" is an Organization
        if (!Organization.class.isInstance(providerResource)) {
            throw new BadCodeMonkeyException();
        }
        Organization provider = (Organization) providerResource;
        // Add the new Identifier to the Organization
        Identifier id = new Identifier().setType(createCodeableConcept(type.getSystem(), type.toCode())).setValue(value.get());
        // Certain types have specific systems
        if (type == C4BBOrganizationIdentifierType.NPI) {
            id.setSystem(TransformerConstants.CODING_NPI_US);
        }
        provider.addIdentifier(id);
        // Set active to value of true
        provider.setActive(true);
        setLastUpdated(provider, lastUpdated);
        // This gets updated for every call, but always set to the same value
        eob.getProvider().setReference(PROVIDER_ORG_REFERENCE);
    }
}
Also used : Organization(org.hl7.fhir.r4.model.Organization) Identifier(org.hl7.fhir.r4.model.Identifier) CurrencyIdentifier(gov.cms.bfd.server.war.r4.providers.BeneficiaryTransformerV2.CurrencyIdentifier) BadCodeMonkeyException(gov.cms.bfd.sharedutils.exceptions.BadCodeMonkeyException) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource) IAnyResource(org.hl7.fhir.instance.model.api.IAnyResource) Resource(org.hl7.fhir.r4.model.Resource)

Example 33 with Resource

use of org.hl7.fhir.r4.model.Resource in project beneficiary-fhir-data by CMSgov.

the class TransformerUtilsV2 method findOrCreateContainedObservation.

static Observation findOrCreateContainedObservation(ExplanationOfBenefit eob, String id) {
    Optional<Resource> observation = eob.getContained().stream().filter(r -> r.getId() == id).findFirst();
    // If it isn't there, add one
    if (!observation.isPresent()) {
        observation = Optional.of(new Observation().setId(id));
        eob.getContained().add(observation.get());
    }
    // At this point `observation.get()` will always return
    if (!Observation.class.isInstance(observation.get())) {
        throw new BadCodeMonkeyException();
    }
    return (Observation) observation.get();
}
Also used : Arrays(java.util.Arrays) CcwCodebookInterface(gov.cms.bfd.model.codebook.model.CcwCodebookInterface) SimpleQuantity(org.hl7.fhir.r4.model.SimpleQuantity) Constants(ca.uhn.fhir.rest.api.Constants) Identifier(org.hl7.fhir.r4.model.Identifier) Reference(org.hl7.fhir.r4.model.Reference) StringUtils(org.apache.commons.lang3.StringUtils) BigDecimal(java.math.BigDecimal) ItemComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.ItemComponent) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource) SupportingInformationComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.SupportingInformationComponent) Map(java.util.Map) CcwCodebookMissingVariable(gov.cms.bfd.model.codebook.data.CcwCodebookMissingVariable) TemporalPrecisionEnum(ca.uhn.fhir.model.api.TemporalPrecisionEnum) Value(gov.cms.bfd.model.codebook.model.Value) Coverage(org.hl7.fhir.r4.model.Coverage) IdDt(ca.uhn.fhir.model.primitive.IdDt) ReflectionUtils(gov.cms.bfd.server.war.commons.ReflectionUtils) MedicareSegment(gov.cms.bfd.server.war.commons.MedicareSegment) BenefitBalanceComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.BenefitBalanceComponent) Period(org.hl7.fhir.r4.model.Period) Set(java.util.Set) StandardCharsets(java.nio.charset.StandardCharsets) ZoneId(java.time.ZoneId) UncheckedIOException(java.io.UncheckedIOException) Coding(org.hl7.fhir.r4.model.Coding) CarrierClaim(gov.cms.bfd.model.rif.CarrierClaim) RaceCategory(gov.cms.bfd.server.war.commons.RaceCategory) ExplanationOfBenefitStatus(org.hl7.fhir.r4.model.ExplanationOfBenefit.ExplanationOfBenefitStatus) Use(org.hl7.fhir.r4.model.ExplanationOfBenefit.Use) C4BBClaimIdentifierType(gov.cms.bfd.server.war.commons.carin.C4BBClaimIdentifierType) IAnyResource(org.hl7.fhir.instance.model.api.IAnyResource) Money(org.hl7.fhir.r4.model.Money) Strings(com.google.common.base.Strings) CCWUtils(gov.cms.bfd.server.war.commons.CCWUtils) RequestDetails(ca.uhn.fhir.rest.api.server.RequestDetails) CcwCodebookVariable(gov.cms.bfd.model.codebook.data.CcwCodebookVariable) UnsignedIntType(org.hl7.fhir.r4.model.UnsignedIntType) CCWProcedure(gov.cms.bfd.server.war.commons.CCWProcedure) Quantity(org.hl7.fhir.r4.model.Quantity) CareTeamComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.CareTeamComponent) OffsetLinkBuilder(gov.cms.bfd.server.war.commons.OffsetLinkBuilder) LinkBuilder(gov.cms.bfd.server.war.commons.LinkBuilder) BadCodeMonkeyException(gov.cms.bfd.sharedutils.exceptions.BadCodeMonkeyException) IOException(java.io.IOException) C4BBClaimProfessionalAndNonClinicianCareTeamRole(gov.cms.bfd.server.war.commons.carin.C4BBClaimProfessionalAndNonClinicianCareTeamRole) InputStreamReader(java.io.InputStreamReader) FDADrugDataUtilityApp(gov.cms.bfd.server.war.FDADrugDataUtilityApp) AdjudicationComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.AdjudicationComponent) ExplanationOfBenefit(org.hl7.fhir.r4.model.ExplanationOfBenefit) MDC(org.slf4j.MDC) Bundle(org.hl7.fhir.r4.model.Bundle) BufferedReader(java.io.BufferedReader) TotalComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.TotalComponent) Date(java.util.Date) LoggerFactory(org.slf4j.LoggerFactory) BenefitComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.BenefitComponent) ProcedureComponent(org.hl7.fhir.r4.model.ExplanationOfBenefit.ProcedureComponent) BundleEntryComponent(org.hl7.fhir.r4.model.Bundle.BundleEntryComponent) C4BBAdjudicationDiscriminator(gov.cms.bfd.server.war.commons.carin.C4BBAdjudicationDiscriminator) Patient(org.hl7.fhir.r4.model.Patient) DateType(org.hl7.fhir.r4.model.DateType) Collection(java.util.Collection) Resource(org.hl7.fhir.r4.model.Resource) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) Beneficiary(gov.cms.bfd.model.rif.Beneficiary) List(java.util.List) TransformerConstants(gov.cms.bfd.server.war.commons.TransformerConstants) C4BBOrganizationIdentifierType(gov.cms.bfd.server.war.commons.carin.C4BBOrganizationIdentifierType) LocalDate(java.time.LocalDate) Optional(java.util.Optional) Extension(org.hl7.fhir.r4.model.Extension) PositiveIntType(org.hl7.fhir.r4.model.PositiveIntType) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ClaimCareteamrole(org.hl7.fhir.r4.model.codesystems.ClaimCareteamrole) DataFormatException(ca.uhn.fhir.parser.DataFormatException) CodeableConcept(org.hl7.fhir.r4.model.CodeableConcept) ProfileConstants(gov.cms.bfd.server.war.commons.ProfileConstants) HashMap(java.util.HashMap) ExBenefitcategory(org.hl7.fhir.r4.model.codesystems.ExBenefitcategory) HashSet(java.util.HashSet) C4BBClaimPharmacyTeamRole(gov.cms.bfd.server.war.commons.carin.C4BBClaimPharmacyTeamRole) C4BBIdentifierType(gov.cms.bfd.server.war.commons.carin.C4BBIdentifierType) Address(org.hl7.fhir.r4.model.Address) InvalidRifValueException(gov.cms.bfd.model.rif.parse.InvalidRifValueException) NoSuchElementException(java.util.NoSuchElementException) Nonnull(javax.annotation.Nonnull) C4BBAdjudication(gov.cms.bfd.server.war.commons.carin.C4BBAdjudication) Observation(org.hl7.fhir.r4.model.Observation) ObservationStatus(org.hl7.fhir.r4.model.Observation.ObservationStatus) C4BBPractitionerIdentifierType(gov.cms.bfd.server.war.commons.carin.C4BBPractitionerIdentifierType) C4BBSupportingInfoType(gov.cms.bfd.server.war.commons.carin.C4BBSupportingInfoType) Logger(org.slf4j.Logger) C4BBClaimInstitutionalCareTeamRole(gov.cms.bfd.server.war.commons.carin.C4BBClaimInstitutionalCareTeamRole) Organization(org.hl7.fhir.r4.model.Organization) ResourceType(org.hl7.fhir.r4.model.ResourceType) CurrencyIdentifier(gov.cms.bfd.server.war.r4.providers.BeneficiaryTransformerV2.CurrencyIdentifier) URLEncoder(java.net.URLEncoder) RemittanceOutcome(org.hl7.fhir.r4.model.ExplanationOfBenefit.RemittanceOutcome) InputStream(java.io.InputStream) Assert(org.springframework.util.Assert) BadCodeMonkeyException(gov.cms.bfd.sharedutils.exceptions.BadCodeMonkeyException) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource) IAnyResource(org.hl7.fhir.instance.model.api.IAnyResource) Resource(org.hl7.fhir.r4.model.Resource) Observation(org.hl7.fhir.r4.model.Observation)

Example 34 with Resource

use of org.hl7.fhir.r4.model.Resource in project beneficiary-fhir-data by CMSgov.

the class TransformerUtilsV2 method addResourcesToBundle.

/**
 * @param bundle a {@link Bundle} to add the list of {@link ExplanationOfBenefit} resources to.
 * @param resources a list of either {@link ExplanationOfBenefit}s, {@link Coverage}s, or {@link
 *     Patient}s, of which a portion will be added to the bundle based on the paging values
 * @return Returns a {@link Bundle} of {@link ExplanationOfBenefit}s, {@link Coverage}s, or {@link
 *     Patient}s, which may contain multiple matching resources, or may also be empty.
 */
public static Bundle addResourcesToBundle(Bundle bundle, List<IBaseResource> resources) {
    Set<String> beneIds = new HashSet<String>();
    for (IBaseResource res : resources) {
        BundleEntryComponent entry = bundle.addEntry();
        entry.setResource((Resource) res);
        if (entry.getResource().getResourceType() == ResourceType.ExplanationOfBenefit) {
            ExplanationOfBenefit eob = ((ExplanationOfBenefit) entry.getResource());
            if (eob != null && eob.getPatient() != null && !Strings.isNullOrEmpty(eob.getPatient().getReference())) {
                String reference = eob.getPatient().getReference().replace("Patient/", "");
                if (!Strings.isNullOrEmpty(reference)) {
                    beneIds.add(reference);
                }
            }
        } else if (entry.getResource().getResourceType() == ResourceType.Patient) {
            Patient patient = ((Patient) entry.getResource());
            if (patient != null && !Strings.isNullOrEmpty(patient.getId())) {
                beneIds.add(patient.getId());
            }
        } else if (entry.getResource().getResourceType() == ResourceType.Coverage) {
            Coverage coverage = ((Coverage) entry.getResource());
            if (coverage != null && coverage.getBeneficiary() != null && !Strings.isNullOrEmpty(coverage.getBeneficiary().getReference())) {
                String reference = coverage.getBeneficiary().getReference().replace("Patient/", "");
                if (!Strings.isNullOrEmpty(reference)) {
                    beneIds.add(reference);
                }
            }
        }
    }
    logBeneIdToMdc(beneIds);
    return bundle;
}
Also used : BundleEntryComponent(org.hl7.fhir.r4.model.Bundle.BundleEntryComponent) Patient(org.hl7.fhir.r4.model.Patient) Coverage(org.hl7.fhir.r4.model.Coverage) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource) ExplanationOfBenefit(org.hl7.fhir.r4.model.ExplanationOfBenefit) HashSet(java.util.HashSet)

Example 35 with Resource

use of org.hl7.fhir.r4.model.Resource in project beneficiary-fhir-data by CMSgov.

the class BeneficiaryTransformerV2 method transform.

/**
 * @param beneficiary the CCW {@link Beneficiary} to transform
 * @param requestHeader {@link RequestHeaders} the holder that contains all supported resource
 *     request headers
 * @return a FHIR {@link Patient} resource that represents the specified {@link Beneficiary}
 */
private static Patient transform(Beneficiary beneficiary, RequestHeaders requestHeader) {
    Objects.requireNonNull(beneficiary);
    Patient patient = new Patient();
    /*
     * Notify end users when they receive Patient records impacted by
     * https://jira.cms.gov/browse/BFD-1566. See the documentation on
     * LoadAppOptions.isFilteringNonNullAndNon2022Benes() for details.
     */
    if (!beneficiary.getSkippedRifRecords().isEmpty()) {
        patient.getMeta().addTag(TransformerConstants.CODING_SYSTEM_BFD_TAGS, TransformerConstants.CODING_BFD_TAGS_DELAYED_BACKDATED_ENROLLMENT, TransformerConstants.CODING_BFD_TAGS_DELAYED_BACKDATED_ENROLLMENT_DISPLAY);
    }
    // Required values not directly mapped
    patient.getMeta().addProfile(ProfileConstants.C4BB_PATIENT_URL);
    patient.setId(beneficiary.getBeneficiaryId());
    // BENE_ID => patient.identifier
    TransformerUtilsV2.addIdentifierSlice(patient, TransformerUtilsV2.createCodeableConcept(TransformerConstants.CODING_SYSTEM_HL7_IDENTIFIER_TYPE, null, TransformerConstants.PATIENT_MB_ID_DISPLAY, "MB"), Optional.of(beneficiary.getBeneficiaryId()), Optional.of(TransformerConstants.CODING_BBAPI_BENE_ID));
    // Unhashed MBI
    if (beneficiary.getMedicareBeneficiaryId().isPresent()) {
        Period mbiPeriod = new Period();
        if (beneficiary.getMbiEffectiveDate().isPresent()) {
            TransformerUtilsV2.setPeriodStart(mbiPeriod, beneficiary.getMbiEffectiveDate().get());
        }
        if (beneficiary.getMbiObsoleteDate().isPresent()) {
            TransformerUtilsV2.setPeriodEnd(mbiPeriod, beneficiary.getMbiObsoleteDate().get());
        }
        addUnhashedIdentifier(patient, beneficiary.getMedicareBeneficiaryId().get(), TransformerConstants.CODING_BBAPI_MEDICARE_BENEFICIARY_ID_UNHASHED, TransformerUtilsV2.createIdentifierCurrencyExtension(CurrencyIdentifier.CURRENT), mbiPeriod);
    }
    // Add lastUpdated
    TransformerUtilsV2.setLastUpdated(patient, beneficiary.getLastUpdated());
    /**
     * The following logic attempts to distill {@link MedicareBeneficiaryIdHistory} data into only
     * those records which have an endDate present. This is due to the fact that it includes the
     * CURRENT MBI record which was handle previously. Also, the {@link
     * MedicareBeneficiaryIdHistory} table appears to contain spurious records with the only
     * difference is the generated surrogate key identifier.
     */
    if (requestHeader.isMBIinIncludeIdentifiers()) {
        HashMap<LocalDate, MedicareBeneficiaryIdHistory> mbiHistMap = new HashMap<LocalDate, MedicareBeneficiaryIdHistory>();
        for (MedicareBeneficiaryIdHistory mbiHistory : beneficiary.getMedicareBeneficiaryIdHistories()) {
            // and will have been previously provided as the CURRENT rcd.
            if (mbiHistory.getMbiEndDate().isPresent()) {
                mbiHistMap.put(mbiHistory.getMbiEndDate().get(), mbiHistory);
            }
            // would come in ascending order, so any rcd would have a later
            // update date than prev rcd.
            TransformerUtilsV2.updateMaxLastUpdated(patient, mbiHistory.getLastUpdated());
        }
        if (mbiHistMap.size() > 0) {
            Extension historicalIdentifier = TransformerUtilsV2.createIdentifierCurrencyExtension(CurrencyIdentifier.HISTORIC);
            for (MedicareBeneficiaryIdHistory mbi : mbiHistMap.values()) {
                addUnhashedIdentifier(patient, mbi.getMedicareBeneficiaryId().get(), TransformerConstants.CODING_BBAPI_MEDICARE_BENEFICIARY_ID_UNHASHED, historicalIdentifier, null);
            }
        }
    }
    // support header includeAddressFields from downstream components e.g. BB2
    // per requirement of BFD-379, BB2 always send header includeAddressFields = False
    Boolean addrHdrVal = requestHeader.getValue(R4PatientResourceProvider.HEADER_NAME_INCLUDE_ADDRESS_FIELDS);
    if (addrHdrVal != null && addrHdrVal) {
        patient.addAddress().setState(beneficiary.getStateCode()).setPostalCode(beneficiary.getPostalCode()).setCity(beneficiary.getDerivedCityName().orElse(null)).addLine(beneficiary.getDerivedMailingAddress1().orElse(null)).addLine(beneficiary.getDerivedMailingAddress2().orElse(null)).addLine(beneficiary.getDerivedMailingAddress3().orElse(null)).addLine(beneficiary.getDerivedMailingAddress4().orElse(null)).addLine(beneficiary.getDerivedMailingAddress5().orElse(null)).addLine(beneficiary.getDerivedMailingAddress6().orElse(null));
    } else {
        patient.addAddress().setState(beneficiary.getStateCode()).setPostalCode(beneficiary.getPostalCode());
    }
    if (beneficiary.getBirthDate() != null) {
        patient.setBirthDate(TransformerUtilsV2.convertToDate(beneficiary.getBirthDate()));
    }
    // "Patient.deceased[x]": ["boolean", "dateTime"],
    if (beneficiary.getBeneficiaryDateOfDeath().isPresent()) {
        patient.setDeceased(new DateTimeType(TransformerUtilsV2.convertToDate(beneficiary.getBeneficiaryDateOfDeath().get()), TemporalPrecisionEnum.DAY));
    } else {
        patient.setDeceased(new BooleanType(false));
    }
    char sex = beneficiary.getSex();
    if (sex == Sex.MALE.getCode())
        patient.setGender((AdministrativeGender.MALE));
    else if (sex == Sex.FEMALE.getCode())
        patient.setGender((AdministrativeGender.FEMALE));
    else
        patient.setGender((AdministrativeGender.UNKNOWN));
    if (beneficiary.getRace().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.RACE, beneficiary.getRace().get()));
        // for race category, v2 will just treat all race codes as Unknown (UNK);
        // thus we'll simply pass in the Unknown race code .
        RaceCategory raceCategory = TransformerUtilsV2.getRaceCategory('0');
        Extension raceChildOMBExt1 = new Extension().setValue(new Coding().setCode(raceCategory.toCode()).setSystem(raceCategory.getSystem()).setDisplay(raceCategory.getDisplay())).setUrl("ombCategory");
        Extension raceChildOMBExt2 = new Extension().setValue(new StringType().setValue(raceCategory.getDisplay())).setUrl("text");
        Extension parentOMBRace = new Extension().setUrl(TransformerConstants.CODING_RACE_US);
        parentOMBRace.addExtension(raceChildOMBExt1);
        parentOMBRace.addExtension(raceChildOMBExt2);
        patient.addExtension(parentOMBRace);
    }
    HumanName name = patient.addName().addGiven(beneficiary.getNameGiven()).setFamily(beneficiary.getNameSurname()).setUse(HumanName.NameUse.USUAL);
    if (beneficiary.getNameMiddleInitial().isPresent()) {
        name.addGiven(String.valueOf(beneficiary.getNameMiddleInitial().get()));
    }
    // The reference year of the enrollment data
    if (beneficiary.getBeneEnrollmentReferenceYear().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionDate(CcwCodebookVariable.RFRNC_YR, beneficiary.getBeneEnrollmentReferenceYear()));
    }
    // Monthly Medicare-Medicaid dual eligibility codes
    if (beneficiary.getMedicaidDualEligibilityJanCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_01, beneficiary.getMedicaidDualEligibilityJanCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityFebCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_02, beneficiary.getMedicaidDualEligibilityFebCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityMarCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_03, beneficiary.getMedicaidDualEligibilityMarCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityAprCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_04, beneficiary.getMedicaidDualEligibilityAprCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityMayCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_05, beneficiary.getMedicaidDualEligibilityMayCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityJunCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_06, beneficiary.getMedicaidDualEligibilityJunCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityJulCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_07, beneficiary.getMedicaidDualEligibilityJulCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityAugCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_08, beneficiary.getMedicaidDualEligibilityAugCode()));
    }
    if (beneficiary.getMedicaidDualEligibilitySeptCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_09, beneficiary.getMedicaidDualEligibilitySeptCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityOctCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_10, beneficiary.getMedicaidDualEligibilityOctCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityNovCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_11, beneficiary.getMedicaidDualEligibilityNovCode()));
    }
    if (beneficiary.getMedicaidDualEligibilityDecCode().isPresent()) {
        patient.addExtension(TransformerUtilsV2.createExtensionCoding(patient, CcwCodebookVariable.DUAL_12, beneficiary.getMedicaidDualEligibilityDecCode()));
    }
    // Last Updated => Patient.meta.lastUpdated
    TransformerUtilsV2.setLastUpdated(patient, beneficiary.getLastUpdated());
    return patient;
}
Also used : HashMap(java.util.HashMap) StringType(org.hl7.fhir.r4.model.StringType) BooleanType(org.hl7.fhir.r4.model.BooleanType) Patient(org.hl7.fhir.r4.model.Patient) Period(org.hl7.fhir.r4.model.Period) MedicareBeneficiaryIdHistory(gov.cms.bfd.model.rif.MedicareBeneficiaryIdHistory) LocalDate(java.time.LocalDate) Extension(org.hl7.fhir.r4.model.Extension) HumanName(org.hl7.fhir.r4.model.HumanName) DateTimeType(org.hl7.fhir.r4.model.DateTimeType) Coding(org.hl7.fhir.r4.model.Coding) RaceCategory(gov.cms.bfd.server.war.commons.RaceCategory)

Aggregations

ArrayList (java.util.ArrayList)319 Resource (org.hl7.fhir.r4.model.Resource)312 Test (org.junit.jupiter.api.Test)297 IBaseResource (org.hl7.fhir.instance.model.api.IBaseResource)270 BundleEntryComponent (org.hl7.fhir.r4.model.Bundle.BundleEntryComponent)230 FHIRException (org.hl7.fhir.exceptions.FHIRException)201 Test (org.junit.Test)190 IOException (java.io.IOException)181 Bundle (org.hl7.fhir.r4.model.Bundle)169 Date (java.util.Date)147 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)139 List (java.util.List)133 HashMap (java.util.HashMap)131 Patient (org.hl7.fhir.r4.model.Patient)118 FileOutputStream (java.io.FileOutputStream)110 Reference (org.hl7.fhir.r4.model.Reference)109 IGenericClient (ca.uhn.fhir.rest.client.api.IGenericClient)102 File (java.io.File)100 Collectors (java.util.stream.Collectors)95 XhtmlNode (org.hl7.fhir.utilities.xhtml.XhtmlNode)92