Search in sources :

Example 1 with Claim

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

the class TransformerUtils method mapEobCommonGroupCarrierDME.

/**
 * Transforms the common group level data elements between the {@link CarrierClaim} and {@link
 * DMEClaim} claim types to FHIR. The method parameter fields from {@link CarrierClaim} and {@link
 * DMEClaim} are listed below and their corresponding RIF CCW fields (denoted in all CAPS below
 * from {@link CarrierClaimColumn} and {@link DMEClaimColumn}).
 *
 * @param eob the {@link ExplanationOfBenefit} to modify
 * @param benficiaryId BEME_ID, *
 * @param carrierNumber CARR_NUM,
 * @param clinicalTrialNumber CLM_CLNCL_TRIL_NUM,
 * @param beneficiaryPartBDeductAmount CARR_CLM_CASH_DDCTBL_APLD_AMT,
 * @param paymentDenialCode CARR_CLM_PMT_DNL_CD,
 * @param referringPhysicianNpi RFR_PHYSN_NPI
 * @param providerAssignmentIndicator CARR_CLM_PRVDR_ASGNMT_IND_SW,
 * @param providerPaymentAmount NCH_CLM_PRVDR_PMT_AMT,
 * @param beneficiaryPaymentAmount NCH_CLM_BENE_PMT_AMT,
 * @param submittedChargeAmount NCH_CARR_CLM_SBMTD_CHRG_AMT,
 * @param allowedChargeAmount NCH_CARR_CLM_ALOWD_AMT,
 */
static void mapEobCommonGroupCarrierDME(ExplanationOfBenefit eob, String beneficiaryId, String carrierNumber, Optional<String> clinicalTrialNumber, BigDecimal beneficiaryPartBDeductAmount, String paymentDenialCode, Optional<String> referringPhysicianNpi, Optional<Character> providerAssignmentIndicator, BigDecimal providerPaymentAmount, BigDecimal beneficiaryPaymentAmount, BigDecimal submittedChargeAmount, BigDecimal allowedChargeAmount, String claimDispositionCode, Optional<String> claimCarrierControlNumber) {
    eob.addExtension(createExtensionIdentifier(CcwCodebookVariable.CARR_NUM, carrierNumber));
    // Carrier Claim Control Number
    if (claimCarrierControlNumber.isPresent()) {
        eob.addExtension(createExtensionIdentifier(CcwCodebookMissingVariable.CARR_CLM_CNTL_NUM, claimCarrierControlNumber.get()));
    }
    eob.addExtension(createExtensionCoding(eob, CcwCodebookVariable.CARR_CLM_PMT_DNL_CD, paymentDenialCode));
    // Claim Disposition Code
    eob.setDisposition(claimDispositionCode);
    /*
     * Referrals are represented as contained resources, since they share the lifecycle and identity
     * of their containing EOB.
     */
    if (referringPhysicianNpi.isPresent()) {
        ReferralRequest referral = new ReferralRequest();
        referral.setStatus(ReferralRequestStatus.COMPLETED);
        referral.setSubject(referencePatient(beneficiaryId));
        referral.setRequester(new ReferralRequestRequesterComponent(referencePractitioner(referringPhysicianNpi.get())));
        referral.addRecipient(referencePractitioner(referringPhysicianNpi.get()));
        // Set the ReferralRequest as a contained resource in the EOB:
        eob.setReferral(new Reference(referral));
    }
    if (providerAssignmentIndicator.isPresent()) {
        eob.addExtension(createExtensionCoding(eob, CcwCodebookVariable.ASGMNTCD, providerAssignmentIndicator));
    }
    if (clinicalTrialNumber.isPresent()) {
        eob.addExtension(createExtensionIdentifier(CcwCodebookVariable.CLM_CLNCL_TRIL_NUM, clinicalTrialNumber));
    }
    addAdjudicationTotal(eob, CcwCodebookVariable.CARR_CLM_CASH_DDCTBL_APLD_AMT, beneficiaryPartBDeductAmount);
    addAdjudicationTotal(eob, CcwCodebookVariable.NCH_CLM_PRVDR_PMT_AMT, providerPaymentAmount);
    addAdjudicationTotal(eob, CcwCodebookVariable.NCH_CLM_BENE_PMT_AMT, beneficiaryPaymentAmount);
    addAdjudicationTotal(eob, CcwCodebookVariable.NCH_CARR_CLM_SBMTD_CHRG_AMT, submittedChargeAmount);
    addAdjudicationTotal(eob, CcwCodebookVariable.NCH_CARR_CLM_ALOWD_AMT, allowedChargeAmount);
}
Also used : ReferralRequest(org.hl7.fhir.dstu3.model.ReferralRequest) ReferralRequestRequesterComponent(org.hl7.fhir.dstu3.model.ReferralRequest.ReferralRequestRequesterComponent) Reference(org.hl7.fhir.dstu3.model.Reference)

Example 2 with Claim

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

the class ExplanationOfBenefitResourceProvider method findByPatient.

/**
 * Adds support for the FHIR "search" operation for {@link ExplanationOfBenefit}s, allowing users
 * to search by {@link ExplanationOfBenefit#getPatient()}.
 *
 * <p>The {@link Search} annotation indicates that this method supports the search operation.
 * There may be many different methods annotated with this {@link Search} annotation, to support
 * many different search criteria.
 *
 * @param patient a {@link ReferenceParam} for the {@link ExplanationOfBenefit#getPatient()} to
 *     try and find matches for {@link ExplanationOfBenefit}s
 * @param type a list of {@link ClaimType} to include in the result. Defaults to all types.
 * @param startIndex an {@link OptionalParam} for the startIndex (or offset) used to determine
 *     pagination
 * @param excludeSamhsa an {@link OptionalParam} that, if <code>"true"</code>, will use {@link
 *     Stu3EobSamhsaMatcher} to filter out all SAMHSA-related claims from the results
 * @param lastUpdated an {@link OptionalParam} that specifies a date range for the lastUpdated
 *     field.
 * @param serviceDate an {@link OptionalParam} that specifies a date range for {@link
 *     ExplanationOfBenefit}s that completed
 * @param requestDetails a {@link RequestDetails} containing the details of the request URL, used
 *     to parse out pagination values
 * @return Returns a {@link Bundle} of {@link ExplanationOfBenefit}s, which may contain multiple
 *     matching resources, or may also be empty.
 */
