Extend $member match to validate matched patient (#4136)
* added validation for family name and birthdate * making changes to tests * update patient identifer return and validatePatientMember * update patient identifer type for test * update method name * update test comment
This commit is contained in:
parent
bd22b8d1c0
commit
dac266b719
|
@ -210,6 +210,8 @@ public class Constants {
|
||||||
public static final String PARAM_MEMBER_PATIENT = "MemberPatient";
|
public static final String PARAM_MEMBER_PATIENT = "MemberPatient";
|
||||||
public static final String PARAM_OLD_COVERAGE = "OldCoverage";
|
public static final String PARAM_OLD_COVERAGE = "OldCoverage";
|
||||||
public static final String PARAM_NEW_COVERAGE = "NewCoverage";
|
public static final String PARAM_NEW_COVERAGE = "NewCoverage";
|
||||||
|
public static final String PARAM_MEMBER_PATIENT_NAME = PARAM_MEMBER_PATIENT + " Name";
|
||||||
|
public static final String PARAM_MEMBER_PATIENT_BIRTHDATE = PARAM_MEMBER_PATIENT + " Birthdate";
|
||||||
|
|
||||||
public static final String PARAMQUALIFIER_MISSING = ":missing";
|
public static final String PARAMQUALIFIER_MISSING = ":missing";
|
||||||
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
|
public static final String PARAMQUALIFIER_MISSING_FALSE = "false";
|
||||||
|
|
|
@ -189,4 +189,5 @@ operation.member.match.error.coverage.not.found=Could not find coverage for memb
|
||||||
operation.member.match.error.beneficiary.not.found=Could not find beneficiary for coverage.
|
operation.member.match.error.beneficiary.not.found=Could not find beneficiary for coverage.
|
||||||
operation.member.match.error.missing.parameter=Parameter "{0}" is required.
|
operation.member.match.error.missing.parameter=Parameter "{0}" is required.
|
||||||
operation.member.match.error.beneficiary.without.identifier=Coverage beneficiary does not have an identifier.
|
operation.member.match.error.beneficiary.without.identifier=Coverage beneficiary does not have an identifier.
|
||||||
|
operation.member.match.error.patient.not.found=Could not find matching patient for coverage.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 4133
|
||||||
|
title: "Extend $member-match to validate matched patient against family name and birthdate"
|
|
@ -194,8 +194,8 @@ public abstract class BaseJpaResourceProviderPatientR4 extends JpaResourceProvid
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /Patient/$member-match operation
|
* /Patient/$member-match operation
|
||||||
* Basic implementation matching by coverage id or by coverage identifier. Not matching by
|
* Basic implementation matching by coverage id or by coverage identifier. Matching by
|
||||||
* Beneficiary (Patient) demographics in this version
|
* Beneficiary (Patient) demographics on family name and birthdate in this version
|
||||||
*/
|
*/
|
||||||
@Operation(name = ProviderConstants.OPERATION_MEMBER_MATCH, canonicalUrl = "http://hl7.org/fhir/us/davinci-hrex/OperationDefinition/member-match", idempotent = false, returnParameters = {
|
@Operation(name = ProviderConstants.OPERATION_MEMBER_MATCH, canonicalUrl = "http://hl7.org/fhir/us/davinci-hrex/OperationDefinition/member-match", idempotent = false, returnParameters = {
|
||||||
@OperationParam(name = "MemberIdentifier", typeName = "string")
|
@OperationParam(name = "MemberIdentifier", typeName = "string")
|
||||||
|
@ -240,7 +240,13 @@ public abstract class BaseJpaResourceProviderPatientR4 extends JpaResourceProvid
|
||||||
"operation.member.match.error.beneficiary.not.found");
|
"operation.member.match.error.beneficiary.not.found");
|
||||||
throw new UnprocessableEntityException(Msg.code(1156) + i18nMessage);
|
throw new UnprocessableEntityException(Msg.code(1156) + i18nMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
Patient patient = patientOpt.get();
|
Patient patient = patientOpt.get();
|
||||||
|
if (!myMemberMatcherR4Helper.validPatientMember(patient, theMemberPatient)) {
|
||||||
|
String i18nMessage = getContext().getLocalizer().getMessage(
|
||||||
|
"operation.member.match.error.patient.not.found");
|
||||||
|
throw new UnprocessableEntityException(Msg.code(2146) + i18nMessage);
|
||||||
|
}
|
||||||
|
|
||||||
if (patient.getIdentifier().isEmpty()) {
|
if (patient.getIdentifier().isEmpty()) {
|
||||||
String i18nMessage = getContext().getLocalizer().getMessage(
|
String i18nMessage = getContext().getLocalizer().getMessage(
|
||||||
|
@ -258,9 +264,9 @@ public abstract class BaseJpaResourceProviderPatientR4 extends JpaResourceProvid
|
||||||
validateParam(theMemberPatient, Constants.PARAM_MEMBER_PATIENT);
|
validateParam(theMemberPatient, Constants.PARAM_MEMBER_PATIENT);
|
||||||
validateParam(theOldCoverage, Constants.PARAM_OLD_COVERAGE);
|
validateParam(theOldCoverage, Constants.PARAM_OLD_COVERAGE);
|
||||||
validateParam(theNewCoverage, Constants.PARAM_NEW_COVERAGE);
|
validateParam(theNewCoverage, Constants.PARAM_NEW_COVERAGE);
|
||||||
|
validateMemberPatientParam(theMemberPatient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void validateParam(Object theParam, String theParamName) {
|
private void validateParam(Object theParam, String theParamName) {
|
||||||
if (theParam == null) {
|
if (theParam == null) {
|
||||||
String i18nMessage = getContext().getLocalizer().getMessage(
|
String i18nMessage = getContext().getLocalizer().getMessage(
|
||||||
|
@ -269,6 +275,14 @@ public abstract class BaseJpaResourceProviderPatientR4 extends JpaResourceProvid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void validateMemberPatientParam(Patient theMemberPatient) {
|
||||||
|
if (theMemberPatient.getName().isEmpty()) {
|
||||||
|
validateParam(null, Constants.PARAM_MEMBER_PATIENT_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
validateParam(theMemberPatient.getName().get(0).getFamily(), Constants.PARAM_MEMBER_PATIENT_NAME);
|
||||||
|
validateParam(theMemberPatient.getBirthDate(), Constants.PARAM_MEMBER_PATIENT_BIRTHDATE);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a list of string types, return only the ID portions of any parameters passed in.
|
* Given a list of string types, return only the ID portions of any parameters passed in.
|
||||||
|
|
|
@ -4,15 +4,19 @@ import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
|
import ca.uhn.fhir.rest.param.DateParam;
|
||||||
|
import ca.uhn.fhir.rest.param.StringOrListParam;
|
||||||
import ca.uhn.fhir.rest.param.StringParam;
|
import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||||
import ca.uhn.fhir.util.ParametersUtil;
|
import ca.uhn.fhir.util.ParametersUtil;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
import org.hl7.fhir.r4.model.Coverage;
|
import org.hl7.fhir.r4.model.Coverage;
|
||||||
|
import org.hl7.fhir.r4.model.HumanName;
|
||||||
import org.hl7.fhir.r4.model.Identifier;
|
import org.hl7.fhir.r4.model.Identifier;
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
@ -48,7 +52,7 @@ import static ca.uhn.fhir.rest.api.Constants.PARAM_NEW_COVERAGE;
|
||||||
public class MemberMatcherR4Helper {
|
public class MemberMatcherR4Helper {
|
||||||
|
|
||||||
private static final String OUT_COVERAGE_IDENTIFIER_CODE_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0203";
|
private static final String OUT_COVERAGE_IDENTIFIER_CODE_SYSTEM = "http://terminology.hl7.org/CodeSystem/v2-0203";
|
||||||
private static final String OUT_COVERAGE_IDENTIFIER_CODE = "UMB";
|
private static final String OUT_COVERAGE_IDENTIFIER_CODE = "MB";
|
||||||
private static final String OUT_COVERAGE_IDENTIFIER_TEXT = "Member Number";
|
private static final String OUT_COVERAGE_IDENTIFIER_TEXT = "Member Number";
|
||||||
private static final String COVERAGE_TYPE = "Coverage";
|
private static final String COVERAGE_TYPE = "Coverage";
|
||||||
|
|
||||||
|
@ -66,8 +70,7 @@ public class MemberMatcherR4Helper {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find Coverage matching the received member (Patient) by coverage id or by coverage identifier
|
* Find Coverage matching the received member (Patient) by coverage id or by coverage identifier only
|
||||||
* Matching by member patient demographics is not supported.
|
|
||||||
*/
|
*/
|
||||||
public Optional<Coverage> findMatchingCoverage(Coverage theCoverageToMatch) {
|
public Optional<Coverage> findMatchingCoverage(Coverage theCoverageToMatch) {
|
||||||
// search by received old coverage id
|
// search by received old coverage id
|
||||||
|
@ -169,4 +172,28 @@ public class MemberMatcherR4Helper {
|
||||||
Patient beneficiary = myPatientDao.read(new IdDt(beneficiaryRef.getReference()));
|
Patient beneficiary = myPatientDao.read(new IdDt(beneficiaryRef.getReference()));
|
||||||
return Optional.ofNullable(beneficiary);
|
return Optional.ofNullable(beneficiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matching by member patient demographics - family name and birthdate only
|
||||||
|
*/
|
||||||
|
public boolean validPatientMember(Patient thePatientFromContract, Patient thePatientToMatch) {
|
||||||
|
if (thePatientFromContract == null || thePatientFromContract.getIdElement() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
StringOrListParam familyName = new StringOrListParam();
|
||||||
|
for (HumanName name: thePatientToMatch.getName()) {
|
||||||
|
familyName.addOr(new StringParam(name.getFamily()));
|
||||||
|
}
|
||||||
|
SearchParameterMap map = new SearchParameterMap()
|
||||||
|
.add("family", familyName)
|
||||||
|
.add("birthdate", new DateParam(thePatientToMatch.getBirthDateElement().getValueAsString()));
|
||||||
|
ca.uhn.fhir.rest.api.server.IBundleProvider bundle = myPatientDao.search(map);
|
||||||
|
for (IBaseResource patientResource: bundle.getAllResources()) {
|
||||||
|
IIdType patientId = patientResource.getIdElement().toUnqualifiedVersionless();
|
||||||
|
if ( patientId.getValue().equals(thePatientFromContract.getIdElement().toUnqualifiedVersionless().getValue())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,11 @@ import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
import ca.uhn.fhir.model.primitive.IdDt;
|
||||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.SimpleBundleProvider;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.hl7.fhir.r4.model.Coverage;
|
import org.hl7.fhir.r4.model.Coverage;
|
||||||
|
import org.hl7.fhir.r4.model.DateType;
|
||||||
|
import org.hl7.fhir.r4.model.HumanName;
|
||||||
import org.hl7.fhir.r4.model.Identifier;
|
import org.hl7.fhir.r4.model.Identifier;
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
|
@ -32,6 +35,7 @@ import static ca.uhn.fhir.rest.api.Constants.PARAM_NEW_COVERAGE;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.isA;
|
import static org.mockito.ArgumentMatchers.isA;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
@ -47,10 +51,10 @@ class MemberMatcherR4HelperTest {
|
||||||
private MemberMatcherR4Helper myTestedHelper;
|
private MemberMatcherR4Helper myTestedHelper;
|
||||||
|
|
||||||
@Mock private Coverage myCoverageToMatch;
|
@Mock private Coverage myCoverageToMatch;
|
||||||
@Mock private Patient myPatient;
|
|
||||||
@Mock private IBundleProvider myBundleProvider;
|
@Mock private IBundleProvider myBundleProvider;
|
||||||
|
|
||||||
private final Coverage myMatchedCoverage = new Coverage();
|
private final Coverage myMatchedCoverage = new Coverage()
|
||||||
|
.setBeneficiary(new Reference("Patient/123"));
|
||||||
private final Identifier myMatchingIdentifier = new Identifier()
|
private final Identifier myMatchingIdentifier = new Identifier()
|
||||||
.setSystem("identifier-system").setValue("identifier-value");
|
.setSystem("identifier-system").setValue("identifier-value");
|
||||||
|
|
||||||
|
@ -237,5 +241,87 @@ class MemberMatcherR4HelperTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
public class TestValidPatientMember {
|
||||||
|
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private Coverage coverage;
|
||||||
|
private Patient patient;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void noPatientFoundFromContractReturnsFalse() {
|
||||||
|
boolean result = myTestedHelper.validPatientMember(null, patient);
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void noPatientFoundFromPatientMemberReturnsFalse() {
|
||||||
|
boolean result = myTestedHelper.validPatientMember(patient, null);
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void noMatchingFamilyNameReturnsFalse() {
|
||||||
|
Patient patientFromMemberMatch = getPatientWithNoIDParm("Person", "2020-01-01");
|
||||||
|
Patient patientFromContractFound = getPatientWithIDParm("A123", "Smith", "2020-01-01");
|
||||||
|
when(myPatientDao.search(any(SearchParameterMap.class))).thenAnswer(t -> {
|
||||||
|
IBundleProvider provider = new SimpleBundleProvider(Collections.singletonList(new Patient().setId("B123")));
|
||||||
|
return provider;
|
||||||
|
});
|
||||||
|
boolean result = myTestedHelper.validPatientMember(patientFromContractFound, patientFromMemberMatch);
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void noMatchingBirthdayReturnsFalse() {
|
||||||
|
Patient patientFromMemberMatch = getPatientWithNoIDParm("Person", "1990-01-01");
|
||||||
|
Patient patientFromContractFound = getPatientWithIDParm("A123", "Person", "2020-01-01");
|
||||||
|
when(myPatientDao.search(any(SearchParameterMap.class))).thenAnswer(t -> {
|
||||||
|
IBundleProvider provider = new SimpleBundleProvider(Collections.singletonList(new Patient().setId("B123")));
|
||||||
|
return provider;
|
||||||
|
});
|
||||||
|
boolean result = myTestedHelper.validPatientMember(patientFromContractFound, patientFromMemberMatch);
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void noMatchingFieldsReturnsFalse() {
|
||||||
|
Patient patientFromMemberMatch = getPatientWithNoIDParm("Person", "1990-01-01");
|
||||||
|
Patient patientFromContractFound = getPatientWithIDParm("A123", "Smith", "2020-01-01");
|
||||||
|
when(myPatientDao.search(any(SearchParameterMap.class))).thenAnswer(t -> {
|
||||||
|
IBundleProvider provider = new SimpleBundleProvider(Collections.singletonList(new Patient().setId("B123")));
|
||||||
|
return provider;
|
||||||
|
});
|
||||||
|
boolean result = myTestedHelper.validPatientMember(patientFromContractFound, patientFromMemberMatch);
|
||||||
|
assertFalse(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void patientMatchingReturnTrue() {
|
||||||
|
Patient patientFromMemberMatch = getPatientWithNoIDParm("Person", "2020-01-01");
|
||||||
|
Patient patientFromContractFound = getPatientWithIDParm("A123", "Person", "2020-01-01");
|
||||||
|
when(myPatientDao.search(any(SearchParameterMap.class))).thenAnswer(t -> {
|
||||||
|
IBundleProvider provider = new SimpleBundleProvider(Collections.singletonList(patientFromContractFound));
|
||||||
|
return provider;
|
||||||
|
});
|
||||||
|
boolean result = myTestedHelper.validPatientMember(patientFromContractFound, patientFromMemberMatch);
|
||||||
|
assertTrue(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Patient getPatientWithNoIDParm(String familyName, String birthdate) {
|
||||||
|
Patient patient = new Patient().setName(Lists.newArrayList(new HumanName()
|
||||||
|
.setUse(HumanName.NameUse.OFFICIAL).setFamily(familyName)))
|
||||||
|
.setBirthDateElement(new DateType(birthdate));
|
||||||
|
return patient;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Patient getPatientWithIDParm(String id, String familyName, String birthdate) {
|
||||||
|
Patient patient = getPatientWithNoIDParm(familyName, birthdate);
|
||||||
|
patient.setId(id);
|
||||||
|
return patient;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import ca.uhn.fhir.parser.StrictErrorHandler;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||||
import ca.uhn.fhir.rest.client.apache.ResourceEntity;
|
import ca.uhn.fhir.rest.client.apache.ResourceEntity;
|
||||||
|
import ca.uhn.fhir.rest.param.DateParam;
|
||||||
import ca.uhn.fhir.util.ParametersUtil;
|
import ca.uhn.fhir.util.ParametersUtil;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
@ -14,6 +15,7 @@ import org.hl7.fhir.instance.model.api.IBase;
|
||||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||||
import org.hl7.fhir.r4.model.Coding;
|
import org.hl7.fhir.r4.model.Coding;
|
||||||
import org.hl7.fhir.r4.model.Coverage;
|
import org.hl7.fhir.r4.model.Coverage;
|
||||||
|
import org.hl7.fhir.r4.model.DateType;
|
||||||
import org.hl7.fhir.r4.model.Enumerations;
|
import org.hl7.fhir.r4.model.Enumerations;
|
||||||
import org.hl7.fhir.r4.model.HumanName;
|
import org.hl7.fhir.r4.model.HumanName;
|
||||||
import org.hl7.fhir.r4.model.Identifier;
|
import org.hl7.fhir.r4.model.Identifier;
|
||||||
|
@ -51,7 +53,9 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
||||||
private static final String EXISTING_COVERAGE_PATIENT_IDENT_VALUE = "DHU-55678";
|
private static final String EXISTING_COVERAGE_PATIENT_IDENT_VALUE = "DHU-55678";
|
||||||
|
|
||||||
private Identifier ourExistingCoverageIdentifier;
|
private Identifier ourExistingCoverageIdentifier;
|
||||||
|
private Patient myPatient;
|
||||||
|
private Coverage oldCoverage; // Old Coverage (must match field)
|
||||||
|
private Coverage newCoverage; // New Coverage (must return unchanged)
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void beforeDisableResultReuse() {
|
public void beforeDisableResultReuse() {
|
||||||
|
@ -68,41 +72,52 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
||||||
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
|
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void before() throws Exception {
|
public void before() throws Exception {
|
||||||
super.before();
|
super.before();
|
||||||
myFhirContext.setParserErrorHandler(new StrictErrorHandler());
|
myFhirContext.setParserErrorHandler(new StrictErrorHandler());
|
||||||
}
|
myPatient = (Patient) new Patient().setName(Lists.newArrayList(new HumanName()
|
||||||
|
.setUse(HumanName.NameUse.OFFICIAL).setFamily("Person")))
|
||||||
|
.setBirthDateElement(new DateType("2020-01-01"))
|
||||||
|
.setId("Patient/A123");
|
||||||
|
|
||||||
|
// Old Coverage (must match field)
|
||||||
|
oldCoverage = (Coverage) new Coverage()
|
||||||
|
.setId(EXISTING_COVERAGE_ID);
|
||||||
|
|
||||||
|
// New Coverage (must return unchanged)
|
||||||
|
newCoverage = (Coverage) new Coverage()
|
||||||
|
.setIdentifier(Lists.newArrayList(new Identifier().setSystem("http://newealthplan.example.com").setValue("234567")))
|
||||||
|
.setId("AA87654");
|
||||||
|
}
|
||||||
|
|
||||||
private void createCoverageWithBeneficiary(
|
private void createCoverageWithBeneficiary(
|
||||||
boolean theAssociateBeneficiaryPatient, boolean includeBeneficiaryIdentifier) {
|
boolean theAssociateBeneficiaryPatient, boolean includeBeneficiaryIdentifier) {
|
||||||
|
|
||||||
Patient member = null;
|
Patient member = new Patient();
|
||||||
if (theAssociateBeneficiaryPatient) {
|
if (theAssociateBeneficiaryPatient) {
|
||||||
// Patient
|
// Patient
|
||||||
member = new Patient().setName(Lists.newArrayList(new HumanName()
|
member.setName(Lists.newArrayList(new HumanName()
|
||||||
.setUse(HumanName.NameUse.OFFICIAL).setFamily("Person").addGiven("Patricia").addGiven("Ann")));
|
.setUse(HumanName.NameUse.OFFICIAL).setFamily("Person")))
|
||||||
|
.setBirthDateElement(new DateType("2020-01-01"))
|
||||||
|
.setId("Patient/A123");
|
||||||
if (includeBeneficiaryIdentifier) {
|
if (includeBeneficiaryIdentifier) {
|
||||||
member.setIdentifier(Collections.singletonList(new Identifier()
|
member.setIdentifier(Collections.singletonList(new Identifier()
|
||||||
.setSystem(EXISTING_COVERAGE_PATIENT_IDENT_SYSTEM).setValue(EXISTING_COVERAGE_PATIENT_IDENT_VALUE)));
|
.setSystem(EXISTING_COVERAGE_PATIENT_IDENT_SYSTEM).setValue(EXISTING_COVERAGE_PATIENT_IDENT_VALUE)));
|
||||||
}
|
}
|
||||||
|
member.setActive(true);
|
||||||
myClient.create().resource(member).execute().getId().toUnqualifiedVersionless().getValue();
|
myClient.update().resource(member).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coverage
|
// Coverage
|
||||||
ourExistingCoverageIdentifier = new Identifier()
|
ourExistingCoverageIdentifier = new Identifier()
|
||||||
.setSystem(EXISTING_COVERAGE_IDENT_SYSTEM).setValue(EXISTING_COVERAGE_IDENT_VALUE);
|
.setSystem(EXISTING_COVERAGE_IDENT_SYSTEM).setValue(EXISTING_COVERAGE_IDENT_VALUE);
|
||||||
Coverage ourExistingCoverage = new Coverage()
|
Coverage ourExistingCoverage = (Coverage) new Coverage()
|
||||||
.setStatus(Coverage.CoverageStatus.ACTIVE)
|
.setStatus(Coverage.CoverageStatus.ACTIVE)
|
||||||
.setIdentifier(Collections.singletonList(ourExistingCoverageIdentifier));
|
.setIdentifier(Collections.singletonList(ourExistingCoverageIdentifier));
|
||||||
|
|
||||||
if (theAssociateBeneficiaryPatient) {
|
if (theAssociateBeneficiaryPatient) {
|
||||||
// this doesn't work
|
|
||||||
// myOldCoverage.setBeneficiaryTarget(patient)
|
|
||||||
ourExistingCoverage.setBeneficiary(new Reference(member))
|
ourExistingCoverage.setBeneficiary(new Reference(member))
|
||||||
.setId(EXISTING_COVERAGE_ID);
|
.setId(EXISTING_COVERAGE_ID);
|
||||||
}
|
}
|
||||||
|
@ -115,20 +130,7 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
||||||
public void testMemberMatchByCoverageId() throws Exception {
|
public void testMemberMatchByCoverageId() throws Exception {
|
||||||
createCoverageWithBeneficiary(true, true);
|
createCoverageWithBeneficiary(true, true);
|
||||||
|
|
||||||
// patient doesn't participate in match
|
Parameters inputParameters = buildInputParameters(myPatient, oldCoverage, newCoverage);
|
||||||
Patient patient = new Patient().setGender(Enumerations.AdministrativeGender.FEMALE);
|
|
||||||
|
|
||||||
// Old Coverage
|
|
||||||
Coverage oldCoverage = new Coverage();
|
|
||||||
oldCoverage.setId(EXISTING_COVERAGE_ID); // must match field
|
|
||||||
|
|
||||||
// New Coverage (must return unchanged)
|
|
||||||
Coverage newCoverage = new Coverage();
|
|
||||||
newCoverage.setId("AA87654");
|
|
||||||
newCoverage.setIdentifier(Lists.newArrayList(
|
|
||||||
new Identifier().setSystem("http://newealthplan.example.com").setValue("234567")));
|
|
||||||
|
|
||||||
Parameters inputParameters = buildInputParameters(patient, oldCoverage, newCoverage);
|
|
||||||
Parameters parametersResponse = performOperation(ourServerBase + ourQuery,
|
Parameters parametersResponse = performOperation(ourServerBase + ourQuery,
|
||||||
EncodingEnum.JSON, inputParameters);
|
EncodingEnum.JSON, inputParameters);
|
||||||
|
|
||||||
|
@ -141,47 +143,39 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
||||||
public void testCoverageNoBeneficiaryReturns422() throws Exception {
|
public void testCoverageNoBeneficiaryReturns422() throws Exception {
|
||||||
createCoverageWithBeneficiary(false, false);
|
createCoverageWithBeneficiary(false, false);
|
||||||
|
|
||||||
// patient doesn't participate in match
|
Parameters inputParameters = buildInputParameters(myPatient, oldCoverage, newCoverage);
|
||||||
Patient patient = new Patient().setGender(Enumerations.AdministrativeGender.FEMALE);
|
|
||||||
|
|
||||||
// Old Coverage
|
|
||||||
Coverage oldCoverage = new Coverage();
|
|
||||||
oldCoverage.setId(EXISTING_COVERAGE_ID); // must match field
|
|
||||||
|
|
||||||
// New Coverage (must return unchanged)
|
|
||||||
Coverage newCoverage = new Coverage();
|
|
||||||
newCoverage.setId("AA87654");
|
|
||||||
newCoverage.setIdentifier(Lists.newArrayList(
|
|
||||||
new Identifier().setSystem("http://newealthplan.example.com").setValue("234567")));
|
|
||||||
|
|
||||||
Parameters inputParameters = buildInputParameters(patient, oldCoverage, newCoverage);
|
|
||||||
performOperationExpecting422(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters,
|
performOperationExpecting422(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters,
|
||||||
"Could not find beneficiary for coverage.");
|
"Could not find beneficiary for coverage.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCoverageBeneficiaryNoIdentifierReturns422() throws Exception {
|
public void testCoverageBeneficiaryNoIdentifierReturns422() throws Exception {
|
||||||
createCoverageWithBeneficiary(true, false);
|
createCoverageWithBeneficiary(true, false);
|
||||||
|
|
||||||
// patient doesn't participate in match
|
Parameters inputParameters = buildInputParameters(myPatient, oldCoverage, newCoverage);
|
||||||
Patient patient = new Patient().setGender(Enumerations.AdministrativeGender.FEMALE);
|
|
||||||
|
|
||||||
// Old Coverage
|
|
||||||
Coverage oldCoverage = new Coverage();
|
|
||||||
oldCoverage.setId(EXISTING_COVERAGE_ID); // must match field
|
|
||||||
|
|
||||||
// New Coverage (must return unchanged)
|
|
||||||
Coverage newCoverage = new Coverage();
|
|
||||||
newCoverage.setId("AA87654");
|
|
||||||
newCoverage.setIdentifier(Lists.newArrayList(
|
|
||||||
new Identifier().setSystem("http://newealthplan.example.com").setValue("234567")));
|
|
||||||
|
|
||||||
Parameters inputParameters = buildInputParameters(patient, oldCoverage, newCoverage);
|
|
||||||
performOperationExpecting422(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters,
|
performOperationExpecting422(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters,
|
||||||
"Coverage beneficiary does not have an identifier.");
|
"Coverage beneficiary does not have an identifier.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCoverageNoMatchingPatientFamilyNameReturns422() throws Exception {
|
||||||
|
createCoverageWithBeneficiary(true, true);
|
||||||
|
|
||||||
|
myPatient.setName(Lists.newArrayList(new HumanName().setUse(HumanName.NameUse.OFFICIAL).setFamily("Smith")));
|
||||||
|
Parameters inputParameters = buildInputParameters(myPatient, oldCoverage, newCoverage);
|
||||||
|
performOperationExpecting422(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters,
|
||||||
|
"Could not find matching patient for coverage.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCoverageNoMatchingPatientBirthdateReturns422() throws Exception {
|
||||||
|
createCoverageWithBeneficiary(true, false);
|
||||||
|
|
||||||
|
myPatient.setBirthDateElement(new DateType("2000-01-01"));
|
||||||
|
Parameters inputParameters = buildInputParameters(myPatient, oldCoverage, newCoverage);
|
||||||
|
performOperationExpecting422(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters,
|
||||||
|
"Could not find matching patient for coverage.");
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
public class ValidateParameterErrors {
|
public class ValidateParameterErrors {
|
||||||
|
@ -229,21 +223,7 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
||||||
public void testMemberMatchByCoverageIdentifier() throws Exception {
|
public void testMemberMatchByCoverageIdentifier() throws Exception {
|
||||||
createCoverageWithBeneficiary(true, true);
|
createCoverageWithBeneficiary(true, true);
|
||||||
|
|
||||||
// patient doesn't participate in match
|
Parameters inputParameters = buildInputParameters(myPatient, oldCoverage, newCoverage);
|
||||||
Patient patient = new Patient().setGender(Enumerations.AdministrativeGender.FEMALE);
|
|
||||||
|
|
||||||
// Old Coverage
|
|
||||||
Coverage oldCoverage = new Coverage();
|
|
||||||
oldCoverage.setId("9876B1");
|
|
||||||
oldCoverage.setIdentifier(Lists.newArrayList(ourExistingCoverageIdentifier)); // must match field
|
|
||||||
|
|
||||||
// New Coverage (must return unchanged)
|
|
||||||
Coverage newCoverage = new Coverage();
|
|
||||||
newCoverage.setId("AA87654");
|
|
||||||
newCoverage.setIdentifier(Lists.newArrayList(
|
|
||||||
new Identifier().setSystem("http://newealthplan.example.com").setValue("234567")));
|
|
||||||
|
|
||||||
Parameters inputParameters = buildInputParameters(patient, oldCoverage, newCoverage);
|
|
||||||
Parameters parametersResponse = performOperation(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters);
|
Parameters parametersResponse = performOperation(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters);
|
||||||
|
|
||||||
validateMemberPatient(parametersResponse);
|
validateMemberPatient(parametersResponse);
|
||||||
|
@ -299,27 +279,7 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoCoverageMatchFound() throws Exception {
|
public void testNoCoverageMatchFound() throws Exception {
|
||||||
// Patient doesn't participate in match
|
Parameters inputParameters = buildInputParameters(myPatient, oldCoverage, newCoverage);
|
||||||
Patient patient = new Patient().setGender(Enumerations.AdministrativeGender.FEMALE);
|
|
||||||
|
|
||||||
// Old Coverage
|
|
||||||
Coverage oldCoverage = new Coverage();
|
|
||||||
oldCoverage.setId("9876B1");
|
|
||||||
oldCoverage.setIdentifier(Lists.newArrayList(
|
|
||||||
new Identifier().setSystem("http://oldhealthplan.example.com").setValue("DH10001235")));
|
|
||||||
|
|
||||||
// New Coverage
|
|
||||||
Organization newOrg = new Organization();
|
|
||||||
newOrg.setId("Organization/ProviderOrg1");
|
|
||||||
newOrg.setName("New Health Plan");
|
|
||||||
|
|
||||||
Coverage newCoverage = new Coverage();
|
|
||||||
newCoverage.setId("AA87654");
|
|
||||||
newCoverage.getContained().add(newOrg);
|
|
||||||
newCoverage.setIdentifier(Lists.newArrayList(
|
|
||||||
new Identifier().setSystem("http://newealthplan.example.com").setValue("234567")));
|
|
||||||
|
|
||||||
Parameters inputParameters = buildInputParameters(patient, oldCoverage, newCoverage);
|
|
||||||
performOperationExpecting422(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters,
|
performOperationExpecting422(ourServerBase + ourQuery, EncodingEnum.JSON, inputParameters,
|
||||||
"Could not find coverage for member");
|
"Could not find coverage for member");
|
||||||
}
|
}
|
||||||
|
@ -371,14 +331,14 @@ public class PatientMemberMatchOperationR4Test extends BaseResourceProviderR4Tes
|
||||||
// "coding": [
|
// "coding": [
|
||||||
// {
|
// {
|
||||||
// "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
|
// "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
|
||||||
// "code": "UMB",
|
// "code": "MB",
|
||||||
// "display": "Member Number",
|
// "display": "Member Number",
|
||||||
// "userSelected": false
|
// "userSelected": false
|
||||||
// }
|
// }
|
||||||
// * ]
|
// * ]
|
||||||
Coding coding = theType.getCoding().get(0);
|
Coding coding = theType.getCoding().get(0);
|
||||||
assertEquals("http://terminology.hl7.org/CodeSystem/v2-0203", coding.getSystem());
|
assertEquals("http://terminology.hl7.org/CodeSystem/v2-0203", coding.getSystem());
|
||||||
assertEquals("UMB", coding.getCode());
|
assertEquals("MB", coding.getCode());
|
||||||
assertEquals("Member Number", coding.getDisplay());
|
assertEquals("Member Number", coding.getDisplay());
|
||||||
assertFalse(coding.getUserSelected());
|
assertFalse(coding.getUserSelected());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue