Search in sources :

Example 16 with Identifiers

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()));
}
Also used : Identifiers(gov.cms.ab2d.coverage.model.Identifiers) CoverageSearchEvent(gov.cms.ab2d.coverage.model.CoverageSearchEvent) Test(org.junit.jupiter.api.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) DisplayName(org.junit.jupiter.api.DisplayName)

Example 17 with Identifiers

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));
}
Also used : LinkedHashSet(java.util.LinkedHashSet) CoveragePagingRequest(gov.cms.ab2d.coverage.model.CoveragePagingRequest) CoveragePagingResult(gov.cms.ab2d.coverage.model.CoveragePagingResult) CoverageSummary(gov.cms.ab2d.coverage.model.CoverageSummary) CoverageSearchEvent(gov.cms.ab2d.coverage.model.CoverageSearchEvent) Identifiers(gov.cms.ab2d.coverage.model.Identifiers) Collections.disjoint(java.util.Collections.disjoint) Test(org.junit.jupiter.api.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) DisplayName(org.junit.jupiter.api.DisplayName)

Example 18 with Identifiers

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());
}
Also used : LinkedHashSet(java.util.LinkedHashSet) CoveragePagingRequest(gov.cms.ab2d.coverage.model.CoveragePagingRequest) BeforeEach(org.junit.jupiter.api.BeforeEach) ArgumentMatchers(org.mockito.ArgumentMatchers) CoverageDeltaTestRepository(gov.cms.ab2d.coverage.repository.CoverageDeltaTestRepository) Date(java.util.Date) Collections.disjoint(java.util.Collections.disjoint) Autowired(org.springframework.beans.factory.annotation.Autowired) COVERAGE_ADDED(gov.cms.ab2d.coverage.repository.CoverageDeltaRepository.COVERAGE_ADDED) FilterOutByDate(gov.cms.ab2d.filter.FilterOutByDate) CoveragePagingRequest(gov.cms.ab2d.coverage.model.CoveragePagingRequest) Assertions.assertFalse(org.junit.jupiter.api.Assertions.assertFalse) Map(java.util.Map) ZoneOffset(java.time.ZoneOffset) Collectors.toSet(java.util.stream.Collectors.toSet) CoverageDeltaRepository(gov.cms.ab2d.coverage.repository.CoverageDeltaRepository) SpyBean(org.springframework.boot.test.mock.mockito.SpyBean) CoverageSearchRepository(gov.cms.ab2d.coverage.repository.CoverageSearchRepository) CoveragePagingResult(gov.cms.ab2d.coverage.model.CoveragePagingResult) Set(java.util.Set) TestPropertySource(org.springframework.test.context.TestPropertySource) AB2DCoveragePostgressqlContainer(gov.cms.ab2d.coverage.util.AB2DCoveragePostgressqlContainer) Collectors(java.util.stream.Collectors) CoverageSearchEvent(gov.cms.ab2d.coverage.model.CoverageSearchEvent) Test(org.junit.jupiter.api.Test) AB2D_EPOCH(gov.cms.ab2d.common.util.DateUtil.AB2D_EPOCH) List(java.util.List) OffsetDateTime(java.time.OffsetDateTime) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) Identifiers(gov.cms.ab2d.coverage.model.Identifiers) CoveragePeriodRepository(gov.cms.ab2d.coverage.repository.CoveragePeriodRepository) Assertions.assertTrue(org.junit.jupiter.api.Assertions.assertTrue) CoverageMapping(gov.cms.ab2d.coverage.model.CoverageMapping) CoveragePeriod(gov.cms.ab2d.coverage.model.CoveragePeriod) Optional(java.util.Optional) CoverageDataSetup(gov.cms.ab2d.coverage.util.CoverageDataSetup) CoverageSearch(gov.cms.ab2d.coverage.model.CoverageSearch) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) ContractForCoverageDTO(gov.cms.ab2d.coverage.model.ContractForCoverageDTO) CoverageServiceRepository(gov.cms.ab2d.coverage.repository.CoverageServiceRepository) EntityScan(org.springframework.boot.autoconfigure.domain.EntityScan) Assertions.assertNull(org.junit.jupiter.api.Assertions.assertNull) PostgreSQLContainer(org.testcontainers.containers.PostgreSQLContainer) Function(java.util.function.Function) CoverageJobStatus(gov.cms.ab2d.coverage.model.CoverageJobStatus) CoverageCount(gov.cms.ab2d.coverage.model.CoverageCount) EntityNotFoundException(javax.persistence.EntityNotFoundException) DataSource(javax.sql.DataSource) CoverageSearchDiff(gov.cms.ab2d.coverage.model.CoverageSearchDiff) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) LinkedHashSet(java.util.LinkedHashSet) Container(org.testcontainers.junit.jupiter.Container) LogManager(gov.cms.ab2d.eventlogger.LogManager) Testcontainers(org.testcontainers.junit.jupiter.Testcontainers) COVERAGE_DELETED(gov.cms.ab2d.coverage.repository.CoverageDeltaRepository.COVERAGE_DELETED) CoverageSummary(gov.cms.ab2d.coverage.model.CoverageSummary) DisplayName(org.junit.jupiter.api.DisplayName) Coverage(gov.cms.ab2d.coverage.util.Coverage) Mockito(org.mockito.Mockito) AfterEach(org.junit.jupiter.api.AfterEach) Collectors.toList(java.util.stream.Collectors.toList) CoverageDelta(gov.cms.ab2d.coverage.model.CoverageDelta) Assertions(org.junit.jupiter.api.Assertions) CoverageSearchEventRepository(gov.cms.ab2d.coverage.repository.CoverageSearchEventRepository) Comparator(java.util.Comparator) EnableJpaRepositories(org.springframework.data.jpa.repository.config.EnableJpaRepositories) CoveragePagingResult(gov.cms.ab2d.coverage.model.CoveragePagingResult) CoverageSummary(gov.cms.ab2d.coverage.model.CoverageSummary) CoverageSearchEvent(gov.cms.ab2d.coverage.model.CoverageSearchEvent) Identifiers(gov.cms.ab2d.coverage.model.Identifiers) Collections.disjoint(java.util.Collections.disjoint) Test(org.junit.jupiter.api.Test) SpringBootTest(org.springframework.boot.test.context.SpringBootTest) DisplayName(org.junit.jupiter.api.DisplayName)