@Search
@Trace
public Bundle findByPatient(@RequiredParam(name = ExplanationOfBenefit.SP_PATIENT) @Description(shortDefinition = "The patient identifier to search for") ReferenceParam patient, @OptionalParam(name = "type") @Description(shortDefinition = "A list of claim types to include") TokenAndListParam type, @OptionalParam(name = "startIndex") @Description(shortDefinition = "The offset used for result pagination") String startIndex, @OptionalParam(name = "excludeSAMHSA") @Description(shortDefinition = "If true, exclude all SAMHSA-related resources") String excludeSamhsa, @OptionalParam(name = "_lastUpdated") @Description(shortDefinition = "Include resources last updated in the given range") DateRangeParam lastUpdated, @OptionalParam(name = "service-date") @Description(shortDefinition = "Include resources that completed in the given range") DateRangeParam serviceDate, RequestDetails requestDetails) {
    /*
     * startIndex is an optional parameter here because it must be declared in the
     * event it is passed in. However, it is not being used here because it is also
     * contained within requestDetails and parsed out along with other parameters
     * later.
     */
    String beneficiaryId = patient.getIdPart();
    Set<ClaimType> claimTypes = parseTypeParam(type);
    Boolean includeTaxNumbers = returnIncludeTaxNumbers(requestDetails);
    OffsetLinkBuilder paging = new OffsetLinkBuilder(requestDetails, "/ExplanationOfBenefit?");
    Operation operation = new Operation(Operation.Endpoint.V1_EOB);
    operation.setOption("by", "patient");
    operation.setOption("types", (claimTypes.size() == ClaimType.values().length) ? "*" : claimTypes.stream().sorted(Comparator.comparing(ClaimType::name)).collect(Collectors.toList()).toString());
    operation.setOption("IncludeTaxNumbers", "" + includeTaxNumbers);
    operation.setOption("pageSize", paging.isPagingRequested() ? "" + paging.getPageSize() : "*");
    operation.setOption("_lastUpdated", Boolean.toString(lastUpdated != null && !lastUpdated.isEmpty()));
    operation.setOption("service-date", Boolean.toString(serviceDate != null && !serviceDate.isEmpty()));
    operation.publishOperationName();
    List<IBaseResource> eobs = new ArrayList<IBaseResource>();
    // Optimize when the lastUpdated parameter is specified and result set is empty
    if (loadedFilterManager.isResultSetEmpty(beneficiaryId, lastUpdated)) {
        return TransformerUtils.createBundle(paging, eobs, loadedFilterManager.getTransactionTime());
    }
    /*
     * The way our JPA/SQL schema is setup, we have to run a separate search for
     * each claim type, then combine the results. It's not super efficient, but it's
     * also not so inefficient that it's worth fixing.
     */
    if (claimTypes.contains(ClaimType.CARRIER))
        eobs.addAll(transformToEobs(ClaimType.CARRIER, findClaimTypeByPatient(ClaimType.CARRIER, beneficiaryId, lastUpdated, serviceDate), Optional.of(includeTaxNumbers)));
    if (claimTypes.contains(ClaimType.DME))
        eobs.addAll(transformToEobs(ClaimType.DME, findClaimTypeByPatient(ClaimType.DME, beneficiaryId, lastUpdated, serviceDate), Optional.of(includeTaxNumbers)));
    if (claimTypes.contains(ClaimType.HHA))
        eobs.addAll(transformToEobs(ClaimType.HHA, findClaimTypeByPatient(ClaimType.HHA, beneficiaryId, lastUpdated, serviceDate), Optional.of(includeTaxNumbers)));
    if (claimTypes.contains(ClaimType.HOSPICE))
        eobs.addAll(transformToEobs(ClaimType.HOSPICE, findClaimTypeByPatient(ClaimType.HOSPICE, beneficiaryId, lastUpdated, serviceDate), Optional.of(includeTaxNumbers)));
    if (claimTypes.contains(ClaimType.INPATIENT))
        eobs.addAll(transformToEobs(ClaimType.INPATIENT, findClaimTypeByPatient(ClaimType.INPATIENT, beneficiaryId, lastUpdated, serviceDate), Optional.of(includeTaxNumbers)));
    if (claimTypes.contains(ClaimType.OUTPATIENT))
        eobs.addAll(transformToEobs(ClaimType.OUTPATIENT, findClaimTypeByPatient(ClaimType.OUTPATIENT, beneficiaryId, lastUpdated, serviceDate), Optional.of(includeTaxNumbers)));
    if (claimTypes.contains(ClaimType.PDE))
        eobs.addAll(transformToEobs(ClaimType.PDE, findClaimTypeByPatient(ClaimType.PDE, beneficiaryId, lastUpdated, serviceDate), Optional.of(includeTaxNumbers)));
    if (claimTypes.contains(ClaimType.SNF))
        eobs.addAll(transformToEobs(ClaimType.SNF, findClaimTypeByPatient(ClaimType.SNF, beneficiaryId, lastUpdated, serviceDate), Optional.of(includeTaxNumbers)));
    if (Boolean.parseBoolean(excludeSamhsa))
        filterSamhsa(eobs);
    eobs.sort(ExplanationOfBenefitResourceProvider::compareByClaimIdThenClaimType);
    // Add bene_id to MDC logs
    TransformerUtils.logBeneIdToMdc(Arrays.asList(beneficiaryId));
    return TransformerUtils.createBundle(paging, eobs, loadedFilterManager.getTransactionTime());
}
Also used : OffsetLinkBuilder(gov.cms.bfd.server.war.commons.OffsetLinkBuilder) ArrayList(java.util.ArrayList) Operation(gov.cms.bfd.server.war.Operation) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource) Trace(com.newrelic.api.agent.Trace) Search(ca.uhn.fhir.rest.annotation.Search)

Example 3 with Claim

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

