diff --git a/.github/workflows/ci-java.yml b/.github/workflows/ci-java.yml index 96f7cb5338..2adaf29c43 100644 --- a/.github/workflows/ci-java.yml +++ b/.github/workflows/ci-java.yml @@ -68,7 +68,7 @@ jobs: cache: 'maven' - name: 'Run Maven Build' - run: mvn --threads 1C --quiet --batch-mode -Dmaven.build.cache.enabled=false -Dapidocgen.skip=false -DbfdOps.skip=false verify + run: mvn --threads 1C --batch-mode -Dmaven.build.cache.enabled=false -Dapidocgen.skip=false -DbfdOps.skip=false verify working-directory: ./apps # TODO: Conformance testing is currently missing from mvn-verify. BFD-3245 will re-examine conformance regression testing in BFD. diff --git a/apps/bfd-data-npi/pom.xml b/apps/bfd-data-npi/pom.xml index 5bf574133f..f383b8cc2d 100644 --- a/apps/bfd-data-npi/pom.xml +++ b/apps/bfd-data-npi/pom.xml @@ -70,6 +70,14 @@ com.google.guava guava + + org.projectlombok + lombok + + + com.fasterxml.jackson.core + jackson-databind + bfd-data-npi diff --git a/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/dto/NPIData.java b/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/dto/NPIData.java new file mode 100644 index 0000000000..8e3f427005 --- /dev/null +++ b/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/dto/NPIData.java @@ -0,0 +1,52 @@ +package gov.cms.bfd.data.npi.dto; + +import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** DTO used to supply the server with NPI enrichment information. */ +@Builder +@Getter +@AllArgsConstructor +@NoArgsConstructor +@JsonInclude(NON_NULL) +@JsonIgnoreProperties(ignoreUnknown = true) +public class NPIData { + /** Provider or Org npi. */ + String npi; + + /** Entity Type. Will be 1 or 2. */ + String entityTypeCode; + + /** Organization name. */ + String providerOrganizationName; + + /** Taxonomy code. */ + String taxonomyCode; + + /** Taxonomy display. */ + String taxonomyDisplay; + + /** Provider name prefix. */ + String providerNamePrefix; + + /** Provider first name. */ + String providerFirstName; + + /** Provider middle name. */ + String providerMiddleName; + + /** Provider last name. */ + String providerLastName; + + /** Provider suffix. */ + String providerNameSuffix; + + /** Provider credential. */ + String providerCredential; +} diff --git a/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookup.java b/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookup.java index 371565735e..ab5207b8b9 100644 --- a/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookup.java +++ b/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookup.java @@ -1,13 +1,19 @@ package gov.cms.bfd.data.npi.lookup; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.utility.App; +import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.zip.InflaterInputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,6 +27,9 @@ public class NPIOrgLookup { /** A field to return the production org lookup. */ private static NPIOrgLookup npiOrgLookupForProduction; + /** Zlib compression header. */ + private static final byte[] COMPRESSED_HEADER = {120, -100}; + /** * Factory method for creating a {@link NPIOrgLookup } for production that does not include the * fake org name. @@ -53,7 +62,7 @@ public NPIOrgLookup(Map npiOrgMap) { * @throws IOException if there is an issue reading file */ public NPIOrgLookup(InputStream npiDataStream) throws IOException { - npiOrgHashMap = readNPIOrgDataStream(npiDataStream); + npiOrgHashMap = readNPIOrgDataStream(new BufferedInputStream(npiDataStream)); } /** @@ -63,7 +72,7 @@ public NPIOrgLookup(InputStream npiDataStream) throws IOException { * @param npiNumber - npiNumber value in claim records * @return the npi org data display string */ - public Optional retrieveNPIOrgDisplay(Optional npiNumber) { + public Optional retrieveNPIOrgDisplay(Optional npiNumber) { /* * Handle bad data (e.g. our random test data) if npiNumber is empty */ @@ -72,8 +81,14 @@ public Optional retrieveNPIOrgDisplay(Optional npiNumber) { } if (npiOrgHashMap.containsKey(npiNumber.get())) { - String npiDisplay = npiOrgHashMap.get(npiNumber.get()); - return Optional.of(npiDisplay); + String json = npiOrgHashMap.get(npiNumber.get()); + ObjectMapper mapper = new ObjectMapper(); + try { + NPIData npiData = mapper.readValue(json, NPIData.class); + return Optional.of(npiData); + } catch (JsonProcessingException e) { + return Optional.empty(); + } } return Optional.empty(); @@ -88,29 +103,44 @@ public Optional retrieveNPIOrgDisplay(Optional npiNumber) { * @return the hashmapped for npis and the npi org names */ protected Map readNPIOrgDataStream(InputStream inputStream) throws IOException { - Map npiProcessedData = new HashMap(); - - try (final InputStream npiStream = inputStream; - final BufferedReader npiReader = new BufferedReader(new InputStreamReader(npiStream))) { - - String line = ""; - while ((line = npiReader.readLine()) != null) { - String npiDataColumns[] = line.split("\t"); - if (npiDataColumns.length == 2) { - npiProcessedData.put( - npiDataColumns[0].replace("\"", ""), npiDataColumns[1].replace("\"", "")); - } else if (npiDataColumns.length == 3) { - // three columns means it's a practitioner taxonomy - npiProcessedData.put( - npiDataColumns[0].replace("\"", ""), - npiDataColumns[1].replace("\"", "") + "\t" + npiDataColumns[2].replace("\"", "")); + Map npiProcessedData = new HashMap<>(); + // if the stream is compressed, we will have to use InflaterInputStream to read it. + boolean isCompressedStream = isStreamDeflated(inputStream); + String line; + try (final InputStream npiStream = + isCompressedStream ? new InflaterInputStream(inputStream) : inputStream; + final BufferedReader reader = new BufferedReader(new InputStreamReader(npiStream))) { + while ((line = reader.readLine()) != null) { + // the first part of the line will be the NPI, and the second part is the json. + String[] tsv = line.split("\t"); + if (tsv.length == 2) { + npiProcessedData.put(tsv[0], tsv[1]); } } } - return npiProcessedData; } + /** + * Checks if a stream is deflated. We will read the first two bytes of the stream to compare + * against the Zlib header (used by DeflaterOutputStream), then reset the stream back to the + * beginning. + * + * @param inputStream The stream to check + * @return true if the stream is deflated + * @throws IOException on read error. + */ + public boolean isStreamDeflated(InputStream inputStream) throws IOException { + // Mark the current position in the stream. + inputStream.mark(2); + // Read the first two bytes + byte[] bytes = new byte[2]; + int bytesRead = inputStream.read(bytes); + // Reset the stream to the marked position + inputStream.reset(); + return (bytesRead == 2 && Arrays.equals(bytes, COMPRESSED_HEADER)); + } + /** * Returns a inputStream from file name passed in. * diff --git a/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/utility/DataUtilityCommons.java b/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/utility/DataUtilityCommons.java index deebd7f19e..338c71c3d6 100644 --- a/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/utility/DataUtilityCommons.java +++ b/apps/bfd-data-npi/src/main/java/gov/cms/bfd/data/npi/utility/DataUtilityCommons.java @@ -1,16 +1,15 @@ package gov.cms.bfd.data.npi.utility; -import com.google.common.base.Strings; +import com.fasterxml.jackson.databind.ObjectMapper; +import gov.cms.bfd.data.npi.dto.NPIData; import java.io.BufferedOutputStream; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; -import java.io.OutputStreamWriter; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; @@ -27,6 +26,7 @@ import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; +import java.util.zip.DeflaterOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.apache.commons.csv.CSVFormat; @@ -59,6 +59,24 @@ public class DataUtilityCommons { /** Field for Entity Type Code in CSV. */ public static final String ENTITY_TYPE_CODE_FIELD = "Entity Type Code"; + /** Field for Provider Credential code in CSV. */ + private static final String PROVIDER_CREDENTIAL_FIELD = "Provider Credential Text"; + + /** Field for Provider first name in CSV. */ + private static final String PROVIDER_FIRST_NAME_FIELD = "Provider First Name"; + + /** Field for Provider middle name in CSV. */ + private static final String PROVIDER_MIDDLE_NAME_FIELD = "Provider Middle Name"; + + /** Field for Provider last name in CSV. */ + private static final String PROVIDER_LAST_NAME_FIELD = "Provider Last Name (Legal Name)"; + + /** Field for Provider prefix in CSV. */ + private static final String PROVIDER_PREFIX_FIELD = "Provider Name Prefix Text"; + + /** Field for Provider Suffix in CSV. */ + private static final String PROVIDER_SUFFIX_FIELD = "Provider Name Suffix Text"; + /** * Gets the org names from the npi file. * @@ -332,27 +350,42 @@ private static void convertNpiDataFile(Path convertedNpiDataFile, Path originalN BufferedReader reader = new BufferedReader(new InputStreamReader(is, inDec)); FileOutputStream fw = new FileOutputStream(convertedNpiDataFile.toFile().getAbsolutePath()); - BufferedWriter out = new BufferedWriter(new OutputStreamWriter(fw, outEnc))) { - CSVParser csvParser = + DeflaterOutputStream dos = new DeflaterOutputStream(fw); ) { + CSVParser csvParser = new CSVParser( reader, CSVFormat.DEFAULT.withFirstRecordAsHeader().withIgnoreHeaderCase().withTrim()); + ObjectMapper objectMapper = new ObjectMapper(); for (CSVRecord csvRecord : csvParser) { String orgName = csvRecord.get(PROVIDER_ORGANIZATION_NAME_FIELD); String npi = csvRecord.get(NPI_FIELD); String entityTypeCode = csvRecord.get(ENTITY_TYPE_CODE_FIELD); String taxonomyCode = csvRecord.get(TAXONOMY_CODE_FIELD); - // entity type code 2 is organization - if (!Strings.isNullOrEmpty(entityTypeCode)) { - if (Integer.parseInt(entityTypeCode) == 2) { - out.write(npi + "\t" + orgName); - out.newLine(); - } else if (!Strings.isNullOrEmpty(taxonomyCode)) { - out.write(npi + "\t" + taxonomyCode + "\t" + taxonomyMap.get(taxonomyCode)); - out.newLine(); - } - } + String providerFirstName = csvRecord.get(PROVIDER_FIRST_NAME_FIELD); + String providerMiddleName = csvRecord.get(PROVIDER_MIDDLE_NAME_FIELD); + String providerLastName = csvRecord.get(PROVIDER_LAST_NAME_FIELD); + String providerPrefix = csvRecord.get(PROVIDER_PREFIX_FIELD); + String providerSuffix = csvRecord.get(PROVIDER_SUFFIX_FIELD); + String providerCredential = csvRecord.get(PROVIDER_CREDENTIAL_FIELD); + NPIData npiData = + NPIData.builder() + .npi(npi) + .providerOrganizationName(orgName) + .entityTypeCode(entityTypeCode) + .taxonomyCode(taxonomyCode) + .taxonomyDisplay(taxonomyMap.get(taxonomyCode)) + .providerFirstName(providerFirstName) + .providerMiddleName(providerMiddleName) + .providerLastName(providerLastName) + .providerNamePrefix(providerPrefix) + .providerNameSuffix(providerSuffix) + .providerCredential(providerCredential) + .build(); + String json = objectMapper.writeValueAsString(npiData); + dos.write((npi + "\t" + json).getBytes()); + dos.write("\n".getBytes()); } + dos.close(); } } diff --git a/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookupE2E.java b/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookupE2E.java index 024ab2c247..969626e406 100644 --- a/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookupE2E.java +++ b/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookupE2E.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import gov.cms.bfd.data.npi.dto.NPIData; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -17,7 +18,7 @@ public class NPIOrgLookupE2E { NPIOrgLookup npiOrgDataLookup; /** Global variable for npiOrgDisplay. */ - Optional npiOrgDisplay; + Optional npiOrgDisplay; /** Global variable for NPI taxonomy. */ Optional npiTaxonomyDisplay; @@ -44,15 +45,34 @@ public class NPIOrgLookupE2E { @BeforeEach void setup() throws IOException { StringBuilder initialString = new StringBuilder(); - initialString.append(npiOrgNumber); - initialString.append("\t"); - initialString.append(npiOrgName); + initialString.append( + String.format( + "%s" + + "\t" + + " {" + + " \"npi\": \"%s\"," + + " \"entityTypeCode\": \"2\"," + + " \"providerOrganizationName\": \"%s\"" + + " }", + npiOrgNumber, npiOrgNumber, npiOrgName)); initialString.append("\n"); - initialString.append(practitionerNPI); - initialString.append("\t"); - initialString.append(taxononomyCode); - initialString.append("\t"); - initialString.append(taxonomyDisplay); + initialString.append( + String.format( + "%s" + + "\t" + + " {" + + " \"npi\": \"%s\"," + + " \"taxonomyCode\": \"%s\"," + + " \"taxonomyDisplay\": \"%s\"," + + " \"providerNamePrefix\": \"Dr\"," + + " \"providerFirstName\": \"Stephen\"," + + " \"providerMiddleName\": \"J.\"," + + " \"providerLastName\": \"Smith\"," + + " \"providerNameSuffix\": \"Sr.\"," + + " \"providerCredential\": \"MD\"" + + " }", + practitionerNPI, practitionerNPI, taxononomyCode, taxonomyDisplay)); + InputStream npiDataStream = new ByteArrayInputStream(initialString.toString().getBytes()); npiOrgDataLookup = new NPIOrgLookup(npiDataStream); npiOrgDisplay = Optional.empty(); @@ -63,7 +83,15 @@ void setup() throws IOException { @Test public void shouldCorrectlyReturnNpiNameObtainedFromFileStream() throws IOException { npiOrgDisplay = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of(npiOrgNumber)); - assertEquals(npiOrgName, npiOrgDisplay.get()); + assertEquals(npiOrgName, npiOrgDisplay.get().getProviderOrganizationName()); + } + + /** End to End test for NPI Taxononomy Dislplay. */ + @Test + public void shouldCorrectlyReturnTaxonomyForNPI() throws IOException { + npiOrgDisplay = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of(practitionerNPI)); + assertEquals(taxononomyCode, npiOrgDisplay.get().getTaxonomyCode()); + assertEquals(taxonomyDisplay, npiOrgDisplay.get().getTaxonomyDisplay()); } /** End to End test for NPI Taxononomy Dislplay. */ diff --git a/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookupTest.java b/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookupTest.java index 622f79e44f..1664210c61 100644 --- a/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookupTest.java +++ b/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/lookup/NPIOrgLookupTest.java @@ -2,6 +2,8 @@ import static org.junit.jupiter.api.Assertions.*; +import com.fasterxml.jackson.databind.ObjectMapper; +import gov.cms.bfd.data.npi.dto.NPIData; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; @@ -29,8 +31,34 @@ public class NPIOrgLookupTest { /** A fake org name display that is associated with the FAKE_NPI_ORG_NAME. */ public static final String FAKE_NPI_ORG_NAME = "Fake ORG Name"; - /** A fake taxonomy to use with FAKE_PRACTITIONER_NPI. */ - public static final String FAKE_TAXONOMY = "0000000X\tFake Taxonomy"; + /** A fake taxonomy code. */ + public static final String FAKE_TAXONOMY_CODE = "0000000X"; + + /** A fake taxonomy display. */ + public static final String FAKE_TAXONOMY_DISPLAY = "Fake Taxonomy"; + + /** Test JSON, which will be deserialized. */ + private static final String testJson = + String.format( + "%s" + + "\t" + + " \"npi\": \"%s\"," + + " \"entityTypeCode\": \"2\"," + + " \"providerOrganizationName\": \"%s," + + " \"taxonomyCode\": \"%s\"," + + " \"taxonomyDisplay\": \"%s\"," + + " \"providerNamePrefix\": \"Dr\"," + + " \"providerFirstName\": \"Stephen\"," + + " \"providerMiddleName\", \"J.\"," + + " \"providerLastName\": \"Smith\"," + + " \"providerNameSuffix\": \"Sr.\"," + + " \"providerCredential\": \"MD\"" + + " }", + FAKE_NPI_NUMBER, + FAKE_NPI_NUMBER, + FAKE_NPI_ORG_NAME, + FAKE_TAXONOMY_CODE, + FAKE_TAXONOMY_DISPLAY); /** Setup Before Each test method. */ @BeforeEach @@ -38,46 +66,64 @@ void setup() throws IOException { npiOrgDisplay = Optional.empty(); Map npiOrgHashMap = new HashMap<>(); - npiOrgHashMap.put(FAKE_NPI_NUMBER, FAKE_NPI_ORG_NAME); - npiOrgHashMap.put(FAKE_PRACTITIONER_NPI, FAKE_TAXONOMY); - + NPIData fakeNpiData = + NPIData.builder() + .npi(FAKE_NPI_NUMBER) + .entityTypeCode("2") + .providerOrganizationName(FAKE_NPI_ORG_NAME) + .taxonomyCode(FAKE_TAXONOMY_CODE) + .taxonomyDisplay(FAKE_TAXONOMY_DISPLAY) + .providerNamePrefix("Dr.") + .providerFirstName("Stephen") + .providerMiddleName("J.") + .providerLastName("Smith") + .providerNameSuffix("Sr.") + .providerCredential("MD") + .build(); + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(fakeNpiData); + npiOrgHashMap.put(FAKE_NPI_NUMBER, json); npiOrgDataLookup = new NPIOrgLookup(npiOrgHashMap); } /** Should Return taxonomy. */ @Test public void shouldReturnTaxonomy() { - npiOrgDisplay = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of(FAKE_PRACTITIONER_NPI)); - assertTrue(npiOrgDisplay.isPresent()); - assertEquals(FAKE_TAXONOMY, npiOrgDisplay.get()); + Optional npiData = + npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of(FAKE_NPI_NUMBER)); + assertTrue(npiData.isPresent()); + assertEquals(FAKE_TAXONOMY_CODE, npiData.get().getTaxonomyCode()); + assertEquals(FAKE_TAXONOMY_DISPLAY, npiData.get().getTaxonomyDisplay()); } /** Return Fake NPI Org. */ @Test public void shouldReturnFakeOrgData() throws IOException { - npiOrgDisplay = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of(FAKE_NPI_NUMBER)); - assertNotEquals(null, npiOrgDisplay.get()); + Optional npiData = + npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of(FAKE_NPI_NUMBER)); + assertTrue(npiData.isPresent()); } /** Return Fake NPI Org Name. */ @Test public void shouldReturnFakeNPIOrgName() throws IOException { - npiOrgDisplay = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of(FAKE_NPI_NUMBER)); - assertEquals(FAKE_NPI_ORG_NAME, npiOrgDisplay.get()); + Optional npiData = + npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of(FAKE_NPI_NUMBER)); + assertEquals(FAKE_NPI_ORG_NAME, npiData.get().getProviderOrganizationName()); } /** Should not return Org Name and NPI Number is empty. */ @Test public void shouldNotReturnWhenNPINumberIsEmpty() throws IOException { - npiOrgDisplay = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.empty()); - assertFalse(npiOrgDisplay.isPresent()); + Optional npiData = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.empty()); + assertFalse(npiData.isPresent()); } /** Should not return Org Name and NPI Number is empty string. */ @Test public void shouldNotReturnWhenNPINumberIEmptyString() throws IOException { - npiOrgDisplay = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of("")); - assertFalse(npiOrgDisplay.isPresent()); + Optional npiData = npiOrgDataLookup.retrieveNPIOrgDisplay(Optional.of("")); + assertFalse(npiData.isPresent()); } /** @@ -86,12 +132,11 @@ public void shouldNotReturnWhenNPINumberIEmptyString() throws IOException { */ @Test public void shouldReturnMapWhenInputStreamIsFormattedCorrectly() throws IOException { - String initialString = FAKE_NPI_NUMBER + "\t" + FAKE_NPI_ORG_NAME; - InputStream targetStream = new ByteArrayInputStream(initialString.getBytes()); + InputStream targetStream = new ByteArrayInputStream(testJson.getBytes()); Map npiOrgMap = npiOrgDataLookup.readNPIOrgDataStream(targetStream); assertFalse(isNullOrEmptyMap(npiOrgMap)); - assertEquals(FAKE_NPI_ORG_NAME, npiOrgMap.get(FAKE_NPI_NUMBER)); + assertTrue(npiOrgMap.containsKey(FAKE_NPI_NUMBER)); } /** diff --git a/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/utility/DataUtilityCommonsTest.java b/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/utility/DataUtilityCommonsTest.java index d56126b741..e83715cd19 100644 --- a/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/utility/DataUtilityCommonsTest.java +++ b/apps/bfd-data-npi/src/test/java/gov/cms/bfd/data/npi/utility/DataUtilityCommonsTest.java @@ -1,7 +1,6 @@ package gov.cms.bfd.data.npi.utility; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; import java.io.IOException; import java.util.HashMap; diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/CarrierClaimTransformerV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/CarrierClaimTransformerV2.java index 18aabb3d6c..c0596ab8fc 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/CarrierClaimTransformerV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/CarrierClaimTransformerV2.java @@ -6,6 +6,7 @@ import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; import gov.cms.bfd.data.fda.lookup.FdaDrugCodeDisplayLookup; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.CarrierClaim; @@ -251,9 +252,6 @@ private ExplanationOfBenefit transformClaim(CarrierClaim claimGroup, boolean inc // Update the responsible flag careTeam.setResponsible(true); - // PRVDR_SPCLTY => ExplanationOfBenefit.careTeam.qualification - TransformerUtilsV2.addCareTeamQualification( - careTeam, eob, CcwCodebookVariable.PRVDR_SPCLTY, line.getProviderSpecialityCode()); // CARR_LINE_PRVDR_TYPE_CD => ExplanationOfBenefit.careTeam.extension TransformerUtilsV2.addCareTeamExtension( @@ -275,7 +273,9 @@ private ExplanationOfBenefit transformClaim(CarrierClaim claimGroup, boolean inc C4BBPractitionerIdentifierType.NPI, C4BBClaimProfessionalAndNonClinicianCareTeamRole.PRIMARY, line.getOrganizationNpi().get(), - npiOrgLookup.retrieveNPIOrgDisplay(line.getOrganizationNpi())); + npiOrgLookup + .retrieveNPIOrgDisplay(line.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName)); } // CARR_LINE_RDCD_PMT_PHYS_ASTN_C => ExplanationOfBenefit.item.adjudication diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/CoverageTransformerV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/CoverageTransformerV2.java index a6b6b4601f..d214e0174e 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/CoverageTransformerV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/CoverageTransformerV2.java @@ -385,6 +385,27 @@ private Coverage transformPartC(Beneficiary beneficiary, Profile profile) { Optional.empty()); } + int month = Calendar.getInstance().get(Calendar.MONTH); + String contractAndPbpID = + concatenateContractAndPbp( + getPartCContractNumber(beneficiary, month), getPartCPbpNumber(beneficiary, month)); + + if (profile.equals(Profile.C4DIC)) { + // Hide resource Part C when Contract ID or PBP ID is null + if (contractAndPbpID == null) { + return null; + } + createCoverageClass(coverage, CoverageClass.PLAN, contractAndPbpID, Optional.empty()); + } else { + createCoverageClass( + coverage, CoverageClass.GROUP, TransformerConstants.COVERAGE_PLAN, Optional.empty()); + createCoverageClass( + coverage, + CoverageClass.PLAN, + TransformerConstants.COVERAGE_PLAN_PART_C, + Optional.empty()); + } + // update Coverage.meta.lastUpdated TransformerUtilsV2.setLastUpdated(coverage, beneficiary.getLastUpdated()); @@ -509,6 +530,28 @@ private Coverage transformPartD(Beneficiary beneficiary, Profile profile) { Optional.empty()); } + int month = Calendar.getInstance().get(Calendar.MONTH); + + String contractAndPbpID = + concatenateContractAndPbp( + getPartDContractNumber(beneficiary, month), getPartDPbpNumber(beneficiary, month)); + + if (profile.equals(Profile.C4DIC)) { + // Hide resource Part D when Contract ID or PBP ID is null + if (contractAndPbpID == null) { + return null; + } + createCoverageClass(coverage, CoverageClass.PLAN, contractAndPbpID, Optional.empty()); + } else { + createCoverageClass( + coverage, CoverageClass.GROUP, TransformerConstants.COVERAGE_PLAN, Optional.empty()); + createCoverageClass( + coverage, + CoverageClass.PLAN, + TransformerConstants.COVERAGE_PLAN_PART_D, + Optional.empty()); + } + // update Coverage.meta.lastUpdated TransformerUtilsV2.setLastUpdated(coverage, beneficiary.getLastUpdated()); diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/DMEClaimTransformerV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/DMEClaimTransformerV2.java index df02d767f5..71a0dc8956 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/DMEClaimTransformerV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/DMEClaimTransformerV2.java @@ -244,10 +244,6 @@ private void handleClaimLines( CareTeamComponent careTeam = performing.get(); performing.get().setResponsible(true); - // PRVDR_SPCLTY => ExplanationOfBenefit.careTeam.qualification - TransformerUtilsV2.addCareTeamQualification( - careTeam, eob, CcwCodebookVariable.PRVDR_SPCLTY, line.getProviderSpecialityCode()); - // PRTCPTNG_IND_CD => ExplanationOfBenefit.careTeam.extension TransformerUtilsV2.addCareTeamExtension( CcwCodebookVariable.PRTCPTNG_IND_CD, diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/HHAClaimTransformerV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/HHAClaimTransformerV2.java index 42da112fad..a019650335 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/HHAClaimTransformerV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/HHAClaimTransformerV2.java @@ -5,6 +5,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.HHAClaim; @@ -154,7 +155,9 @@ private ExplanationOfBenefit transformClaim(HHAClaim claimGroup) { TransformerUtilsV2.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/HospiceClaimTransformerV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/HospiceClaimTransformerV2.java index e804570141..a0d8583d75 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/HospiceClaimTransformerV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/HospiceClaimTransformerV2.java @@ -5,6 +5,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.HospiceClaim; @@ -174,7 +175,9 @@ private ExplanationOfBenefit transformClaim(HospiceClaim claimGroup) { TransformerUtilsV2.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/InpatientClaimTransformerV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/InpatientClaimTransformerV2.java index e188bf36dd..a5c39ac440 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/InpatientClaimTransformerV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/InpatientClaimTransformerV2.java @@ -5,6 +5,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.InpatientClaim; @@ -292,7 +293,9 @@ private ExplanationOfBenefit transformClaim(InpatientClaim claimGroup) { TransformerUtilsV2.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/OutpatientClaimTransformerV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/OutpatientClaimTransformerV2.java index db8b2a9303..eef76856ed 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/OutpatientClaimTransformerV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/OutpatientClaimTransformerV2.java @@ -6,6 +6,7 @@ import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; import gov.cms.bfd.data.fda.lookup.FdaDrugCodeDisplayLookup; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.InpatientClaim; @@ -223,7 +224,9 @@ private ExplanationOfBenefit transformClaim(OutpatientClaim claimGroup) { TransformerUtilsV2.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/SNFClaimTransformerV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/SNFClaimTransformerV2.java index e15f9830a2..b695c8c579 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/SNFClaimTransformerV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/SNFClaimTransformerV2.java @@ -6,6 +6,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.SNFClaim; @@ -300,7 +301,9 @@ private ExplanationOfBenefit transformClaim(SNFClaim claimGroup) { TransformerUtilsV2.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/TransformerUtilsV2.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/TransformerUtilsV2.java index c53766ba3a..47e28b10d1 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/TransformerUtilsV2.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/r4/providers/TransformerUtilsV2.java @@ -9,6 +9,7 @@ import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import com.google.common.base.Strings; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.model.codebook.data.CcwCodebookMissingVariable; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.codebook.model.CcwCodebookInterface; @@ -1935,7 +1936,7 @@ private static CareTeamComponent addCareTeamPractitioner( String roleSystem, String roleCode, String roleDisplay, - Optional taxonomy) { + Optional taxonomy) { // Try to find a matching pre-existing entry. CareTeamComponent careTeamEntry = eob.getCareTeam().stream() @@ -1967,17 +1968,11 @@ private static CareTeamComponent addCareTeamPractitioner( careTeamEntry.setProvider(createPractitionerIdentifierReference(type, practitionerIdValue)); if (taxonomy.isPresent()) { - String[] taxonomyArray = taxonomy.get().split("\t"); - if (taxonomyArray.length == 2) { - String taxonomyCode = taxonomyArray[0]; - String taxonomyDisplay = taxonomyArray[1]; - addCodingToCodeableConcept( - careTeamEntry.getQualification(), - TransformerConstants.NUCC_TAXONOMY_SYSTEM, - null, - taxonomyDisplay, - taxonomyCode); - } + String taxonomyCode = taxonomy.get().getTaxonomyCode(); + String taxonomyDisplay = taxonomy.get().getTaxonomyDisplay(); + careTeamEntry.setQualification( + createCodeableConcept( + TransformerConstants.NUCC_TAXONOMY_SYSTEM, null, taxonomyDisplay, taxonomyCode)); } CodeableConcept careTeamRoleConcept = createCodeableConcept(roleSystem, roleCode); careTeamRoleConcept.getCodingFirstRep().setDisplay(roleDisplay); @@ -2488,7 +2483,7 @@ static void mapEobCommonGroupCarrierDME( BigDecimal beneficiaryPartBDeductAmount, String paymentDenialCode, Optional referringPhysicianNpi, - Optional referringPhysicianTaxonomy, + Optional referringPhysicianTaxonomy, Optional referringPhysicianUpin, Optional providerAssignmentIndicator, BigDecimal providerPaymentAmount, @@ -2953,7 +2948,7 @@ static Optional addCareTeamMember( C4BBPractitionerIdentifierType type, C4BBClaimInstitutionalCareTeamRole role, Optional id, - Optional taxonomy) { + Optional taxonomy) { return id.map( i -> addCareTeamPractitioner( @@ -2998,7 +2993,7 @@ static Optional addCareTeamMember( C4BBPractitionerIdentifierType type, C4BBClaimInstitutionalCareTeamRole role, Optional id, - Optional taxonomy) { + Optional taxonomy) { return addCareTeamMember(eob, null, type, role, id, taxonomy); } @@ -3022,7 +3017,7 @@ static Optional addCareTeamMember( C4BBPractitionerIdentifierType type, C4BBClaimPharmacyTeamRole role, Optional id, - Optional taxonomy) { + Optional taxonomy) { return id.map( i -> addCareTeamPractitioner( @@ -3081,7 +3076,7 @@ static Optional addCareTeamMember( C4BBPractitionerIdentifierType type, C4BBClaimProfessionalAndNonClinicianCareTeamRole role, Optional id, - Optional taxonomy) { + Optional taxonomy) { return id.map( i -> addCareTeamPractitioner( @@ -3165,7 +3160,7 @@ static Optional addCareTeamMember( C4BBPractitionerIdentifierType type, C4BBClaimProfessionalAndNonClinicianCareTeamRole role, Optional id, - Optional taxonomy) { + Optional taxonomy) { return addCareTeamMember(eob, null, type, role, id, taxonomy); } @@ -3191,11 +3186,11 @@ static Optional addCareTeamMember( static void mapCareTeam( ExplanationOfBenefit eob, Optional attendingPhysicianNpi, - Optional attendingPhysicianTaxonomy, + Optional attendingPhysicianTaxonomy, Optional operatingPhysicianNpi, - Optional operatingPhysicianTaxonomy, + Optional operatingPhysicianTaxonomy, Optional otherPhysicianNpi, - Optional otherPhysicianTaxonomy, + Optional otherPhysicianTaxonomy, Optional attendingPhysicianUpin, Optional operatingPhysicianUpin, Optional otherPhysicianUpin) { diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/CarrierClaimTransformer.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/CarrierClaimTransformer.java index b9ab773ff8..51017a9606 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/CarrierClaimTransformer.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/CarrierClaimTransformer.java @@ -7,6 +7,7 @@ import com.google.common.base.Strings; import com.newrelic.api.agent.Trace; import gov.cms.bfd.data.fda.lookup.FdaDrugCodeDisplayLookup; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.CarrierClaim; @@ -201,7 +202,9 @@ private ExplanationOfBenefit transformClaim(CarrierClaim claimGroup, boolean inc performingCareTeamMember, TransformerConstants.CODING_NPI_US, TransformerConstants.CODING_NPI_US, - npiOrgLookup.retrieveNPIOrgDisplay(claimLine.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimLine.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimLine.getOrganizationNpi().get()); } } diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/HHAClaimTransformer.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/HHAClaimTransformer.java index 45b16c161a..3de15fd498 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/HHAClaimTransformer.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/HHAClaimTransformer.java @@ -5,6 +5,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.HHAClaim; @@ -111,7 +112,9 @@ private ExplanationOfBenefit transformClaim(HHAClaim claimGroup) { TransformerUtils.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/HospiceClaimTransformer.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/HospiceClaimTransformer.java index 529ea9e2ed..5c28d7262f 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/HospiceClaimTransformer.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/HospiceClaimTransformer.java @@ -5,6 +5,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.HospiceClaim; @@ -131,7 +132,9 @@ private ExplanationOfBenefit transformClaim(HospiceClaim claimGroup) { TransformerUtils.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/InpatientClaimTransformer.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/InpatientClaimTransformer.java index 9a64b9a99f..ebe4ed4ae8 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/InpatientClaimTransformer.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/InpatientClaimTransformer.java @@ -5,6 +5,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.InpatientClaim; @@ -217,7 +218,9 @@ private ExplanationOfBenefit transformClaim(InpatientClaim claimGroup) { TransformerUtils.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/OutpatientClaimTransformer.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/OutpatientClaimTransformer.java index e1b87c354c..fb3b2ac4f6 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/OutpatientClaimTransformer.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/OutpatientClaimTransformer.java @@ -5,6 +5,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.InpatientClaim; @@ -153,7 +154,9 @@ private ExplanationOfBenefit transformClaim(OutpatientClaim claimGroup) { TransformerUtils.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/SNFClaimTransformer.java b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/SNFClaimTransformer.java index 58cd9e2011..adc0f99aad 100644 --- a/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/SNFClaimTransformer.java +++ b/apps/bfd-server/bfd-server-war/src/main/java/gov/cms/bfd/server/war/stu3/providers/SNFClaimTransformer.java @@ -6,6 +6,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import com.newrelic.api.agent.Trace; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.SNFClaim; @@ -187,7 +188,9 @@ private ExplanationOfBenefit transformClaim(SNFClaim claimGroup) { TransformerUtils.mapEobCommonGroupInpOutHHAHospiceSNF( eob, claimGroup.getOrganizationNpi(), - npiOrgLookup.retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()), + npiOrgLookup + .retrieveNPIOrgDisplay(claimGroup.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claimGroup.getClaimFacilityTypeCode(), claimGroup.getClaimFrequencyCode(), claimGroup.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/NPIOrgLookupIT.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/NPIOrgLookupIT.java index 35d7ec82cc..fcfe93df8f 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/NPIOrgLookupIT.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/NPIOrgLookupIT.java @@ -3,6 +3,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import java.io.IOException; import java.util.Optional; @@ -14,15 +15,16 @@ public class NPIOrgLookupIT { @Test public void VerifyAValidNPIOrg() throws IOException { NPIOrgLookup npiOrgLookup = NPIOrgLookup.createNpiOrgLookup(); - Optional orgDisplay = npiOrgLookup.retrieveNPIOrgDisplay(Optional.of("1497758544")); - assertEquals("CUMBERLAND COUNTY HOSPITAL SYSTEM, INC", orgDisplay.get()); + Optional orgDisplay = npiOrgLookup.retrieveNPIOrgDisplay(Optional.of("1497758544")); + assertEquals( + "CUMBERLAND COUNTY HOSPITAL SYSTEM, INC", orgDisplay.get().getProviderOrganizationName()); } /** Verifies that it returns a empty string for a non valid npiOrg Number. */ @Test public void VerifyANonValidNPIOrgReturnsEmpty() throws IOException { NPIOrgLookup npiOrgLookup = NPIOrgLookup.createNpiOrgLookup(); - Optional orgDisplay = npiOrgLookup.retrieveNPIOrgDisplay(Optional.of("-497758544")); + Optional orgDisplay = npiOrgLookup.retrieveNPIOrgDisplay(Optional.of("-497758544")); assertTrue(orgDisplay.isEmpty()); } } diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/CarrierClaimTransformerV2Test.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/CarrierClaimTransformerV2Test.java index 9a7bb7475b..8827b7fe98 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/CarrierClaimTransformerV2Test.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/CarrierClaimTransformerV2Test.java @@ -784,11 +784,7 @@ public void shouldHaveCareTeamMembers() { new Coding() .setSystem("http://nucc.org/provider-taxonomy") .setDisplay("Health Care") - .setCode("390200000X"), - new Coding() - .setSystem("https://bluebutton.cms.gov/resources/variables/prvdr_spclty") - .setDisplay("Optometrist") - .setCode("41")))); + .setCode("390200000X")))); compare3.addExtension( "https://bluebutton.cms.gov/resources/variables/carr_line_prvdr_type_cd", new Coding() diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/DMEClaimTransformerV2Test.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/DMEClaimTransformerV2Test.java index 67b95bcaa1..6d70b3d0c3 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/DMEClaimTransformerV2Test.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/DMEClaimTransformerV2Test.java @@ -14,6 +14,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import gov.cms.bfd.data.fda.lookup.FdaDrugCodeDisplayLookup; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.DMEClaim; @@ -115,11 +116,17 @@ public DMEClaim generateClaim() throws FHIRException { */ @BeforeEach public void before() throws IOException { + NPIData npiData = + NPIData.builder() + .npi("0000000000") + .taxonomyCode("207X00000X") + .taxonomyDisplay("Orthopaedic Surgery") + .build(); + when(metricRegistry.timer(any())).thenReturn(metricsTimer); when(metricsTimer.time()).thenReturn(metricsTimerContext); FdaDrugCodeDisplayLookup fdaDrugCodeDisplayLookup = RDATestUtils.fdaFakeDrugCodeDisplayLookup(); - when(mockNpiOrgLookup.retrieveNPIOrgDisplay(any())) - .thenReturn(Optional.of("207X00000X\tOrthopaedic Surgery")); + when(mockNpiOrgLookup.retrieveNPIOrgDisplay(any())).thenReturn(Optional.of(npiData)); dmeClaimTransformer = new DMEClaimTransformerV2(metricRegistry, fdaDrugCodeDisplayLookup, mockNpiOrgLookup); claim = generateClaim(); diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/PartDEventTransformerV2Test.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/PartDEventTransformerV2Test.java index efbb5dd7ae..b47f1f0010 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/PartDEventTransformerV2Test.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/PartDEventTransformerV2Test.java @@ -13,6 +13,7 @@ import com.codahale.metrics.Timer; import gov.cms.bfd.data.fda.lookup.FdaDrugCodeDisplayLookup; import gov.cms.bfd.data.fda.utility.App; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.PartDEvent; @@ -115,10 +116,16 @@ public PartDEvent generateClaim() throws FHIRException { */ @BeforeEach public void before() throws IOException { + NPIData npiData = + NPIData.builder() + .npi("0000000000") + .taxonomyCode("207X00000X") + .taxonomyDisplay("Orthopaedic Surgery") + .build(); + when(metricRegistry.timer(any())).thenReturn(metricsTimer); when(metricsTimer.time()).thenReturn(metricsTimerContext); - when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())) - .thenReturn(Optional.of("207X00000X\tOrthopaedic Surgery")); + when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.of(npiData)); InputStream npiDataStream = Thread.currentThread() .getContextClassLoader() diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/PatientClaimsEobTaskTransformerV2Test.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/PatientClaimsEobTaskTransformerV2Test.java index aac96fe8e3..733311d007 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/PatientClaimsEobTaskTransformerV2Test.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/PatientClaimsEobTaskTransformerV2Test.java @@ -18,6 +18,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import gov.cms.bfd.data.fda.lookup.FdaDrugCodeDisplayLookup; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.rif.entities.CarrierClaim; import gov.cms.bfd.model.rif.entities.DMEClaim; @@ -117,15 +118,20 @@ class PatientClaimsEobTaskTransformerV2Test { @BeforeEach public void setup() { setupEntities(); - + NPIData npiData = + NPIData.builder() + .npi("0000000000") + .taxonomyCode("207X00000X") + .taxonomyDisplay("Orthopaedic Surgery") + .build(); // metrics mocking when(metricRegistry.timer(any())).thenReturn(metricsTimer); when(metricsTimer.time()).thenReturn(metricsTimerContext); // NPI and FDA drug mocking - when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.of("JUNK")); + when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.empty()); when(mockDrugDisplayLookup.retrieveFDADrugCodeDisplay(Optional.empty())).thenReturn("JUNK"); when(mockNpiTaxonomyLookup.retrieveNPIOrgDisplay(Optional.empty())) - .thenReturn(Optional.of("207X00000X\tOrthopaedic Surgery")); + .thenReturn(Optional.of(npiData)); // used to get the claim type in transformer utils CodeableConcept mockConcept = mock(CodeableConcept.class); Coding mockCoding = mock(Coding.class); diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/R4ExplanationOfBenefitResourceProviderTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/R4ExplanationOfBenefitResourceProviderTest.java index 790f1b44bc..ad81653ad7 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/R4ExplanationOfBenefitResourceProviderTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/r4/providers/R4ExplanationOfBenefitResourceProviderTest.java @@ -169,7 +169,7 @@ public void setup() { when(metricsTimer.time()).thenReturn(metricsTimerContext); // NPI and FDA drug mocking - when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.of("JUNK")); + // when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.of("JUNK")); when(mockDrugDisplayLookup.retrieveFDADrugCodeDisplay(Optional.empty())).thenReturn("JUNK"); when(mockCarrierClaimTransformer.transform(any(), anyBoolean())).thenReturn(testEob); diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/CarrierClaimTransformerTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/CarrierClaimTransformerTest.java index 55f76a61f8..e1eeed3f54 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/CarrierClaimTransformerTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/CarrierClaimTransformerTest.java @@ -14,6 +14,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; import gov.cms.bfd.data.fda.lookup.FdaDrugCodeDisplayLookup; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.CarrierClaim; @@ -70,10 +71,18 @@ public final class CarrierClaimTransformerTest { /** One-time setup of objects that are normally injected. */ @BeforeEach protected void setup() { + NPIData npiData = + NPIData.builder() + .npi("0000000000") + .providerOrganizationName(RDATestUtils.FAKE_NPI_ORG_NAME) + .taxonomyCode("207X00000X") + .taxonomyDisplay("Orthopaedic Surgery") + .build(); + when(metricRegistry.timer(any())).thenReturn(metricsTimer); when(metricsTimer.time()).thenReturn(metricsTimerContext); when(npiOrgLookup.retrieveNPIOrgDisplay(Optional.of(anyString()))) - .thenReturn(Optional.of(RDATestUtils.FAKE_NPI_ORG_NAME)); + .thenReturn(Optional.of(npiData)); when(drugDisplayLookup.retrieveFDADrugCodeDisplay(Optional.of(anyString()))) .thenReturn("UNKNOWN"); diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/ExplanationOfBenefitResourceProviderTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/ExplanationOfBenefitResourceProviderTest.java index f261a925ec..a341c6d2d3 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/ExplanationOfBenefitResourceProviderTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/ExplanationOfBenefitResourceProviderTest.java @@ -169,7 +169,8 @@ public void setup() { when(metricsTimer.time()).thenReturn(metricsTimerContext); // NPI and FDA drug mocking - when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.of("JUNK")); + // + // when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.of("JUNK")); when(mockDrugDisplayLookup.retrieveFDADrugCodeDisplay(Optional.empty())).thenReturn("JUNK"); when(mockCarrierClaimTransformer.transform(any(), anyBoolean())).thenReturn(testEob); diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/HHAClaimTransformerTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/HHAClaimTransformerTest.java index 7f61ffcef4..e4cba344eb 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/HHAClaimTransformerTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/HHAClaimTransformerTest.java @@ -8,6 +8,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.HHAClaim; @@ -155,7 +156,9 @@ public static void assertMatches(HHAClaim claim, ExplanationOfBenefit eob) TransformerTestUtils.assertEobCommonGroupInpOutHHAHospiceSNFEquals( eob, claim.getOrganizationNpi(), - localNpiLookup.retrieveNPIOrgDisplay(claim.getOrganizationNpi()), + localNpiLookup + .retrieveNPIOrgDisplay(claim.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claim.getClaimFacilityTypeCode(), claim.getClaimFrequencyCode(), claim.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/HospiceClaimTransformerTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/HospiceClaimTransformerTest.java index d0cd9289ad..d485741acd 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/HospiceClaimTransformerTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/HospiceClaimTransformerTest.java @@ -8,6 +8,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.HospiceClaim; @@ -162,7 +163,9 @@ static void assertMatches(HospiceClaim claim, ExplanationOfBenefit eob) TransformerTestUtils.assertEobCommonGroupInpOutHHAHospiceSNFEquals( eob, claim.getOrganizationNpi(), - localNpiLookup.retrieveNPIOrgDisplay(claim.getOrganizationNpi()), + localNpiLookup + .retrieveNPIOrgDisplay(claim.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claim.getClaimFacilityTypeCode(), claim.getClaimFrequencyCode(), claim.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/InpatientClaimTransformerTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/InpatientClaimTransformerTest.java index cc7207bb9a..7ada19bde8 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/InpatientClaimTransformerTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/InpatientClaimTransformerTest.java @@ -8,6 +8,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.InpatientClaim; @@ -230,7 +231,9 @@ static void assertMatches(InpatientClaim claim, ExplanationOfBenefit eob) TransformerTestUtils.assertEobCommonGroupInpOutHHAHospiceSNFEquals( eob, claim.getOrganizationNpi(), - localNpiLookup.retrieveNPIOrgDisplay(claim.getOrganizationNpi()), + localNpiLookup + .retrieveNPIOrgDisplay(claim.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claim.getClaimFacilityTypeCode(), claim.getClaimFrequencyCode(), claim.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/OutpatientClaimTransformerTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/OutpatientClaimTransformerTest.java index a4d50820f3..3ee026f495 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/OutpatientClaimTransformerTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/OutpatientClaimTransformerTest.java @@ -9,6 +9,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.OutpatientClaim; @@ -178,7 +179,9 @@ static void assertMatches(OutpatientClaim claim, ExplanationOfBenefit eob) TransformerTestUtils.assertEobCommonGroupInpOutHHAHospiceSNFEquals( eob, claim.getOrganizationNpi(), - localNpiLookup.retrieveNPIOrgDisplay(claim.getOrganizationNpi()), + localNpiLookup + .retrieveNPIOrgDisplay(claim.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claim.getClaimFacilityTypeCode(), claim.getClaimFrequencyCode(), claim.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/PatientClaimsEobTaskTransformerTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/PatientClaimsEobTaskTransformerTest.java index cc23060d37..c3f1766cdd 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/PatientClaimsEobTaskTransformerTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/PatientClaimsEobTaskTransformerTest.java @@ -119,7 +119,7 @@ public void setup() { when(metricRegistry.timer(any())).thenReturn(metricsTimer); when(metricsTimer.time()).thenReturn(metricsTimerContext); // NPI and FDA drug mocking - when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.of("JUNK")); + // when(mockNpiOrgLookup.retrieveNPIOrgDisplay(Optional.empty())).thenReturn(Optional.of("JUNK")); when(mockDrugDisplayLookup.retrieveFDADrugCodeDisplay(Optional.empty())).thenReturn("JUNK"); // used to get the claim type in transformer utils diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/SNFClaimTransformerTest.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/SNFClaimTransformerTest.java index 4624855c77..73461e7499 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/SNFClaimTransformerTest.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/stu3/providers/SNFClaimTransformerTest.java @@ -8,6 +8,7 @@ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.Timer; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.codebook.data.CcwCodebookVariable; import gov.cms.bfd.model.rif.entities.SNFClaim; @@ -216,7 +217,9 @@ static void assertMatches(SNFClaim claim, ExplanationOfBenefit eob) TransformerTestUtils.assertEobCommonGroupInpOutHHAHospiceSNFEquals( eob, claim.getOrganizationNpi(), - localNpiLookup.retrieveNPIOrgDisplay(claim.getOrganizationNpi()), + localNpiLookup + .retrieveNPIOrgDisplay(claim.getOrganizationNpi()) + .map(NPIData::getProviderOrganizationName), claim.getClaimFacilityTypeCode(), claim.getClaimFrequencyCode(), claim.getClaimNonPaymentReasonCode(), diff --git a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/utils/RDATestUtils.java b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/utils/RDATestUtils.java index 1826e9703d..19a77e2136 100644 --- a/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/utils/RDATestUtils.java +++ b/apps/bfd-server/bfd-server-war/src/test/java/gov/cms/bfd/server/war/utils/RDATestUtils.java @@ -3,6 +3,7 @@ import gov.cms.bfd.DatabaseTestUtils; import gov.cms.bfd.data.fda.lookup.FdaDrugCodeDisplayLookup; import gov.cms.bfd.data.fda.utility.App; +import gov.cms.bfd.data.npi.dto.NPIData; import gov.cms.bfd.data.npi.lookup.NPIOrgLookup; import gov.cms.bfd.model.rda.Mbi; import gov.cms.bfd.model.rda.entities.RdaFissClaim; @@ -38,6 +39,8 @@ import org.jetbrains.annotations.NotNull; import org.mockito.MockedStatic; import org.mockito.Mockito; +import org.testcontainers.shaded.com.fasterxml.jackson.core.JsonProcessingException; +import org.testcontainers.shaded.com.fasterxml.jackson.databind.ObjectMapper; /** Supplies test data for the RDA based unit tests. */ public class RDATestUtils { @@ -97,8 +100,11 @@ public class RDATestUtils { /** A fake org name display that is associated with the FAKE_NPI_ORG_NAME. */ public static final String FAKE_NPI_ORG_NAME = "Fake ORG Name"; - /** a fake taxonomy. */ - public static final String FAKE_TAXONOMY = "390200000X\tHealth Care"; + /** a fake taxonomy code. */ + public static final String FAKE_TAXONOMY_CODE = "390200000X"; + + /** a fake taxonomy display. */ + public static final String FAKE_TAXONOMY_DISPLAY = "Health Care"; /** A fake drug code used for testing. */ public static final String FAKE_DRUG_CODE = "00000-0000"; @@ -940,8 +946,26 @@ public Mbi lookupTestMbiRecord(EntityManager em) { public static @NotNull MockedStatic mockNPIOrgLookup() { MockedStatic npiOrgLookup = Mockito.mockStatic(NPIOrgLookup.class); Map npiOrgHashMap = new HashMap<>(); - npiOrgHashMap.put(FAKE_NPI_NUMBER, FAKE_NPI_ORG_NAME); - npiOrgHashMap.put(FAKE_PRACTITIONER_NPI, FAKE_TAXONOMY); + ObjectMapper mapper = new ObjectMapper(); + NPIData npiOrgData = + NPIData.builder() + .npi(FAKE_NPI_NUMBER) + .providerOrganizationName(FAKE_NPI_ORG_NAME) + .taxonomyDisplay(FAKE_TAXONOMY_DISPLAY) + .taxonomyCode(FAKE_TAXONOMY_CODE) + .build(); + NPIData npiTaxonomyData = + NPIData.builder() + .npi(FAKE_PRACTITIONER_NPI) + .providerOrganizationName(FAKE_NPI_ORG_NAME) + .taxonomyCode(FAKE_TAXONOMY_CODE) + .taxonomyDisplay(FAKE_TAXONOMY_DISPLAY) + .build(); + try { + npiOrgHashMap.put(FAKE_NPI_NUMBER, mapper.writeValueAsString(npiOrgData)); + npiOrgHashMap.put(FAKE_PRACTITIONER_NPI, mapper.writeValueAsString(npiTaxonomyData)); + } catch (JsonProcessingException ignored) { + } npiOrgLookup .when(NPIOrgLookup::createNpiOrgLookup) .thenAnswer( diff --git a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobByPatientIdAll.json b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobByPatientIdAll.json index 1fca0562c4..38d3c1af32 100644 --- a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobByPatientIdAll.json +++ b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobByPatientIdAll.json @@ -1078,17 +1078,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "http://nucc.org/provider-taxonomy", - "code" : "207ZH0000X", - "display" : "Hematology (Pathology) Physician" - }, { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "A5", - "display" : "Pharmacy (DMERC)" - } ] } } ], "supportingInfo" : [ { @@ -5082,13 +5071,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "41", - "display" : "Optometrist" - } ] } }, { "sequence" : 4, diff --git a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobByPatientIdPaged.json b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobByPatientIdPaged.json index 236e7f5e3f..a516e8779d 100644 --- a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobByPatientIdPaged.json +++ b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobByPatientIdPaged.json @@ -1084,17 +1084,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "http://nucc.org/provider-taxonomy", - "code" : "207ZH0000X", - "display" : "Hematology (Pathology) Physician" - }, { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "A5", - "display" : "Pharmacy (DMERC)" - } ] } } ], "supportingInfo" : [ { @@ -5088,13 +5077,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "41", - "display" : "Optometrist" - } ] } }, { "sequence" : 4, diff --git a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrier.json b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrier.json index 25aed327fd..82cbe92a18 100644 --- a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrier.json +++ b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrier.json @@ -214,13 +214,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "41", - "display" : "Optometrist" - } ] } }, { "sequence" : 4, diff --git a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrierWithMultipleLines.json b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrierWithMultipleLines.json index 98785a3b7d..781378dc76 100644 --- a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrierWithMultipleLines.json +++ b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrierWithMultipleLines.json @@ -298,13 +298,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "41", - "display" : "Optometrist" - } ] } }, { "sequence" : 4, diff --git a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrierWithTaxNumbers.json b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrierWithTaxNumbers.json index 480cbe8525..11c3edb4a8 100644 --- a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrierWithTaxNumbers.json +++ b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadCarrierWithTaxNumbers.json @@ -214,13 +214,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "41", - "display" : "Optometrist" - } ] } }, { "sequence" : 4, diff --git a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadDme.json b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadDme.json index 9080451cf7..c097777db8 100644 --- a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadDme.json +++ b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadDme.json @@ -183,17 +183,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "http://nucc.org/provider-taxonomy", - "code" : "207ZH0000X", - "display" : "Hematology (Pathology) Physician" - }, { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "A5", - "display" : "Pharmacy (DMERC)" - } ] } } ], "supportingInfo" : [ { diff --git a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadDmeWithTaxNumbers.json b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadDmeWithTaxNumbers.json index 19d74d6999..656bd3f351 100644 --- a/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadDmeWithTaxNumbers.json +++ b/apps/bfd-server/bfd-server-war/src/test/resources/endpoint-responses/v2/eobReadDmeWithTaxNumbers.json @@ -183,17 +183,6 @@ "code" : "performing", "display" : "Performing provider" } ] - }, - "qualification" : { - "coding" : [ { - "system" : "http://nucc.org/provider-taxonomy", - "code" : "207ZH0000X", - "display" : "Hematology (Pathology) Physician" - }, { - "system" : "https://bluebutton.cms.gov/resources/variables/prvdr_spclty", - "code" : "A5", - "display" : "Pharmacy (DMERC)" - } ] } } ], "supportingInfo" : [ { diff --git a/apps/bfd-server/bfd-server-war/src/test/resources/fakeOrgData.tsv b/apps/bfd-server/bfd-server-war/src/test/resources/fakeOrgData.tsv index deae4d3b0d..9c082804be 100644 --- a/apps/bfd-server/bfd-server-war/src/test/resources/fakeOrgData.tsv +++ b/apps/bfd-server/bfd-server-war/src/test/resources/fakeOrgData.tsv @@ -1,6 +1,5 @@ -0000000000 Fake ORG Name -2222222222 207R00000X Internal Medicine Physician -3333333333 207T00000X Neurological Surgery Physician -4444 204D00000X Neuromusculoskeletal Medicine & OMM Physician -345345345 207ZH0000X Hematology (Pathology) Physician -1244444444 207ZH0000X Hematology (Pathology) Physician \ No newline at end of file +0000000000 { "npi": "0000000000", "providerOrganizationName": "Fake ORG Name"} +2222222222 { "npi": "2222222222", "taxonomyCode": "207R00000X", "taxonomyDisplay": "Internal Medicine Physician" } +3333333333 { "npi": "3333333333", "taxonomyCode": "207T00000X", "taxonomyDisplay": "Neurological Surgery Physician" } +4444 { "npi": "444", "taxonomyCode": "204D00000X", "taxonomyDisplay": "Neuromusculoskeletal Medicine & OMM Physician" } +345345345 { "npi": "345345345", "taxonomyCode": "207ZH0000X", "taxonomyDisplay": "Hematology (Pathology) Physician" }