use of gov.cms.ab2d.coverage.model.Identifiers in project ab2d by CMSgov.
the class CoverageServiceImplTest method deletePreviousSearchOnCompletion.
@DisplayName("Delete all previous search coverage information on completion of a new search")
@Test
void deletePreviousSearchOnCompletion() {
Set<Identifiers> results1 = Set.of(createIdentifier(1231L), createIdentifier(4561L), createIdentifier(7891L));
Set<Long> beneIds1 = results1.stream().map(Identifiers::getBeneficiaryId).collect(toSet());
Set<Identifiers> results2 = Set.of(createIdentifier(1232L), createIdentifier(4562L), createIdentifier(7892L));
Set<Long> beneIds2 = results2.stream().map(Identifiers::getBeneficiaryId).collect(toSet());
coverageService.submitSearch(period1Jan.getId(), "testing");
CoverageSearchEvent inProgress1 = startSearchAndPullEvent();
CoverageSearchEvent savedTo1 = coverageService.insertCoverage(inProgress1.getId(), results1);
coverageService.completeSearch(period1Jan.getId(), "testing");
assertEquals(inProgress1, savedTo1);
// Failing a search and somehow deletion doesn't process
coverageService.submitSearch(period1Jan.getId(), "testing");
CoverageSearchEvent inProgress2 = startSearchAndPullEvent();
CoverageSearchEvent savedTo2 = coverageService.insertCoverage(inProgress2.getId(), results1);
assertEquals(inProgress2, savedTo2);
// Fail search outside of normal method
CoverageSearchEvent failSearch = new CoverageSearchEvent();
failSearch.setCoveragePeriod(period1Jan);
failSearch.setDescription("testing");
failSearch.setOldStatus(CoverageJobStatus.IN_PROGRESS);
failSearch.setNewStatus(CoverageJobStatus.FAILED);
coverageSearchEventRepo.saveAndFlush(failSearch);
period1Jan.setStatus(CoverageJobStatus.FAILED);
coveragePeriodRepo.saveAndFlush(period1Jan);
// Completing a second search should trigger deletion of old data
coverageService.submitSearch(period1Jan.getId(), "testing");
CoverageSearchEvent inProgress3 = startSearchAndPullEvent();
CoverageSearchEvent savedTo3 = coverageService.insertCoverage(inProgress3.getId(), results2);
coverageService.completeSearch(period1Jan.getId(), "testing");
assertEquals(inProgress3, savedTo3);
List<Long> coverages = dataSetup.findCoverage().stream().map(Coverage::getBeneficiaryId).collect(toList());
assertTrue(disjoint(beneIds1, coverages));
assertTrue(coverages.containsAll(beneIds2));
Set<Long> distinctSearchEvents = dataSetup.findCoverage().stream().map(Coverage::getSearchEventId).collect(toSet());
assertFalse(distinctSearchEvents.contains(inProgress1.getId()));
assertFalse(distinctSearchEvents.contains(inProgress2.getId()));
assertTrue(distinctSearchEvents.contains(inProgress3.getId()));
}
use of gov.cms.ab2d.coverage.model.Identifiers in project ab2d by CMSgov.
the class CoverageServiceImplTest method pageCoverageOnlyReturnsBeneficiariesForContract.
@DisplayName("Page coverage only returns beneficiaries from the right contract only")
@Test
void pageCoverageOnlyReturnsBeneficiariesForContract() {
dataSetup.createCoveragePeriod("TST-34", 2020, 2);
dataSetup.createCoveragePeriod("TST-34", 2020, 3);
dataSetup.createCoveragePeriod("TST-34", 2020, 4);
coverageService.submitSearch(period1Jan.getId(), "testing");
coverageService.submitSearch(period2Jan.getId(), "testing");
CoverageSearchEvent inProgressContract1 = startSearchAndPullEvent();
CoverageSearchEvent inProgressContract2 = startSearchAndPullEvent();
// Last page will have only one id
int totalBeneficiaries = 500;
int pageSize = 1000;
// Add 700 beneficiaries to
Set<Identifiers> identifiersContract1 = new LinkedHashSet<>();
for (long idx = 0; idx < totalBeneficiaries; idx++) {
identifiersContract1.add(createIdentifier(idx));
}
Set<Identifiers> identifiersContract2 = new LinkedHashSet<>();
for (long idx = 500; idx < 500 + totalBeneficiaries; idx++) {
identifiersContract1.add(createIdentifier(idx));
}
CoverageSearchEvent savedTo1 = coverageService.insertCoverage(inProgressContract1.getId(), identifiersContract1);
CoverageSearchEvent savedTo2 = coverageService.insertCoverage(inProgressContract2.getId(), identifiersContract2);
assertEquals(inProgressContract1, savedTo1);
assertEquals(inProgressContract2, savedTo2);
CoveragePagingRequest pagingRequest1 = new CoveragePagingRequest(pageSize, null, contract1, jobStartTime);
CoveragePagingResult pagingResult1 = coverageServiceRepo.pageCoverage(pagingRequest1);
List<CoverageSummary> coverageSummaries1 = pagingResult1.getCoverageSummaries();
assertTrue(coverageSummaries1.stream().map(CoverageSummary::getIdentifiers).allMatch(identifiersContract1::contains));
assertTrue(coverageSummaries1.stream().map(CoverageSummary::getIdentifiers).noneMatch(identifiersContract2::contains));
CoveragePagingRequest pagingRequest2 = new CoveragePagingRequest(pageSize, null, contract2, jobStartTime);
CoveragePagingResult pagingResult2 = coverageServiceRepo.pageCoverage(pagingRequest2);
List<CoverageSummary> coverageSummaries2 = pagingResult2.getCoverageSummaries();
assertTrue(coverageSummaries2.stream().map(CoverageSummary::getIdentifiers).noneMatch(identifiersContract1::contains));
assertTrue(coverageSummaries2.stream().map(CoverageSummary::getIdentifiers).allMatch(identifiersContract2::contains));
}
use of gov.cms.ab2d.coverage.model.Identifiers in project ab2d by CMSgov.
the class CoverageServiceImplTest method pageCoverage.
@DisplayName("Page coverage from database correctly provides next requests")
@Test
void pageCoverage() {
coverageService.submitSearch(period1Jan.getId(), "testing");
CoverageSearchEvent inProgress = startSearchAndPullEvent();
// Last page will have only one id
int totalBeneficiaries = 501;
int pageSize = 250;
// Add 700 beneficiaries to
Set<Identifiers> identifiers = new LinkedHashSet<>();
for (long idx = 0; idx < totalBeneficiaries; idx++) {
identifiers.add(createIdentifier(idx));
}
CoverageSearchEvent savedTo = coverageService.insertCoverage(inProgress.getId(), identifiers);
assertEquals(inProgress, savedTo);
CoveragePagingRequest pagingRequest = new CoveragePagingRequest(pageSize, null, contract1, jobStartTime);
// Complete first request which should return exactly 333 results, and the next
CoveragePagingResult pagingResult = coverageServiceRepo.pageCoverage(pagingRequest);
List<CoverageSummary> coverageSummaries = pagingResult.getCoverageSummaries();
assertEquals(pageSize, coverageSummaries.size());
assertTrue(pagingResult.getNextRequest().isPresent());
pagingRequest = pagingResult.getNextRequest().get();
assertTrue(pagingRequest.getCursor().isPresent());
assertEquals(pageSize, pagingRequest.getPageSize());
// Complete second request which should return exactly 333
Long cursor = pagingRequest.getCursor().get();
pagingResult = coverageServiceRepo.pageCoverage(pagingRequest);
coverageSummaries = pagingResult.getCoverageSummaries();
coverageSummaries.sort(Comparator.comparing(summary -> summary.getIdentifiers().getBeneficiaryId()));
assertEquals(cursor, coverageSummaries.get(0).getIdentifiers().getBeneficiaryId());
assertEquals(pageSize, coverageSummaries.size());
assertTrue(pagingResult.getNextRequest().isPresent());
pagingRequest = pagingResult.getNextRequest().get();
assertTrue(pagingRequest.getCursor().isPresent());
assertEquals(pageSize, pagingRequest.getPageSize());
// Complete third request should return one record with no next cursor
cursor = pagingRequest.getCursor().get();
pagingResult = coverageServiceRepo.pageCoverage(pagingRequest);
coverageSummaries = pagingResult.getCoverageSummaries();
coverageSummaries.sort(Comparator.comparing(summary -> summary.getIdentifiers().getBeneficiaryId()));
assertEquals(cursor, coverageSummaries.get(0).getIdentifiers().getBeneficiaryId());
assertEquals(1, coverageSummaries.size());
assertTrue(pagingResult.getNextRequest().isEmpty());
}
use of gov.cms.ab2d.coverage.model.Identifiers in project ab2d by CMSgov.
the class CoverageMappingCallable method extractPatientId.
/**
* Given a patient, extract patient ids and package into an {@link Identifiers} object.
*
* Record metrics on the identifiers found.
*
* Steps
* - Find all types of identifiers present on the patient
* - Check that an internal beneficiary id is present for the patient.
* - If not present do not add the patient to the list
* - Check that a current MBI is present
* - Check whether historical MBIs are present
* - Create identifiers using identifiers that were present in the patient object
*
* @param patient - the patient id
* @return the identifiers present if a beneficiary id is present on the patient
*/
Identifiers extractPatientId(IDomainResource patient) {
List<PatientIdentifier> ids = IdentifierUtils.getIdentifiers(patient);
// Get patient beneficiary id
// if not found eobs cannot be looked up so do not return a meaningful list
PatientIdentifier beneIdObj = IdentifierUtils.getBeneId(ids);
if (beneIdObj == null || beneIdObj.getValue() == null) {
missingBeneId += 1;
return null;
}
// Get current mbi if present or else log not present
PatientIdentifier currentMbi = IdentifierUtils.getCurrentMbi(ids);
if (currentMbi == null) {
missingCurrentMbi += 1;
}
LinkedHashSet<PatientIdentifier> historicMbis = IdentifierUtils.getHistoricMbi(ids);
if (historicMbis == null || !historicMbis.isEmpty()) {
hasHistoricalMbi += 1;
}
LinkedHashSet<String> historicalIds = new LinkedHashSet<>();
if (historicMbis != null) {
historicalIds = historicMbis.stream().map(PatientIdentifier::getValue).collect(toCollection(LinkedHashSet::new));
}
if (currentMbi == null) {
int numOfHistorical = historicalIds.size();
log.error("Beneficiary " + beneIdObj.getValue() + " has a null MBI and " + numOfHistorical + " historical");
return new Identifiers(beneIdObj.getValueAsLong(), null, new LinkedHashSet<>(historicalIds));
}
return new Identifiers(beneIdObj.getValueAsLong(), currentMbi.getValue(), new LinkedHashSet<>(historicalIds));
}
use of gov.cms.ab2d.coverage.model.Identifiers in project ab2d by CMSgov.
the class CoverageMappingCallable method call.
/**
* Execute queries against BFD and collect enrollment result into a single object.
*
* In the past there have been significant issues related to the values of the enrollment returned by BFD.
* These issues have led to adding a bunch of logs in here for most steps in the enrollment process.
*
* These logs include:
* - log each bundle received with the page number
* - listing all links to additional pages returned by BFD
* - log last page received
* - record statistics regarding potentially missing things like MBIs, beneficiary ids, distribution of reference
* years on the patient, and past reference years which are not expected.
*
* Steps
* - Set a unique id for the job as a header to BFD for monitoring purposes
* - Get the first page of enrollment results and process those results
* - Loop over the remaining pages of results and query until none are left
* - Add the results to the CoverageMapping object
* - Mark the search as completed
* - Log statistics concerning enrollment pulled
* - Remove the unique id header used for BFD
*
* @throws Exception on any failure, before the exception is thrown it will be logged
*/
@Trace(metricName = "EnrollmentRequest", dispatcher = true)
@Override
public CoverageMapping call() {
int month = coverageMapping.getPeriod().getMonth();
String contractNumber = coverageMapping.getContractNumber();
final Set<Identifiers> patientIds = new HashSet<>();
int bundleNo = 1;
try {
log.info("retrieving contract membership for ContractWorkerDto {}-{}-{} bundle #{}", contractNumber, this.year, month, bundleNo);
BFDClient.BFD_BULK_JOB_ID.set(coverageMapping.getJobId());
IBaseBundle bundle = getBundle(contractNumber, month, this.year);
patientIds.addAll(extractAndFilter(bundle));
String availableLinks = BundleUtils.getAvailableLinks(bundle);
log.info("retrieving contract membership for ContractWorkerDto {}-{}-{} bundle #{}, available links {}", contractNumber, this.year, month, bundleNo, availableLinks);
if (BundleUtils.getNextLink(bundle) == null) {
log.info("retrieving contract membership for ContractWorkerDto {}-{}-{} bundle #{}, does not have a next link", contractNumber, this.year, month, bundleNo);
}
while (BundleUtils.getNextLink(bundle) != null) {
bundleNo += 1;
log.info("retrieving contract membership for ContractWorkerDto {}-{}-{} bundle #{}", contractNumber, this.year, month, bundleNo);
bundle = bfdClient.requestNextBundleFromServer(version, bundle);
availableLinks = BundleUtils.getAvailableLinksPretty(bundle);
log.info("retrieving contract membership for ContractWorkerDto {}-{}-{} bundle #{}, available links {}", contractNumber, this.year, month, bundleNo, availableLinks);
if (BundleUtils.getNextLink(bundle) == null) {
log.info("retrieving contract membership for ContractWorkerDto {}-{}-{} bundle #{}, does not have a next link", contractNumber, this.year, month, bundleNo);
}
patientIds.addAll(extractAndFilter(bundle));
}
log.info("retrieving contract membership for ContractWorkerDto {}-{}-{}, #{} bundles received.", contractNumber, this.year, month, bundleNo);
coverageMapping.addBeneficiaries(patientIds);
log.debug("finished reading [{}] Set<Identifiers>resources", patientIds.size());
coverageMapping.completed();
return coverageMapping;
} catch (Exception e) {
log.error("Unable to get patient information for " + contractNumber + " for month " + month + " and year " + this.year, e);
coverageMapping.failed();
throw e;
} finally {
int total = patientIds.size() + missingReferenceYear + missingBeneId + pastReferenceYear;
log.info("Search {}-{}-{} found {} distribution of reference years over a total of {} benes", contractNumber, this.year, month, referenceYears, total);
log.info("Search {}-{}-{} discarded {} entries missing a reference year out of {}", contractNumber, this.year, month, missingReferenceYear, total);
log.info("Search {}-{}-{} discarded {} entries with a reference year in the past out of {}", contractNumber, this.year, month, pastReferenceYear, total);
log.info("Search {}-{}-{} discarded {} entries missing a beneficiary identifier out of {}", contractNumber, this.year, month, missingBeneId, total);
log.info("Search {}-{}-{} found {} entries missing a current mbi out of {}", contractNumber, this.year, month, missingCurrentMbi, total);
log.info("Search {}-{}-{} found {} entries with a historical mbi out of {}", contractNumber, this.year, month, hasHistoricalMbi, total);
completed.set(true);
BFDClient.BFD_BULK_JOB_ID.remove();
}
}
Aggregations