Currently, the RegisterPatientFragmentController within the registrationapp module has registration logic embedded into it that is non-transactional. This includes the following operations that run in sequence:
- registrationCoreService.registerPatient (includes patient, person, name, address, relationships, identifiers, attributes, biometrics)
- registrationEncounter (without obs)
- registrationEncounter (again, with obs)
- non-encounter-based obs (saved individually)
- Any data saved within 0-N "afterCreatedActions"
The result is that it is possible that a patient registration can succeed in part but not in full - eg. a patient might be saved but a registration encounter never created, or a registration encounter might be created but without observations saved into it, or one or more afterCreatedActions may fail.
Ideally, we would ensure that all of this succeeded or failed within a transaction. Additionally, the logic for what kind of data is supported as a part of a 'registration', and how it should be saved, should really be included in the services of the registrationcore module, not in the controller of the registrationapp module.
The recent addition of a new registration method in registrationcore:
RegistrationCoreService"registerPatient(RegistrationData)" makes this relatively straight-forward and backwards-compatible. We simply need to add the relevant data that we wish to be able to save to the RegistrationData bean, and then move the logic into the registrationcore service method from the registrationapp controller to save this. Since this method is Transactional at the Service layer, this should (hopefully) solve the issue.
(NOTE: In an initial quick spike to solve this with manual transactions a few weeks ago, I ran into some mysql lock issues as a result of the NamePhoneticsHibernateInterceptor, so any possible solution needs to ensure this scenario is tested)