Example 19 with Identifiers

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));
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Identifiers(gov.cms.ab2d.coverage.model.Identifiers) PatientIdentifier(gov.cms.ab2d.fhir.PatientIdentifier)

Example 20 with Identifiers

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();
    }
}
Also used : IBaseBundle(org.hl7.fhir.instance.model.api.IBaseBundle) Identifiers(gov.cms.ab2d.coverage.model.Identifiers) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Trace(com.newrelic.api.agent.Trace)

Aggregations

Identifiers (gov.cms.ab2d.coverage.model.Identifiers)24 CoverageSearchEvent (gov.cms.ab2d.coverage.model.CoverageSearchEvent)18 Test (org.junit.jupiter.api.Test)18 DisplayName (org.junit.jupiter.api.DisplayName)17 LinkedHashSet (java.util.LinkedHashSet)14 SpringBootTest (org.springframework.boot.test.context.SpringBootTest)14 CoveragePeriod (gov.cms.ab2d.coverage.model.CoveragePeriod)12 CoverageSummary (gov.cms.ab2d.coverage.model.CoverageSummary)10 CoverageMapping (gov.cms.ab2d.coverage.model.CoverageMapping)9 CoverageSearch (gov.cms.ab2d.coverage.model.CoverageSearch)9 Collections.disjoint (java.util.Collections.disjoint)9 CoverageCount (gov.cms.ab2d.coverage.model.CoverageCount)8 CoverageDelta (gov.cms.ab2d.coverage.model.CoverageDelta)8 CoveragePagingRequest (gov.cms.ab2d.coverage.model.CoveragePagingRequest)8 CoveragePagingResult (gov.cms.ab2d.coverage.model.CoveragePagingResult)8 CoverageSearchDiff (gov.cms.ab2d.coverage.model.CoverageSearchDiff)8 FilterOutByDate (gov.cms.ab2d.filter.FilterOutByDate)8 AB2D_EPOCH (gov.cms.ab2d.common.util.DateUtil.AB2D_EPOCH)7 ContractForCoverageDTO (gov.cms.ab2d.coverage.model.ContractForCoverageDTO)7 CoverageJobStatus (gov.cms.ab2d.coverage.model.CoverageJobStatus)7