use of org.hl7.fhir.r4.model.codesystems.ClaimType in project beneficiary-fhir-data by CMSgov.
the class InpatientClaimTransformerTest method assertMatches.
/**
* Verifies that the {@link ExplanationOfBenefit} "looks like" it should, if it were produced from
* the specified {@link InpatientClaim}.
*
* @param claim the {@link InpatientClaim} that the {@link ExplanationOfBenefit} was generated
* from
* @param eob the {@link ExplanationOfBenefit} that was generated from the specified {@link
* InpatientClaim}
* @throws FHIRException (indicates test failure)
*/
static void assertMatches(InpatientClaim claim, ExplanationOfBenefit eob) throws FHIRException {
// Test to ensure group level fields between all claim types match
TransformerTestUtils.assertEobCommonClaimHeaderData(eob, claim.getClaimId(), claim.getBeneficiaryId(), ClaimType.INPATIENT, claim.getClaimGroupId().toPlainString(), MedicareSegment.PART_A, Optional.of(claim.getDateFrom()), Optional.of(claim.getDateThrough()), Optional.of(claim.getPaymentAmount()), claim.getFinalAction());
// test the common field provider number is set as expected in the EOB
TransformerTestUtils.assertProviderNumber(eob, claim.getProviderNumber());
if (claim.getPatientStatusCd().isPresent())
TransformerTestUtils.assertInfoWithCodeEquals(CcwCodebookVariable.NCH_PTNT_STUS_IND_CD, CcwCodebookVariable.NCH_PTNT_STUS_IND_CD, claim.getPatientStatusCd(), eob);
TransformerTestUtils.assertAdjudicationTotalAmountEquals(CcwCodebookVariable.CLM_PASS_THRU_PER_DIEM_AMT, claim.getPassThruPerDiemAmount(), eob);
TransformerTestUtils.assertAdjudicationTotalAmountEquals(CcwCodebookVariable.NCH_PROFNL_CMPNT_CHRG_AMT, claim.getProfessionalComponentCharge(), eob);
TransformerTestUtils.assertAdjudicationTotalAmountEquals(CcwCodebookVariable.CLM_TOT_PPS_CPTL_AMT, claim.getClaimTotalPPSCapitalAmount(), eob);
TransformerTestUtils.assertAdjudicationTotalAmountEquals(CcwCodebookVariable.IME_OP_CLM_VAL_AMT, claim.getIndirectMedicalEducationAmount(), eob);
TransformerTestUtils.assertAdjudicationTotalAmountEquals(CcwCodebookVariable.DSH_OP_CLM_VAL_AMT, claim.getDisproportionateShareAmount(), eob);
// test common eob information between Inpatient, HHA, Hospice and SNF claims are set as
// expected
TransformerTestUtils.assertEobCommonGroupInpHHAHospiceSNFEquals(eob, claim.getClaimAdmissionDate(), claim.getBeneficiaryDischargeDate(), Optional.of(claim.getUtilizationDayCount()));
// test common benefit components between SNF and Inpatient claims are set as expected
TransformerTestUtils.assertCommonGroupInpatientSNF(eob, claim.getCoinsuranceDayCount(), claim.getNonUtilizationDayCount(), claim.getDeductibleAmount(), claim.getPartACoinsuranceLiabilityAmount(), claim.getBloodPintsFurnishedQty(), claim.getNoncoveredCharge(), claim.getTotalDeductionAmount(), claim.getClaimPPSCapitalDisproportionateShareAmt(), claim.getClaimPPSCapitalExceptionAmount(), claim.getClaimPPSCapitalFSPAmount(), claim.getClaimPPSCapitalIMEAmount(), claim.getClaimPPSCapitalOutlierAmount(), claim.getClaimPPSOldCapitalHoldHarmlessAmount());
// test common eob information between SNF and Inpatient claims are set as expected
TransformerTestUtils.assertCommonEobInformationInpatientSNF(eob, claim.getNoncoveredStayFromDate(), claim.getNoncoveredStayThroughDate(), claim.getCoveredCareThoughDate(), claim.getMedicareBenefitsExhaustedDate(), claim.getDiagnosisRelatedGroupCd());
TransformerTestUtils.assertAdjudicationTotalAmountEquals(CcwCodebookVariable.NCH_DRG_OUTLIER_APRVD_PMT_AMT, claim.getDrgOutlierApprovedPaymentAmount(), eob);
// Test to ensure common group fields between Inpatient, Outpatient and SNF
// match
TransformerTestUtils.assertEobCommonGroupInpOutSNFEquals(eob, claim.getBloodDeductibleLiabilityAmount(), claim.getOperatingPhysicianNpi(), claim.getOtherPhysicianNpi(), claim.getClaimQueryCode(), claim.getMcoPaidSw());
// Test to ensure common group fields between Inpatient, Outpatient HHA, Hospice
// and SNF match
TransformerTestUtils.assertEobCommonGroupInpOutHHAHospiceSNFEquals(eob, claim.getOrganizationNpi(), claim.getClaimFacilityTypeCode(), claim.getClaimFrequencyCode(), claim.getClaimNonPaymentReasonCode(), claim.getPatientDischargeStatusCode(), claim.getClaimServiceClassificationTypeCode(), claim.getClaimPrimaryPayerCode(), claim.getAttendingPhysicianNpi(), claim.getTotalChargeAmount(), claim.getPrimaryPayerPaidAmount(), claim.getFiscalIntermediaryNumber(), claim.getFiDocumentClaimControlNumber(), claim.getFiOriginalClaimControlNumber());
assertEquals(9, eob.getDiagnosis().size());
// test to ensure the diagnosis code display lookup table process works
Optional<Diagnosis> diagnosis = Diagnosis.from(claim.getDiagnosis5Code(), claim.getDiagnosis5CodeVersion());
TransformerTestUtils.assertHasCoding(diagnosis.get().getFhirSystem(), null, TransformerUtils.retrieveIcdCodeDisplay(diagnosis.get().getCode()), diagnosis.get().getCode(), eob.getDiagnosis().get(6).getDiagnosisCodeableConcept().getCoding());
CCWProcedure ccwProcedure = new CCWProcedure(claim.getProcedure1Code(), claim.getProcedure1CodeVersion(), claim.getProcedure1Date());
TransformerTestUtils.assertHasCoding(ccwProcedure.getFhirSystem().toString(), claim.getProcedure1Code().get(), eob.getProcedure().get(0).getProcedureCodeableConcept().getCoding());
assertEquals(TransformerUtils.convertToDate(claim.getProcedure1Date().get()), eob.getProcedure().get(0).getDate());
// test to ensure the procedure code display lookup table process works
CCWProcedure ccwProcedureDisplay = new CCWProcedure(claim.getProcedure6Code(), claim.getProcedure6CodeVersion(), claim.getProcedure6Date());
TransformerTestUtils.assertHasCoding(ccwProcedureDisplay.getFhirSystem().toString(), null, TransformerUtils.retrieveProcedureCodeDisplay(claim.getProcedure6Code().get()), claim.getProcedure6Code().get(), eob.getProcedure().get(5).getProcedureCodeableConcept().getCoding());
assertEquals(1, eob.getItem().size());
ItemComponent eobItem0 = eob.getItem().get(0);
InpatientClaimLine claimLine1 = claim.getLines().get(0);
assertEquals(claimLine1.getLineNumber(), new BigDecimal(eobItem0.getSequence()));
assertEquals(claim.getProviderStateCode(), eobItem0.getLocationAddress().getState());
TransformerTestUtils.assertHcpcsCodes(eobItem0, claimLine1.getHcpcsCode(), Optional.empty(), Optional.empty(), Optional.empty(), 0);
// Test to ensure common group field coinsurance between Inpatient, HHA, Hospice and SNF match
TransformerTestUtils.assertEobCommonGroupInpHHAHospiceSNFCoinsuranceEquals(eobItem0, claimLine1.getDeductibleCoinsuranceCd());
String claimControlNumber = "0000000000";
// Test to ensure item level fields between Inpatient, Outpatient, HHA, Hopsice
// and SNF match
TransformerTestUtils.assertEobCommonItemRevenueEquals(eobItem0, eob, claimLine1.getRevenueCenter(), claimLine1.getRateAmount(), claimLine1.getTotalChargeAmount(), claimLine1.getNonCoveredChargeAmount(), claimLine1.getUnitCount(), claimControlNumber, claimLine1.getNationalDrugCodeQuantity(), claimLine1.getNationalDrugCodeQualifierCode(), claimLine1.getRevenueCenterRenderingPhysicianNPI(), 0);
// verify {@link
// TransformerUtils#mapEobType(CodeableConcept,ClaimType,Optional,Optional)}
// method worked as expected for this claim type
TransformerTestUtils.assertMapEobType(eob.getType(), ClaimType.INPATIENT, Optional.of(org.hl7.fhir.dstu3.model.codesystems.ClaimType.INSTITUTIONAL), Optional.of(claim.getNearLineRecordIdCode()), Optional.of(claim.getClaimTypeCode()));
// Test lastUpdated
TransformerTestUtils.assertLastUpdatedEquals(claim.getLastUpdated(), eob);
}
use of org.hl7.fhir.r4.model.codesystems.ClaimType in project beneficiary-fhir-data by CMSgov.
the class TransformerUtilsV2 method mapEobCommonClaimHeaderData.
/**
* Transforms the common group level header fields between all claim types
*
* @param eob the {@link ExplanationOfBenefit} to modify
* @param claimId CLM_ID
* @param beneficiaryId BENE_ID
* @param claimType {@link ClaimTypeV2} to process
* @param claimGroupId CLM_GRP_ID
* @param coverageType {@link MedicareSegment}
* @param dateFrom CLM_FROM_DT || SRVC_DT (For Part D Events)
* @param dateThrough CLM_THRU_DT || SRVC_DT (For Part D Events)
* @param paymentAmount CLM_PMT_AMT
* @param finalAction FINAL_ACTION
*/
static void mapEobCommonClaimHeaderData(ExplanationOfBenefit eob, String claimId, String beneficiaryId, ClaimTypeV2 claimType, String claimGroupId, MedicareSegment coverageType, Optional<LocalDate> dateFrom, Optional<LocalDate> dateThrough, Optional<BigDecimal> paymentAmount, char finalAction) {
// Claim Type + Claim ID => ExplanationOfBenefit.id
eob.setId(buildEobId(claimType, claimId));
// Current timestamp => Created
eob.setCreated(new Date());
// "claim" => ExplanationOfBenefit.use
eob.setUse(Use.CLAIM);
if (claimType.equals(ClaimTypeV2.PDE)) {
// PDE_ID => ExplanationOfBenefit.identifier
eob.addIdentifier(createClaimIdentifier(CcwCodebookVariable.PDE_ID, claimId));
} else {
// CLM_ID => ExplanationOfBenefit.identifier
eob.addIdentifier(createClaimIdentifier(CcwCodebookVariable.CLM_ID, claimId));
}
// CLM_GRP_ID => ExplanationOfBenefit.identifier
eob.addIdentifier().setSystem(TransformerConstants.IDENTIFIER_SYSTEM_BBAPI_CLAIM_GROUP_ID).setValue(claimGroupId).setType(createC4BBClaimCodeableConcept());
// BENE_ID + Coverage Type => ExplanationOfBenefit.insurance.coverage (ref)
eob.addInsurance().setCoverage(referenceCoverage(beneficiaryId, coverageType));
// BENE_ID => ExplanationOfBenefit.patient (reference)
eob.setPatient(referencePatient(beneficiaryId));
// "insurer" => ExplanationOfBenefit.insurer
eob.setInsurer(new Reference().setIdentifier(new Identifier().setValue("CMS")));
// "outcome" => ExplanationOfBenefit.outcome
eob.setOutcome(RemittanceOutcome.COMPLETE);
// FINAL_ACTION => ExplanationOfBenefit.status
switch(finalAction) {
case 'F':
eob.setStatus(ExplanationOfBenefitStatus.ACTIVE);
break;
case 'N':
eob.setStatus(ExplanationOfBenefitStatus.CANCELLED);
break;
default:
// unknown final action value
throw new BadCodeMonkeyException();
}
// CLM_THRU_DT || SRVC_DT (For Part D Events) => ExplanationOfBenefit.billablePeriod.end
if (dateFrom.isPresent()) {
validatePeriodDates(dateFrom, dateThrough);
setPeriodStart(eob.getBillablePeriod(), dateFrom.get());
setPeriodEnd(eob.getBillablePeriod(), dateThrough.get());
}
// CLM_PMT_AMT => ExplanationOfBenefit.payment.amount
if (paymentAmount.isPresent()) {
eob.getPayment().setAmount(createMoney(paymentAmount));
}
}
use of org.hl7.fhir.r4.model.codesystems.ClaimType in project beneficiary-fhir-data by CMSgov.
the class R4ExplanationOfBenefitResourceProvider method findClaimTypeByPatient.
/**
* @param claimType the {@link ClaimTypeV2} 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(ClaimTypeV2 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();
TransformerUtilsV2.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;
}
use of org.hl7.fhir.r4.model.codesystems.ClaimType in project beneficiary-fhir-data by CMSgov.
the class ExplanationOfBenefitResourceProvider method read.
/**
* Adds support for the FHIR "read" operation, for {@link ExplanationOfBenefit}s. The {@link Read}
* annotation indicates that this method supports the read operation.
*
* <p>Read operations take a single parameter annotated with {@link IdParam}, and should return a
* single resource instance.
*
* @param eobId The read operation takes one parameter, which must be of type {@link IdType} and
* must be annotated with the {@link IdParam} annotation.
* @param requestDetails a {@link RequestDetails} containing the details of the request URL, used
* to parse out header values
* @return Returns a resource matching the specified {@link IdDt}, or <code>null</code> if none
* exists.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Read(version = false)
@Trace
public ExplanationOfBenefit read(@IdParam IdType eobId, RequestDetails requestDetails) {
if (eobId == null)
throw new IllegalArgumentException();
if (eobId.getVersionIdPartAsLong() != null)
throw new IllegalArgumentException();
String eobIdText = eobId.getIdPart();
if (eobIdText == null || eobIdText.trim().isEmpty())
throw new IllegalArgumentException();
Matcher eobIdMatcher = EOB_ID_PATTERN.matcher(eobIdText);
if (!eobIdMatcher.matches())
throw new IllegalArgumentException("Unsupported ID pattern: " + eobIdText);
String eobIdTypeText = eobIdMatcher.group(1);
Optional<ClaimType> eobIdType = ClaimType.parse(eobIdTypeText);
Boolean includeTaxNumbers = returnIncludeTaxNumbers(requestDetails);
if (!eobIdType.isPresent())
throw new ResourceNotFoundException(eobId);
String eobIdClaimIdText = eobIdMatcher.group(2);
Operation operation = new Operation(Operation.Endpoint.V1_EOB);
operation.setOption("IncludeTaxNumbers", "" + includeTaxNumbers);
operation.setOption("by", "id");
operation.publishOperationName();
Class<?> entityClass = eobIdType.get().getEntityClass();
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery criteria = builder.createQuery(entityClass);
Root root = criteria.from(entityClass);
eobIdType.get().getEntityLazyAttributes().stream().forEach(a -> root.fetch(a));
criteria.select(root);
criteria.where(builder.equal(root.get(eobIdType.get().getEntityIdAttribute()), eobIdClaimIdText));
Object claimEntity = null;
Long eobByIdQueryNanoSeconds = null;
Timer.Context timerEobQuery = metricRegistry.timer(MetricRegistry.name(getClass().getSimpleName(), "query", "eob_by_id")).time();
try {
claimEntity = entityManager.createQuery(criteria).getSingleResult();
} catch (NoResultException e) {
throw new ResourceNotFoundException(eobId);
} finally {
eobByIdQueryNanoSeconds = timerEobQuery.stop();
TransformerUtils.recordQueryInMdc("eob_by_id", eobByIdQueryNanoSeconds, claimEntity == null ? 0 : 1);
}
ExplanationOfBenefit eob = eobIdType.get().getTransformer().transform(metricRegistry, claimEntity, Optional.of(includeTaxNumbers));
return eob;
}
use of org.hl7.fhir.r4.model.codesystems.ClaimType in project beneficiary-fhir-data by CMSgov.
the class DiagnosisUtilV2 method translateLabels.
/**
* Translates a list of {@link DiagnosisLabel} to an EOB type specific Coding based on the (@link
* ClaimTypeV2}.
*
* <p>In practice, the list will only ever be one {@link DiagnosisLabel}. The {@link Diagnosis}
* class allows multiple labels to be present, so we cover that case here. In V2, only a single
* label will ever be assigned.
*/
static CodeableConcept translateLabels(Set<DiagnosisLabel> labels, ClaimTypeV2 claimType) {
CodeableConcept diagType = new CodeableConcept();
List<Coding> codings = labels.stream().map(l -> translateLabelCode(l, claimType)).collect(Collectors.toList());
return diagType.setCoding(codings);
}
Aggregations