the class ExplanationOfBenefitResourceProvider method findClaimTypeByPatient.

/**
 * @param claimType the {@link ClaimType} to find
 * @param patientId the {@link Beneficiary#getBeneficiaryId()} to filter by
 * @param lastUpdated the update time to filter by
 * @return the matching claim/event entities
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
@Trace
private <T> List<T> findClaimTypeByPatient(ClaimType claimType, String patientId, DateRangeParam lastUpdated, DateRangeParam serviceDate) {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery criteria = builder.createQuery((Class) claimType.getEntityClass());
    Root root = criteria.from(claimType.getEntityClass());
    claimType.getEntityLazyAttributes().stream().forEach(a -> root.fetch(a));
    criteria.select(root).distinct(true);
    // Search for a beneficiary's records. Use lastUpdated if present
    Predicate wherePredicate = builder.equal(root.get(claimType.getEntityBeneficiaryIdAttribute()), patientId);
    if (lastUpdated != null && !lastUpdated.isEmpty()) {
        Predicate predicate = QueryUtils.createLastUpdatedPredicate(builder, root, lastUpdated);
        wherePredicate = builder.and(wherePredicate, predicate);
    }
    criteria.where(wherePredicate);
    List<T> claimEntities = null;
    Long eobsByBeneIdQueryNanoSeconds = null;
    Timer.Context timerEobQuery = metricRegistry.timer(MetricRegistry.name(metricRegistry.getClass().getSimpleName(), "query", "eobs_by_bene_id", claimType.name().toLowerCase())).time();
    try {
        claimEntities = entityManager.createQuery(criteria).getResultList();
    } finally {
        eobsByBeneIdQueryNanoSeconds = timerEobQuery.stop();
        TransformerUtils.recordQueryInMdc(String.format("eobs_by_bene_id.%s", claimType.name().toLowerCase()), eobsByBeneIdQueryNanoSeconds, claimEntities == null ? 0 : claimEntities.size());
    }
    if (claimEntities != null && serviceDate != null && !serviceDate.isEmpty()) {
        final Instant lowerBound = serviceDate.getLowerBoundAsInstant() != null ? serviceDate.getLowerBoundAsInstant().toInstant() : null;
        final Instant upperBound = serviceDate.getUpperBoundAsInstant() != null ? serviceDate.getUpperBoundAsInstant().toInstant() : null;
        final java.util.function.Predicate<LocalDate> lowerBoundCheck = lowerBound == null ? (date) -> true : (date) -> compareLocalDate(date, lowerBound.atZone(ZoneId.systemDefault()).toLocalDate(), serviceDate.getLowerBound().getPrefix());
        final java.util.function.Predicate<LocalDate> upperBoundCheck = upperBound == null ? (date) -> true : (date) -> compareLocalDate(date, upperBound.atZone(ZoneId.systemDefault()).toLocalDate(), serviceDate.getUpperBound().getPrefix());
        return claimEntities.stream().filter(entity -> lowerBoundCheck.test(claimType.getServiceEndAttributeFunction().apply(entity)) && upperBoundCheck.test(claimType.getServiceEndAttributeFunction().apply(entity))).collect(Collectors.toList());
    }
    return claimEntities;
}
Also used : CriteriaBuilder(javax.persistence.criteria.CriteriaBuilder) IdParam(ca.uhn.fhir.rest.annotation.IdParam) Arrays(java.util.Arrays) Bundle(org.hl7.fhir.dstu3.model.Bundle) ListIterator(java.util.ListIterator) Description(ca.uhn.fhir.model.api.annotation.Description) IdType(org.hl7.fhir.dstu3.model.IdType) LoggerFactory(org.slf4j.LoggerFactory) NoResultException(javax.persistence.NoResultException) Matcher(java.util.regex.Matcher) DateRangeParam(ca.uhn.fhir.rest.param.DateRangeParam) Predicate(javax.persistence.criteria.Predicate) IResourceProvider(ca.uhn.fhir.rest.server.IResourceProvider) IBaseResource(org.hl7.fhir.instance.model.api.IBaseResource) CriteriaBuilder(javax.persistence.criteria.CriteriaBuilder) LoadedFilterManager(gov.cms.bfd.server.war.commons.LoadedFilterManager) CriteriaQuery(javax.persistence.criteria.CriteriaQuery) IdDt(ca.uhn.fhir.model.primitive.IdDt) ExplanationOfBenefit(org.hl7.fhir.dstu3.model.ExplanationOfBenefit) InvalidRequestException(ca.uhn.fhir.rest.server.exceptions.InvalidRequestException) ParamPrefixEnum(ca.uhn.fhir.rest.param.ParamPrefixEnum) Set(java.util.Set) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) ZoneId(java.time.ZoneId) Beneficiary(gov.cms.bfd.model.rif.Beneficiary) List(java.util.List) TransformerConstants(gov.cms.bfd.server.war.commons.TransformerConstants) LocalDate(java.time.LocalDate) TokenOrListParam(ca.uhn.fhir.rest.param.TokenOrListParam) Timer(com.codahale.metrics.Timer) Optional(java.util.Optional) OptionalParam(ca.uhn.fhir.rest.annotation.OptionalParam) Pattern(java.util.regex.Pattern) TokenAndListParam(ca.uhn.fhir.rest.param.TokenAndListParam) QueryUtils(gov.cms.bfd.server.war.commons.QueryUtils) Trace(com.newrelic.api.agent.Trace) ArrayList(java.util.ArrayList) RequiredParam(ca.uhn.fhir.rest.annotation.RequiredParam) HashSet(java.util.HashSet) Inject(javax.inject.Inject) RequestDetails(ca.uhn.fhir.rest.api.server.RequestDetails) Search(ca.uhn.fhir.rest.annotation.Search) ReferenceParam(ca.uhn.fhir.rest.param.ReferenceParam) ResourceNotFoundException(ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException) Nullable(javax.annotation.Nullable) Root(javax.persistence.criteria.Root) Read(ca.uhn.fhir.rest.annotation.Read) OffsetLinkBuilder(gov.cms.bfd.server.war.commons.OffsetLinkBuilder) MetricRegistry(com.codahale.metrics.MetricRegistry) Logger(org.slf4j.Logger) Operation(gov.cms.bfd.server.war.Operation) EntityManager(javax.persistence.EntityManager) PersistenceContext(javax.persistence.PersistenceContext) TokenParam(ca.uhn.fhir.rest.param.TokenParam) Component(org.springframework.stereotype.Component) Comparator(java.util.Comparator) Root(javax.persistence.criteria.Root) Instant(java.time.Instant) CriteriaQuery(javax.persistence.criteria.CriteriaQuery) LocalDate(java.time.LocalDate) Predicate(javax.persistence.criteria.Predicate) Timer(com.codahale.metrics.Timer) Trace(com.newrelic.api.agent.Trace)

Example 4 with Claim

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

the class ExplanationOfBenefitResourceProvider method compareByClaimIdThenClaimType.

/*
   * @param eob1 an {@link ExplanationOfBenefit} to be compared
   *
   * @param eob2 an {@link ExplanationOfBenefit} to be compared
   */
private static int compareByClaimIdThenClaimType(IBaseResource res1, IBaseResource res2) {
    /*
     * In order for paging to be meaningful (and stable), the claims have to be
     * consistently sorted across different app server instances (in case page 1
     * comes from Server A but page 2 comes from Server B). Right now, we don't have
     * anything "useful" to sort by, so we just sort by claim ID (subsorted by claim
     * type). TODO once we have metadata from BLUEBUTTON-XXX on when each claim was
     * first loaded into our DB, we should sort by that.
     */
    ExplanationOfBenefit eob1 = (ExplanationOfBenefit) res1;
    ExplanationOfBenefit eob2 = (ExplanationOfBenefit) res2;
    if (TransformerUtils.getUnprefixedClaimId(eob1) == TransformerUtils.getUnprefixedClaimId(eob2)) {
        return TransformerUtils.getClaimType(eob1).compareTo(TransformerUtils.getClaimType(eob2));
    } else {
        return TransformerUtils.getUnprefixedClaimId(eob1).compareTo(TransformerUtils.getUnprefixedClaimId(eob2));
    }
}
Also used : ExplanationOfBenefit(org.hl7.fhir.dstu3.model.ExplanationOfBenefit)

Example 5 with Claim

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

the class HHAClaimTransformer 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();
    // Common group level fields between all claim types
    TransformerUtils.mapEobCommonClaimHeaderData(eob, claimGroup.getClaimId(), claimGroup.getBeneficiaryId(), ClaimType.HHA, claimGroup.getClaimGroupId().toPlainString(), MedicareSegment.PART_B, Optional.of(claimGroup.getDateFrom()), Optional.of(claimGroup.getDateThrough()), Optional.of(claimGroup.getPaymentAmount()), claimGroup.getFinalAction());
    TransformerUtils.mapEobWeeklyProcessDate(eob, claimGroup.getWeeklyProcessDate());
    // map eob type codes into FHIR
    TransformerUtils.mapEobType(eob, ClaimType.HHA, Optional.of(claimGroup.getNearLineRecordIdCode()), Optional.of(claimGroup.getClaimTypeCode()));
    // set the provider number which is common among several claim types
    TransformerUtils.setProviderNumber(eob, claimGroup.getProviderNumber());
    // Common group level fields between Inpatient, Outpatient Hospice, HHA and SNF
    TransformerUtils.mapEobCommonGroupInpOutHHAHospiceSNF(eob, claimGroup.getOrganizationNpi(), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), claimGroup.getPatientDischargeStatusCode(), claimGroup.getClaimServiceClassificationTypeCode(), claimGroup.getClaimPrimaryPayerCode(), claimGroup.getAttendingPhysicianNpi(), claimGroup.getTotalChargeAmount(), claimGroup.getPrimaryPayerPaidAmount(), claimGroup.getFiscalIntermediaryNumber(), claimGroup.getFiDocumentClaimControlNumber(), claimGroup.getFiOriginalClaimControlNumber());
    for (Diagnosis diagnosis : TransformerUtils.extractDiagnoses1Thru12(claimGroup.getDiagnosisPrincipalCode(), claimGroup.getDiagnosisPrincipalCodeVersion(), claimGroup.getDiagnosis1Code(), claimGroup.getDiagnosis1CodeVersion(), claimGroup.getDiagnosis2Code(), claimGroup.getDiagnosis2CodeVersion(), claimGroup.getDiagnosis3Code(), claimGroup.getDiagnosis3CodeVersion(), claimGroup.getDiagnosis4Code(), claimGroup.getDiagnosis4CodeVersion(), claimGroup.getDiagnosis5Code(), claimGroup.getDiagnosis5CodeVersion(), claimGroup.getDiagnosis6Code(), claimGroup.getDiagnosis6CodeVersion(), claimGroup.getDiagnosis7Code(), claimGroup.getDiagnosis7CodeVersion(), claimGroup.getDiagnosis8Code(), claimGroup.getDiagnosis8CodeVersion(), claimGroup.getDiagnosis9Code(), claimGroup.getDiagnosis9CodeVersion(), claimGroup.getDiagnosis10Code(), claimGroup.getDiagnosis10CodeVersion(), claimGroup.getDiagnosis11Code(), claimGroup.getDiagnosis11CodeVersion(), claimGroup.getDiagnosis12Code(), claimGroup.getDiagnosis12CodeVersion())) TransformerUtils.addDiagnosisCode(eob, diagnosis);
    for (Diagnosis diagnosis : TransformerUtils.extractDiagnoses13Thru25(claimGroup.getDiagnosis13Code(), claimGroup.getDiagnosis13CodeVersion(), claimGroup.getDiagnosis14Code(), claimGroup.getDiagnosis14CodeVersion(), claimGroup.getDiagnosis15Code(), claimGroup.getDiagnosis15CodeVersion(), claimGroup.getDiagnosis16Code(), claimGroup.getDiagnosis16CodeVersion(), claimGroup.getDiagnosis17Code(), claimGroup.getDiagnosis17CodeVersion(), claimGroup.getDiagnosis18Code(), claimGroup.getDiagnosis18CodeVersion(), claimGroup.getDiagnosis19Code(), claimGroup.getDiagnosis19CodeVersion(), claimGroup.getDiagnosis20Code(), claimGroup.getDiagnosis20CodeVersion(), claimGroup.getDiagnosis21Code(), claimGroup.getDiagnosis21CodeVersion(), claimGroup.getDiagnosis22Code(), claimGroup.getDiagnosis22CodeVersion(), claimGroup.getDiagnosis23Code(), claimGroup.getDiagnosis23CodeVersion(), claimGroup.getDiagnosis24Code(), claimGroup.getDiagnosis24CodeVersion(), claimGroup.getDiagnosis25Code(), claimGroup.getDiagnosis25CodeVersion())) TransformerUtils.addDiagnosisCode(eob, diagnosis);
    for (Diagnosis diagnosis : TransformerUtils.extractExternalDiagnoses1Thru12(claimGroup.getDiagnosisExternalFirstCode(), claimGroup.getDiagnosisExternalFirstCodeVersion(), claimGroup.getDiagnosisExternal1Code(), claimGroup.getDiagnosisExternal1CodeVersion(), claimGroup.getDiagnosisExternal2Code(), claimGroup.getDiagnosisExternal2CodeVersion(), claimGroup.getDiagnosisExternal3Code(), claimGroup.getDiagnosisExternal3CodeVersion(), claimGroup.getDiagnosisExternal4Code(), claimGroup.getDiagnosisExternal4CodeVersion(), claimGroup.getDiagnosisExternal5Code(), claimGroup.getDiagnosisExternal5CodeVersion(), claimGroup.getDiagnosisExternal6Code(), claimGroup.getDiagnosisExternal6CodeVersion(), claimGroup.getDiagnosisExternal7Code(), claimGroup.getDiagnosisExternal7CodeVersion(), claimGroup.getDiagnosisExternal8Code(), claimGroup.getDiagnosisExternal8CodeVersion(), claimGroup.getDiagnosisExternal9Code(), claimGroup.getDiagnosisExternal9CodeVersion(), claimGroup.getDiagnosisExternal10Code(), claimGroup.getDiagnosisExternal10CodeVersion(), claimGroup.getDiagnosisExternal11Code(), claimGroup.getDiagnosisExternal11CodeVersion(), claimGroup.getDiagnosisExternal12Code(), claimGroup.getDiagnosisExternal12CodeVersion())) TransformerUtils.addDiagnosisCode(eob, diagnosis);
    if (claimGroup.getClaimLUPACode().isPresent()) {
        TransformerUtils.addInformationWithCode(eob, CcwCodebookVariable.CLM_HHA_LUPA_IND_CD, CcwCodebookVariable.CLM_HHA_LUPA_IND_CD, claimGroup.getClaimLUPACode());
    }
    if (claimGroup.getClaimReferralCode().isPresent()) {
        TransformerUtils.addInformationWithCode(eob, CcwCodebookVariable.CLM_HHA_RFRL_CD, CcwCodebookVariable.CLM_HHA_RFRL_CD, claimGroup.getClaimReferralCode());
    }
    BenefitComponent clmHhaTotVisitCntFinancial = TransformerUtils.addBenefitBalanceFinancial(eob, BenefitCategory.MEDICAL, CcwCodebookVariable.CLM_HHA_TOT_VISIT_CNT);
    clmHhaTotVisitCntFinancial.setUsed(new UnsignedIntType(claimGroup.getTotalVisitCount().intValue()));
    // Common group level fields between Inpatient, HHA, Hospice and SNF
    TransformerUtils.mapEobCommonGroupInpHHAHospiceSNF(eob, claimGroup.getCareStartDate(), Optional.empty(), Optional.empty());
    for (HHAClaimLine claimLine : claimGroup.getLines()) {
        ItemComponent item = eob.addItem();
        item.setSequence(claimLine.getLineNumber().intValue());
        item.setLocation(new Address().setState((claimGroup.getProviderStateCode())));
        if (claimLine.getRevCntr1stAnsiCd().isPresent()) {
            item.addAdjudication().setCategory(TransformerUtils.createAdjudicationCategory(CcwCodebookVariable.REV_CNTR_1ST_ANSI_CD)).setReason(TransformerUtils.createCodeableConcept(eob, CcwCodebookVariable.REV_CNTR_1ST_ANSI_CD, claimLine.getRevCntr1stAnsiCd()));
        }
        TransformerUtils.mapHcpcs(eob, item, Optional.empty(), claimLine.getHcpcsCode(), Arrays.asList(claimLine.getHcpcsInitialModifierCode(), claimLine.getHcpcsSecondModifierCode()));
        // Common item level fields between Inpatient, Outpatient, HHA, Hospice and SNF
        TransformerUtils.mapEobCommonItemRevenue(item, eob, claimLine.getRevenueCenterCode(), claimLine.getRateAmount(), claimLine.getTotalChargeAmount(), claimLine.getNonCoveredChargeAmount(), claimLine.getUnitCount(), claimLine.getNationalDrugCodeQuantity(), claimLine.getNationalDrugCodeQualifierCode(), claimLine.getRevenueCenterRenderingPhysicianNPI());
        // Common item level fields between Outpatient, HHA and Hospice
        TransformerUtils.mapEobCommonItemRevenueOutHHAHospice(item, claimLine.getRevenueCenterDate(), claimLine.getPaymentAmount());
        // set revenue center status indicator codes for the claim
        item.getRevenue().addExtension(TransformerUtils.createExtensionCoding(eob, CcwCodebookVariable.REV_CNTR_STUS_IND_CD, claimLine.getStatusCode()));
        // Common group level fields between Inpatient, HHA, Hospice and SNF
        TransformerUtils.mapEobCommonGroupInpHHAHospiceSNFCoinsurance(eob, item, claimLine.getDeductibleCoinsuranceCd());
    }
    TransformerUtils.setLastUpdated(eob, claimGroup.getLastUpdated());
    return eob;
}
Also used : Address(org.hl7.fhir.dstu3.model.Address) ItemComponent(org.hl7.fhir.dstu3.model.ExplanationOfBenefit.ItemComponent) UnsignedIntType(org.hl7.fhir.dstu3.model.UnsignedIntType) Diagnosis(gov.cms.bfd.server.war.commons.Diagnosis) ExplanationOfBenefit(org.hl7.fhir.dstu3.model.ExplanationOfBenefit) HHAClaimLine(gov.cms.bfd.model.rif.HHAClaimLine) BenefitComponent(org.hl7.fhir.dstu3.model.ExplanationOfBenefit.BenefitComponent)

