Skip to content

Commit

Permalink
AB2D-5622 (#1281)
Browse files Browse the repository at this point in the history
the database, there is logic to use the new columns and fields to programmatically filter out beneficiaries from the AB2D response
  • Loading branch information
smirnovaae authored Aug 29, 2023
1 parent 65f6010 commit 93ffec7
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ private PropertyConstants() { }

// Force a coverage update to run even when not scheduled
public static final String COVERAGE_SEARCH_OVERRIDE = "coverage.update.override";

public static final String OPT_OUT_ON = "OptOutOn";

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class PropertyServiceStub implements PropertiesService {
propertiesMapOrig.put("coverage.update.months.past", "1");
propertiesMapOrig.put("coverage.update.override", "false");
propertiesMapOrig.put("maintenance.mode", "false");
propertiesMapOrig.put("OptOutOn", "false");
}

public void reset() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gov.cms.ab2d.coverage.repository;

import com.newrelic.api.agent.Trace;
import gov.cms.ab2d.common.properties.PropertiesService;
import gov.cms.ab2d.coverage.model.ContractForCoverageDTO;
import gov.cms.ab2d.coverage.model.CoverageCount;
import gov.cms.ab2d.coverage.model.CoverageJobStatus;
Expand Down Expand Up @@ -95,6 +96,13 @@ public class CoverageServiceRepository {
private static final String SELECT_DISTINCT_COVERAGE_BY_PERIOD_COUNT = "SELECT COUNT(DISTINCT beneficiary_id) FROM coverage" +
" WHERE bene_coverage_period_id IN(:ids) AND contract = :contract AND year IN (:years)";

/**
* Return a count of all beneficiaries who aggred to share their data associated with an {@link CoveragePeriod}
* from any event. For those beneficiaries out_out_flag equals false in the public.coverage table.
*/
private static final String SELECT_DISTINCT_OPTOUT_COVERAGE_BY_PERIOD_COUNT = "SELECT COUNT(DISTINCT beneficiary_id) FROM coverage" +
" WHERE bene_coverage_period_id IN(:ids) AND contract = :contract AND year IN (:years) AND opt_out_flag = false";

/**
* Delete all coverage associated with a single update from BFD {@link CoverageSearchEvent}
*
Expand Down Expand Up @@ -158,6 +166,13 @@ public class CoverageServiceRepository {
" ORDER BY beneficiary_id " +
" LIMIT :limit";

private static final String SELECT_OPTOUT_COVERAGE_WITHOUT_CURSOR =
"SELECT beneficiary_id, current_mbi, historic_mbis, year, month " +
" FROM coverage " +
" WHERE contract = :contract and year IN (:years) and opt_out_flag = false" +
" ORDER BY beneficiary_id " +
" LIMIT :limit";

/**
* Select a limited number of records starting from a beneficiary (cursor)
* from the coverage table associated with a specific contract.
Expand All @@ -173,6 +188,13 @@ public class CoverageServiceRepository {
" ORDER BY beneficiary_id " +
" LIMIT :limit";

private static final String SELECT_OPTOUT_COVERAGE_WITH_CURSOR =
"SELECT beneficiary_id, current_mbi, historic_mbis, year, month " +
" FROM coverage " +
" WHERE contract = :contract and year IN (:years) and opt_out_flag = false AND beneficiary_id >= :cursor " +
" ORDER BY beneficiary_id " +
" LIMIT :limit";

/**
* Given a list of contracts, for each contract and all {@link CoveragePeriod}s that contract has been active for,
* count the number of beneficiaries covered by the contract and report those results.
Expand All @@ -197,12 +219,14 @@ public class CoverageServiceRepository {
private final DataSource dataSource;
private final CoveragePeriodRepository coveragePeriodRepo;
private final CoverageSearchEventRepository coverageSearchEventRepo;
private final PropertiesService propertiesService;

public CoverageServiceRepository(DataSource dataSource, CoveragePeriodRepository coveragePeriodRepo,
CoverageSearchEventRepository coverageSearchEventRepo) {
CoverageSearchEventRepository coverageSearchEventRepo, PropertiesService propertiesService) {
this.dataSource = dataSource;
this.coverageSearchEventRepo = coverageSearchEventRepo;
this.coveragePeriodRepo = coveragePeriodRepo;
this.propertiesService = propertiesService;
}

/**
Expand Down Expand Up @@ -284,8 +308,10 @@ public int countBeneficiariesByPeriods(List<Integer> coveragePeriodIds, String c
.addValue("years", YEARS);

NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(dataSource);
//If OptOut is enabled, count beneficiaries who agreed to share their data
String query = (propertiesService.isToggleOn("OptOutOn", false)) ? SELECT_DISTINCT_OPTOUT_COVERAGE_BY_PERIOD_COUNT : SELECT_DISTINCT_COVERAGE_BY_PERIOD_COUNT;

return template.queryForList(SELECT_DISTINCT_COVERAGE_BY_PERIOD_COUNT, parameters, Integer.class)
return template.queryForList(query, parameters, Integer.class)
.stream().findFirst().orElseThrow(() -> new RuntimeException("no coverage information found for any " +
"of the coverage periods provided"));
}
Expand Down Expand Up @@ -572,14 +598,17 @@ private List<CoverageMembership> queryCoverageMembership(CoveragePagingRequest p

pageCursor.ifPresent((cursor) -> sqlParameterSource.addValue("cursor", cursor));

boolean isOptOutOn = propertiesService.isToggleOn("OptOutOn", false);
// Grab the enrollment
List<CoverageMembership> enrollment;
NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(dataSource);
if (pageCursor.isPresent()) {
enrollment = template.query(SELECT_COVERAGE_WITH_CURSOR, sqlParameterSource,
String queryWithCursor = (isOptOutOn) ? SELECT_OPTOUT_COVERAGE_WITH_CURSOR : SELECT_COVERAGE_WITH_CURSOR;
enrollment = template.query(queryWithCursor, sqlParameterSource,
CoverageServiceRepository::asMembership);
} else {
enrollment = template.query(SELECT_COVERAGE_WITHOUT_CURSOR, sqlParameterSource,
String queryWithoutCursor = (isOptOutOn) ? SELECT_OPTOUT_COVERAGE_WITHOUT_CURSOR : SELECT_COVERAGE_WITHOUT_CURSOR;
enrollment = template.query(queryWithoutCursor, sqlParameterSource,
CoverageServiceRepository::asMembership);
}
return enrollment;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package gov.cms.ab2d.coverage.repository;

import gov.cms.ab2d.common.feign.ContractFeignClient;
import gov.cms.ab2d.common.properties.PropertiesService;
import gov.cms.ab2d.coverage.model.CoveragePeriod;
import gov.cms.ab2d.coverage.model.CoverageSearch;
import gov.cms.ab2d.coverage.model.CoverageSearchEvent;
import gov.cms.ab2d.coverage.model.Identifiers;
import gov.cms.ab2d.coverage.service.CoverageService;
import gov.cms.ab2d.coverage.util.AB2DCoverageLocalstackContainer;
import gov.cms.ab2d.coverage.util.AB2DCoveragePostgressqlContainer;
import gov.cms.ab2d.coverage.util.CoverageDataSetup;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.test.context.TestPropertySource;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import javax.sql.DataSource;
import java.util.*;

import static gov.cms.ab2d.common.util.PropertyConstants.OPT_OUT_ON;

@SuppressWarnings("OptionalGetWithoutIsPresent")
@SpringBootTest
@EntityScan(basePackages = {"gov.cms.ab2d.common.model", "gov.cms.ab2d.coverage.model"})
@EnableJpaRepositories({"gov.cms.ab2d.common.repository", "gov.cms.ab2d.coverage.repository"})
@Testcontainers
@TestPropertySource(locations = "/application.coverage.properties")
@EnableFeignClients(clients = {ContractFeignClient.class})
class CoverageServiceRepositoryTest {

@Container
private static final PostgreSQLContainer postgreSQLContainer= new AB2DCoveragePostgressqlContainer();

@Container
private static final AB2DCoverageLocalstackContainer localstackContainer = new AB2DCoverageLocalstackContainer();

@Autowired
DataSource dataSource;

@Autowired
CoveragePeriodRepository coveragePeriodRepo;
@Autowired
CoverageSearchRepository coverageSearchRepo;
@Autowired
CoverageSearchEventRepository coverageSearchEventRepo;
@Autowired
CoverageService coverageService;
@Autowired
CoverageDataSetup dataSetup;
@Autowired
PropertiesService propertiesService;
@Mock
private PropertiesService mockPropertiesService;

private CoveragePeriod period1Jan;
private Set<Identifiers> results;

@BeforeEach
public void insertContractAndDefaultCoveragePeriod() {
// OptOut is disabled
Mockito.when(mockPropertiesService.isToggleOn(OPT_OUT_ON, false)).thenReturn(false);
period1Jan = dataSetup.createCoveragePeriod("TST-12", 1, 2020);

coverageService.submitSearch(period1Jan.getId(), "testing");
results = Set.of(createIdentifier(1231L),
createIdentifier(4561L), createIdentifier(7891L));

CoverageSearchEvent inProgress1 = startSearchAndPullEvent();
coverageService.insertCoverage(inProgress1.getId(), results);
}

@DisplayName("Calculate the number of beneficiaries when OptOut is disabled")
@Test
void countBeneficiariesByPeriodsWithoutOptOutTest() {
CoverageServiceRepository coverageServiceRepository = new CoverageServiceRepository(dataSource, coveragePeriodRepo, coverageSearchEventRepo, mockPropertiesService);

Assertions.assertEquals(3, coverageServiceRepository.countBeneficiariesByPeriods(List.of(period1Jan.getId()), "TST-12"));
}

@DisplayName("Calculate the number of beneficiaries when OptOut is enabled")
@Test
void countBeneficiariesByPeriodsWithOptOutTest() {
CoverageServiceRepository coverageServiceRepository = new CoverageServiceRepository(dataSource, coveragePeriodRepo, coverageSearchEventRepo, mockPropertiesService);

Mockito.when(mockPropertiesService.isToggleOn(OPT_OUT_ON, false)).thenReturn(true);
//The expected number is 3, and is the same as in previous test, since switching opt_out_flag from false to true is only available in OptOutLambda.
//Here all beneficiaries have opt_out_flag equals false by default.
Assertions.assertEquals(3, coverageServiceRepository.countBeneficiariesByPeriods(List.of(period1Jan.getId()), "TST-12"));
}

private Identifiers createIdentifier(Long suffix) {
return new Identifiers(suffix, "mbi-" + suffix, new LinkedHashSet<>());
}

private CoverageSearchEvent startSearchAndPullEvent() {
Optional<CoverageSearch> search = coverageSearchRepo.findFirstByOrderByCreatedAsc();
coverageSearchRepo.delete(search.get());
return coverageService.startSearch(search.get(), "testing").get().getCoverageSearchEvent();
}
}

0 comments on commit 93ffec7

Please sign in to comment.