diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_empi/empi_operations.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_empi/empi_operations.md index fcbb2868100..c638a4c7d14 100644 --- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_empi/empi_operations.md +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_empi/empi_operations.md @@ -317,7 +317,11 @@ The operation returns the updated `Person` resource. Note that this is the only ## Merge Persons -The `$empi-merge-persons` operation can be used to merge one Person resource with another. When doing this, you will need to decide which resource to merge from and which one to merge to. In most cases, fields will be merged (e.g. names, identifiers, and links will be the union of two). However when there is a conflict (e.g. birthday), fields in the toPerson will take precedence over fields in the fromPerson. This operation takes the following parameters: +The `$empi-merge-persons` operation can be used to merge one Person resource with another. When doing this, you will need to decide which resource to merge from and which one to merge to. In most cases, fields will be merged (e.g. names, identifiers, and links will be the union of two). However when there is a conflict (e.g. birthday), fields in the toPerson will take precedence over fields in the fromPerson + +After the merge is complete, `fromPerson.active` is set to `false`. Also, a new link with assurance level 4 (MANUAL MATCH) will be added pointing from the fromPerson to the toPerson. + +This operation takes the following parameters: @@ -334,7 +338,7 @@ The `$empi-merge-persons` operation can be used to merge one Person resource wit diff --git a/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiPersonMergerSvcImpl.java b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiPersonMergerSvcImpl.java index 0eebae14e14..80c1ef05389 100644 --- a/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiPersonMergerSvcImpl.java +++ b/hapi-fhir-jpaserver-empi/src/main/java/ca/uhn/fhir/jpa/empi/svc/EmpiPersonMergerSvcImpl.java @@ -20,6 +20,8 @@ package ca.uhn.fhir.jpa.empi.svc; * #L% */ +import ca.uhn.fhir.empi.api.EmpiLinkSourceEnum; +import ca.uhn.fhir.empi.api.EmpiMatchResultEnum; import ca.uhn.fhir.empi.api.IEmpiLinkSvc; import ca.uhn.fhir.empi.api.IEmpiPersonMergerSvc; import ca.uhn.fhir.empi.log.Logs; @@ -56,20 +58,38 @@ public class EmpiPersonMergerSvcImpl implements IEmpiPersonMergerSvc { @Override @Transactional public IAnyResource mergePersons(IAnyResource theFromPerson, IAnyResource theToPerson, EmpiTransactionContext theEmpiTransactionContext) { - // TODO EMPI replace this with a post containing the manually merged fields - myPersonHelper.mergePersonFields(theFromPerson, theToPerson); - mergeLinks(theFromPerson, theToPerson, theEmpiTransactionContext); - myEmpiResourceDaoSvc.updatePerson(theToPerson); - log(theEmpiTransactionContext, "Merged " + theFromPerson.getIdElement().toVersionless() + " into " + theToPerson.getIdElement().toVersionless()); + Long toPersonPid = myIdHelperService.getPidOrThrowException(theToPerson); + myPersonHelper.mergePersonFields(theFromPerson, theToPerson); + mergeLinks(theFromPerson, theToPerson, toPersonPid, theEmpiTransactionContext); + + refreshLinksAndUpdatePerson(theToPerson, theEmpiTransactionContext); + + Long fromPersonPid = myIdHelperService.getPidOrThrowException(theFromPerson); + addMergeLink(fromPersonPid, toPersonPid); myPersonHelper.deactivatePerson(theFromPerson); - myEmpiResourceDaoSvc.updatePerson(theFromPerson); - log(theEmpiTransactionContext, "Deactivated " + theFromPerson.getIdElement().toVersionless()); + + refreshLinksAndUpdatePerson(theFromPerson, theEmpiTransactionContext); + + log(theEmpiTransactionContext, "Merged " + theFromPerson.getIdElement().toVersionless() + " into " + theToPerson.getIdElement().toVersionless()); return theToPerson; } - private void mergeLinks(IAnyResource theFromPerson, IAnyResource theToPerson, EmpiTransactionContext theEmpiTransactionContext) { - long toPersonPid = myIdHelperService.getPidOrThrowException(theToPerson); + private void addMergeLink(Long theFromPersonPid, Long theToPersonPid) { + EmpiLink empiLink = new EmpiLink() + .setPersonPid(theFromPersonPid) + .setTargetPid(theToPersonPid) + .setMatchResult(EmpiMatchResultEnum.MATCH) + .setLinkSource(EmpiLinkSourceEnum.MANUAL); + myEmpiLinkDaoSvc.save(empiLink); + } + + private void refreshLinksAndUpdatePerson(IAnyResource theToPerson, EmpiTransactionContext theEmpiTransactionContext) { + myEmpiLinkSvc.syncEmpiLinksToPersonLinks(theToPerson, theEmpiTransactionContext); + myEmpiResourceDaoSvc.updatePerson(theToPerson); + } + + private void mergeLinks(IAnyResource theFromPerson, IAnyResource theToPerson, Long theToPersonPid, EmpiTransactionContext theEmpiTransactionContext) { List incomingLinks = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(theFromPerson); List origLinks = myEmpiLinkDaoSvc.findEmpiLinksByPersonId(theToPerson); @@ -97,13 +117,10 @@ public class EmpiPersonMergerSvcImpl implements IEmpiPersonMergerSvc { } } // The original links didn't contain this target, so move it over to the toPerson - incomingLink.setPersonPid(toPersonPid); + incomingLink.setPersonPid(theToPersonPid); ourLog.trace("Saving link {}", incomingLink); myEmpiLinkDaoSvc.save(incomingLink); } - - myEmpiLinkSvc.syncEmpiLinksToPersonLinks(theFromPerson, theEmpiTransactionContext); - myEmpiLinkSvc.syncEmpiLinksToPersonLinks(theToPerson, theEmpiTransactionContext); } private Optional findLinkWithMatchingTarget(List theEmpiLinks, EmpiLink theLinkWithTargetToMatch) { diff --git a/hapi-fhir-jpaserver-empi/src/test/java/ca/uhn/fhir/jpa/empi/provider/EmpiProviderMergePersonsR4Test.java b/hapi-fhir-jpaserver-empi/src/test/java/ca/uhn/fhir/jpa/empi/provider/EmpiProviderMergePersonsR4Test.java index 829339373ba..fa9283cb998 100644 --- a/hapi-fhir-jpaserver-empi/src/test/java/ca/uhn/fhir/jpa/empi/provider/EmpiProviderMergePersonsR4Test.java +++ b/hapi-fhir-jpaserver-empi/src/test/java/ca/uhn/fhir/jpa/empi/provider/EmpiProviderMergePersonsR4Test.java @@ -1,5 +1,8 @@ package ca.uhn.fhir.jpa.empi.provider; +import ca.uhn.fhir.empi.api.EmpiLinkSourceEnum; +import ca.uhn.fhir.empi.api.EmpiMatchResultEnum; +import ca.uhn.fhir.empi.util.AssuranceLevelUtil; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import org.hl7.fhir.r4.model.Bundle; @@ -9,6 +12,9 @@ import org.hl7.fhir.r4.model.StringType; import org.junit.Before; import org.junit.Test; +import java.util.List; + +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -48,9 +54,16 @@ public class EmpiProviderMergePersonsR4Test extends BaseProviderR4Test { public void testMerge() { Person mergedPerson = myEmpiProviderR4.mergePersons(myFromPersonId, myToPersonId, myRequestDetails); assertEquals(myToPerson.getIdElement(), mergedPerson.getIdElement()); - assertThat(mergedPerson, is(samePersonAs(mergedPerson))); + assertThat(mergedPerson, is(samePersonAs(myToPerson))); assertEquals(2, getAllPersons().size()); assertEquals(1, getAllActivePersons().size()); + + Person fromPerson = myPersonDao.read(myFromPerson.getIdElement().toUnqualifiedVersionless()); + assertThat(fromPerson.getActive(), is(false)); + List links = fromPerson.getLink(); + assertThat(links, hasSize(1)); + assertThat(links.get(0).getTarget().getReference(), is (myToPerson.getIdElement().toUnqualifiedVersionless().getValue())); + assertThat(links.get(0).getAssurance(), is (AssuranceLevelUtil.getAssuranceLevel(EmpiMatchResultEnum.MATCH, EmpiLinkSourceEnum.MANUAL).toR4())); } @Test
String 1..1 - The id of the Person resource to merge data from. "active" will be set to "false" on this resource after the merge. + The id of the Person resource to merge data from.