Aggregations

Test (org.junit.jupiter.api.Test)149 Coding (org.hl7.fhir.r4.model.Coding)92 CodeableConcept (org.hl7.fhir.r4.model.CodeableConcept)62 Money (org.hl7.fhir.r4.model.Money)61 BenefitComponent (org.hl7.fhir.r4.model.ExplanationOfBenefit.BenefitComponent)56 Optional (java.util.Optional)50 Arrays (java.util.Arrays)49 List (java.util.List)49 ExplanationOfBenefit (org.hl7.fhir.r4.model.ExplanationOfBenefit)49 FHIRException (org.hl7.fhir.exceptions.FHIRException)48 SupportingInformationComponent (org.hl7.fhir.r4.model.ExplanationOfBenefit.SupportingInformationComponent)48 ExplanationOfBenefit (org.hl7.fhir.dstu3.model.ExplanationOfBenefit)47 Assertions.assertEquals (org.junit.jupiter.api.Assertions.assertEquals)47 StaticRifResourceGroup (gov.cms.bfd.model.rif.samples.StaticRifResourceGroup)45 ServerTestUtils (gov.cms.bfd.server.war.ServerTestUtils)45 TransformerConstants (gov.cms.bfd.server.war.commons.TransformerConstants)41 Instant (java.time.Instant)40 ArrayList (java.util.ArrayList)39 IGenericClient (ca.uhn.fhir.rest.client.api.IGenericClient)37 Beneficiary (gov.cms.bfd.model.rif.Beneficiary)37