Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit 5292e19

Browse files
Merge pull request SORMAS-Foundation#3234 from hzi-braunschweig/feat-3217-adapt-messages
SORMAS-Foundation#3217 SORMAS-Foundation#3231 provide more detailed validation messages, update validation logic for external persons
2 parents 855f36b + 8f6f298 commit 5292e19

10 files changed

Lines changed: 109 additions & 39 deletions

File tree

sormas-api/src/main/java/de/symeda/sormas/api/externaljournal/ExternalJournalFacade.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ public interface ExternalJournalFacade {
1515

1616
RegisterResult registerPatientDiaryPerson(PersonDto person);
1717

18-
boolean isPersonExportable(PersonDto person);
18+
ExternalPersonValidation validatePatientDiaryPerson(PersonDto person);
1919
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package de.symeda.sormas.api.externaljournal;
2+
3+
import java.io.Serializable;
4+
5+
public class ExternalPersonValidation implements Serializable {
6+
7+
private boolean valid;
8+
private String message;
9+
10+
public ExternalPersonValidation(boolean valid, String message) {
11+
this.valid = valid;
12+
this.message = message;
13+
}
14+
15+
public boolean isValid() {
16+
return valid;
17+
}
18+
19+
public void setValid(boolean valid) {
20+
this.valid = valid;
21+
}
22+
23+
public String getMessage() {
24+
return message;
25+
}
26+
27+
public void setMessage(String message) {
28+
this.message = message;
29+
}
30+
}

sormas-api/src/main/java/de/symeda/sormas/api/i18n/Captions.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,6 @@ public interface Captions {
10921092
String PathogenTests = "PathogenTests";
10931093
String patientDiaryPersonNotExportable = "patientDiaryPersonNotExportable";
10941094
String patientDiaryRegistrationError = "patientDiaryRegistrationError";
1095-
String patientDiaryRegistrationSuccess = "patientDiaryRegistrationSuccess";
10961095
String Person = "Person";
10971096
String Person_address = "Person.address";
10981097
String Person_addresses = "Person.addresses";

sormas-api/src/main/java/de/symeda/sormas/api/i18n/Validations.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ public interface Validations {
3636
String emptyOverwrittenFollowUpUntilDate = "emptyOverwrittenFollowUpUntilDate";
3737
String errorsInForm = "errorsInForm";
3838
String exportNoNameSpecified = "exportNoNameSpecified";
39-
String externalJournalPersonValidation = "externalJournalPersonValidation";
39+
String externalJournalPersonValidationBirthdate = "externalJournalPersonValidationBirthdate";
40+
String externalJournalPersonValidationEmail = "externalJournalPersonValidationEmail";
41+
String externalJournalPersonValidationError = "externalJournalPersonValidationError";
42+
String externalJournalPersonValidationNoEmailOrPhone = "externalJournalPersonValidationNoEmailOrPhone";
43+
String externalJournalPersonValidationPhone = "externalJournalPersonValidationPhone";
4044
String futureDate = "futureDate";
4145
String futureDateStrict = "futureDateStrict";
4246
String importAreaAlreadyExists = "importAreaAlreadyExists";

sormas-api/src/main/resources/captions.properties

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1950,6 +1950,5 @@ BAGExport=BAG Export
19501950
SurvnetGateway.title=SurvNet
19511951
SurvnetGateway.send=send to own SurvNet instance
19521952

1953-
patientDiaryRegistrationSuccess=Successfully registered person in the patient diary.
19541953
patientDiaryRegistrationError=Could not register person in the patient diary.
19551954
patientDiaryPersonNotExportable=Cannot export the person to the patient diary. The person needs a valid birthdate and either a valid phone number or email address.

sormas-api/src/main/resources/validations.properties

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,8 @@ sormasToSormasSenderNameMissing = Sender name is missing
123123
sormasToSormasSampleExists = This sample already exists
124124
validPhoneNumber = %s must be a valid phone number
125125
validEmailAddress = %s must be a valid email address
126-
externalJournalPersonValidation = Persons exported to an external journal need a valid birthdate and either a valid phone number or email address.
126+
externalJournalPersonValidationBirthdate = Invalid birthdate.
127+
externalJournalPersonValidationEmail = Invalid email address.
128+
externalJournalPersonValidationError = Invalid data provided for person exported to external journal:
129+
externalJournalPersonValidationPhone = Invalid phone number.
130+
externalJournalPersonValidationNoEmailOrPhone = Please provide an email address or a phone number.

sormas-backend/src/main/java/de/symeda/sormas/backend/externaljournal/ExternalJournalFacadeEjb.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import de.symeda.sormas.api.externaljournal.ExternalJournalFacade;
77
import de.symeda.sormas.api.externaljournal.ExternalPatientDto;
8+
import de.symeda.sormas.api.externaljournal.ExternalPersonValidation;
89
import de.symeda.sormas.api.externaljournal.RegisterResult;
910
import de.symeda.sormas.api.person.PersonDto;
1011

@@ -35,8 +36,8 @@ public RegisterResult registerPatientDiaryPerson(PersonDto person) {
3536
}
3637

3738
@Override
38-
public boolean isPersonExportable(PersonDto person) {
39-
return externalJournalService.isPersonExportable(person);
39+
public ExternalPersonValidation validatePatientDiaryPerson(PersonDto person) {
40+
return externalJournalService.validatePatientDiaryPerson(person);
4041
}
4142

4243

sormas-backend/src/main/java/de/symeda/sormas/backend/externaljournal/ExternalJournalService.java

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import javax.ws.rs.core.MediaType;
1919
import javax.ws.rs.core.Response;
2020

21-
import de.symeda.sormas.api.externaljournal.RegisterResult;
2221
import org.apache.commons.lang3.ObjectUtils;
2322
import org.apache.commons.lang3.StringUtils;
2423
import org.apache.commons.validator.routines.EmailValidator;
@@ -37,6 +36,10 @@
3736

3837
import de.symeda.sormas.api.contact.ContactDto;
3938
import de.symeda.sormas.api.externaljournal.ExternalPatientDto;
39+
import de.symeda.sormas.api.externaljournal.ExternalPersonValidation;
40+
import de.symeda.sormas.api.externaljournal.RegisterResult;
41+
import de.symeda.sormas.api.i18n.I18nProperties;
42+
import de.symeda.sormas.api.i18n.Validations;
4043
import de.symeda.sormas.api.person.PersonDto;
4144
import de.symeda.sormas.api.person.SymptomJournalStatus;
4245
import de.symeda.sormas.backend.common.ConfigFacadeEjb;
@@ -307,22 +310,21 @@ private Invocation.Builder getExternalDataPersonInvocationBuilder(String personU
307310
}
308311

309312
/**
310-
* Check whether a person has the necessary data to be exported to the patient diary
311-
*
312-
* @param person
313-
* the person to check
314-
* @return true if the person has the necessary data, false otherwise
313+
* Check whether a person has valid data in orderd to be registered in the patient diary
314+
* @param person the person to validate
315+
* @return the result of the validation
315316
*/
316-
public boolean isPersonExportable(PersonDto person) {
317+
public ExternalPersonValidation validatePatientDiaryPerson(PersonDto person) {
317318
String email = person.getEmailAddress();
318319
String phone = person.getPhone();
319-
boolean validEmail = false;
320-
boolean validPhone = false;
320+
boolean validEmail = true;
321+
boolean validPhone = true;
321322
if (StringUtils.isNotEmpty(email)) {
322323
EmailValidator validator = EmailValidator.getInstance();
323324
validEmail = validator.isValid(email);
324325
}
325326
if (StringUtils.isNotEmpty(phone)) {
327+
validPhone = false;
326328
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
327329
try {
328330
Phonenumber.PhoneNumber germanNumberProto = phoneUtil.parse(phone, "DE");
@@ -335,6 +337,30 @@ public boolean isPersonExportable(PersonDto person) {
335337
if (ObjectUtils.anyNotNull(person.getBirthdateDD(), person.getBirthdateMM(), person.getBirthdateYYYY())) {
336338
validBirthdate = ObjectUtils.allNotNull(person.getBirthdateDD(), person.getBirthdateMM(), person.getBirthdateYYYY());
337339
}
338-
return (validEmail || validPhone) && validBirthdate;
340+
boolean hasPhoneOrEmail = !StringUtils.isAllEmpty(email, phone);
341+
boolean valid = hasPhoneOrEmail && validEmail && validPhone && validBirthdate;
342+
String message = getValidationMessage(hasPhoneOrEmail, validEmail, validPhone, validBirthdate);
343+
return new ExternalPersonValidation(valid, message);
344+
}
345+
346+
private String getValidationMessage(boolean hasPhoneOrEmail, boolean validEmail, boolean validPhone, boolean validBirthdate) {
347+
StringBuilder message = new StringBuilder();
348+
if (!hasPhoneOrEmail) {
349+
message.append(I18nProperties.getValidationError(Validations.externalJournalPersonValidationNoEmailOrPhone));
350+
message.append('\n');
351+
}
352+
if (!validEmail) {
353+
message.append(I18nProperties.getValidationError(Validations.externalJournalPersonValidationEmail));
354+
message.append('\n');
355+
}
356+
if (!validPhone) {
357+
message.append(I18nProperties.getValidationError(Validations.externalJournalPersonValidationPhone));
358+
message.append('\n');
359+
}
360+
if (!validBirthdate) {
361+
message.append(I18nProperties.getValidationError(Validations.externalJournalPersonValidationBirthdate));
362+
message.append('\n');
363+
}
364+
return message.toString();
339365
}
340366
}

sormas-backend/src/main/java/de/symeda/sormas/backend/person/PersonFacadeEjb.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import de.symeda.sormas.api.caze.CaseCriteria;
4949
import de.symeda.sormas.api.caze.CaseDataDto;
5050
import de.symeda.sormas.api.caze.CaseOutcome;
51+
import de.symeda.sormas.api.externaljournal.ExternalPersonValidation;
5152
import de.symeda.sormas.api.i18n.I18nProperties;
5253
import de.symeda.sormas.api.i18n.Validations;
5354
import de.symeda.sormas.api.location.LocationDto;
@@ -306,14 +307,14 @@ public PersonDto savePerson(PersonDto source) throws ValidationRuntimeException
306307

307308
validate(source);
308309

309-
person = fillOrBuildEntity(source, person);
310-
311-
personService.ensurePersisted(person);
312-
313310
if (existingPerson != null) {
314311
handleExternalJournalPerson(existingPerson, source);
315312
}
316313

314+
person = fillOrBuildEntity(source, person);
315+
316+
personService.ensurePersisted(person);
317+
317318
onPersonChanged(existingPerson, person);
318319

319320
return convertToDto(person, Pseudonymizer.getDefault(userService::hasRight), existingPerson == null || isPersonInJurisdiction(person));
@@ -322,8 +323,9 @@ public PersonDto savePerson(PersonDto source) throws ValidationRuntimeException
322323
private void handleExternalJournalPerson(PersonDto existingPerson, PersonDto updatedPerson) {
323324
SymptomJournalStatus status = existingPerson.getSymptomJournalStatus();
324325
if (SymptomJournalStatus.REGISTERED.equals(status) || SymptomJournalStatus.ACCEPTED.equals(status)) {
325-
if (!externalJournalService.isPersonExportable(updatedPerson)) {
326-
throw new ValidationRuntimeException(I18nProperties.getValidationError(Validations.externalJournalPersonValidation));
326+
ExternalPersonValidation validationResult = externalJournalService.validatePatientDiaryPerson(updatedPerson);
327+
if (!validationResult.isValid()) {
328+
throw new ValidationRuntimeException(validationResult.getMessage());
327329
}
328330
}
329331
// 5 second delay added before notifying of update so that current transaction can complete and new data can be retrieved from DB

sormas-ui/src/main/java/de/symeda/sormas/ui/contact/ContactController.java

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@
4545
import com.vaadin.ui.Image;
4646
import com.vaadin.ui.Label;
4747
import com.vaadin.ui.VerticalLayout;
48+
import de.symeda.sormas.api.externaljournal.ExternalPersonValidation;
4849
import de.symeda.sormas.api.externaljournal.RegisterResult;
50+
import de.symeda.sormas.api.i18n.Validations;
4951
import de.symeda.sormas.api.person.SymptomJournalStatus;
5052
import de.symeda.sormas.ui.utils.CssStyles;
5153
import org.jsoup.Jsoup;
@@ -560,8 +562,9 @@ private byte[] createSymptomJournalForm(String formUrl, Map<String, String> inpu
560562
* Displays the result in a popup
561563
*/
562564
public void registerPatientDiaryPerson(PersonDto person) {
563-
if (!externalJournalFacade.isPersonExportable(person)) {
564-
showWarningPopup(I18nProperties.getCaption(Captions.patientDiaryPersonNotExportable));
565+
ExternalPersonValidation validationResult = externalJournalFacade.validatePatientDiaryPerson(person);
566+
if (!validationResult.isValid()) {
567+
showPatientDiaryWarningPopup(validationResult.getMessage());
565568
} else {
566569
if (SymptomJournalStatus.ACCEPTED.equals(person.getSymptomJournalStatus())
567570
|| SymptomJournalStatus.REGISTERED.equals(person.getSymptomJournalStatus())) {
@@ -579,18 +582,21 @@ private void openPatientDiaryEnrollPage(String personUuid) {
579582
UI.getCurrent().getPage().open(url, "_blank");
580583
}
581584

582-
private void showWarningPopup(String message) {
583-
VerticalLayout alreadyRegisteredLayout = new VerticalLayout();
584-
alreadyRegisteredLayout.setMargin(true);
585+
private void showPatientDiaryWarningPopup(String message) {
586+
VerticalLayout warningLayout = new VerticalLayout();
587+
warningLayout.setMargin(true);
585588
Image warningIcon = new Image(null, new ThemeResource("img/warning-icon.png"));
586589
warningIcon.setHeight(35, Unit.PIXELS);
587590
warningIcon.setWidth(35, Unit.PIXELS);
588-
alreadyRegisteredLayout.addComponentAsFirst(warningIcon);
589-
Window popupWindow = VaadinUiUtil.showPopupWindow(alreadyRegisteredLayout);
591+
warningLayout.addComponentAsFirst(warningIcon);
592+
Window popupWindow = VaadinUiUtil.showPopupWindow(warningLayout);
593+
Label messageLabel = new Label(I18nProperties.getValidationError(Validations.externalJournalPersonValidationError));
594+
CssStyles.style(messageLabel, CssStyles.LABEL_LARGE, CssStyles.LABEL_WHITE_SPACE_NORMAL);
595+
warningLayout.addComponent(messageLabel);
590596
Label infoLabel = new Label(message);
591597
CssStyles.style(infoLabel, CssStyles.LABEL_LARGE, CssStyles.LABEL_WHITE_SPACE_NORMAL);
592-
alreadyRegisteredLayout.addComponent(infoLabel);
593-
CssStyles.style(alreadyRegisteredLayout, CssStyles.ALIGN_CENTER);
598+
warningLayout.addComponent(infoLabel);
599+
CssStyles.style(warningLayout, CssStyles.ALIGN_CENTER);
594600
popupWindow.addCloseListener(e -> popupWindow.close());
595601
popupWindow.setWidth(400, Unit.PIXELS);
596602
}
@@ -604,22 +610,21 @@ private void showPatientRegisterResultPopup(RegisterResult registerResult) {
604610
Image successIcon = new Image(null, new ThemeResource("img/success-icon.png"));
605611
successIcon.setHeight(35, Unit.PIXELS);
606612
successIcon.setWidth(35, Unit.PIXELS);
607-
Label infoLabel = new Label();
608-
CssStyles.style(infoLabel, CssStyles.LABEL_LARGE, CssStyles.LABEL_WHITE_SPACE_NORMAL);
609-
registrationResultLayout.addComponent(infoLabel);
610-
Label messageLabel = new Label();
611-
CssStyles.style(messageLabel, CssStyles.LABEL_LARGE, CssStyles.LABEL_WHITE_SPACE_NORMAL);
612-
registrationResultLayout.addComponent(messageLabel);
613613
CssStyles.style(registrationResultLayout, CssStyles.ALIGN_CENTER);
614614
if (registerResult.isSuccess()) {
615615
registrationResultLayout.removeComponent(errorIcon);
616616
registrationResultLayout.addComponentAsFirst(successIcon);
617-
infoLabel.setValue(I18nProperties.getCaption(Captions.patientDiaryRegistrationSuccess));
618617
} else {
619618
registrationResultLayout.removeComponent(successIcon);
620619
registrationResultLayout.addComponentAsFirst(errorIcon);
620+
Label infoLabel = new Label();
621+
CssStyles.style(infoLabel, CssStyles.LABEL_LARGE, CssStyles.LABEL_WHITE_SPACE_NORMAL);
622+
registrationResultLayout.addComponent(infoLabel);
621623
infoLabel.setValue(I18nProperties.getCaption(Captions.patientDiaryRegistrationError));
622624
}
625+
Label messageLabel = new Label();
626+
CssStyles.style(messageLabel, CssStyles.LABEL_LARGE, CssStyles.LABEL_WHITE_SPACE_NORMAL);
627+
registrationResultLayout.addComponent(messageLabel);
623628
messageLabel.setValue(registerResult.getMessage());
624629
Window popupWindow = VaadinUiUtil.showPopupWindow(registrationResultLayout);
625630
popupWindow.addCloseListener(e -> popupWindow.close());

0 commit comments

Comments
 (0)