Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -127,22 +127,15 @@ public enum DocumentWorkflow {
ROOT_TRAVEL_ENTRY,
ROOT_PERSON,
ROOT_USER),
SURVEY_DOCUMENT(DocumentWorkflowType.DOCUMENT,
"survey",
DOCX,
UserRight.SURVEY_EDIT,
ROOT_CASE,
ROOT_PERSON,
ROOT_USER,
ROOT_SAMPLE),
SURVEY_DOCUMENT(DocumentWorkflowType.DOCUMENT, "survey", DOCX, UserRight.SURVEY_EDIT, ROOT_CASE, ROOT_PERSON, ROOT_USER, ROOT_SAMPLE),
SURVEY_EMAIL(DocumentWorkflowType.EMAIL,
Constants.EMAIL_TEMPLATES_FOLDER + "/surveys",
TXT,
UserRight.SURVEY_EDIT,
ROOT_CASE,
ROOT_PERSON,
ROOT_USER,
ROOT_SAMPLE),;
Constants.EMAIL_TEMPLATES_FOLDER + "/surveys",
TXT,
UserRight.SURVEY_EDIT,
ROOT_CASE,
ROOT_PERSON,
ROOT_USER,
ROOT_SAMPLE),;

private final DocumentWorkflowType type;
private final String templateDirectory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
import de.symeda.sormas.api.sormastosormas.ShareTreeCriteria;
import de.symeda.sormas.api.sormastosormas.SormasToSormasException;
import de.symeda.sormas.api.sormastosormas.SormasToSormasRuntimeException;
import de.symeda.sormas.api.survey.SurveyTokenCriteria;
import de.symeda.sormas.api.symptoms.SymptomsDto;
import de.symeda.sormas.api.symptoms.SymptomsHelper;
import de.symeda.sormas.api.task.TaskContext;
Expand Down Expand Up @@ -330,6 +331,8 @@
import de.symeda.sormas.backend.sormastosormas.share.outgoing.ShareRequestInfoService;
import de.symeda.sormas.backend.sormastosormas.share.outgoing.SormasToSormasShareInfo;
import de.symeda.sormas.backend.specialcaseaccess.SpecialCaseAccessService;
import de.symeda.sormas.backend.survey.SurveyToken;
import de.symeda.sormas.backend.survey.SurveyTokenService;
import de.symeda.sormas.backend.symptoms.Symptoms;
import de.symeda.sormas.backend.symptoms.SymptomsFacadeEjb;
import de.symeda.sormas.backend.symptoms.SymptomsFacadeEjb.SymptomsFacadeEjbLocal;
Expand Down Expand Up @@ -517,6 +520,8 @@ public class CaseFacadeEjb extends AbstractCoreFacadeEjb<Case, CaseDataDto, Case
private ImmunizationService immunizationService;
@EJB
private ImmunizationFacadeEjb.ImmunizationFacadeEjbLocal immunizationFacade;
@EJB
private SurveyTokenService surveyService;

@Resource
private ManagedScheduledExecutorService executorService;
Expand Down Expand Up @@ -4081,6 +4086,16 @@ private void mergeCase(CaseDataDto leadCaseData, CaseDataDto otherCaseData, bool
t.setPerson(leadCase.getPerson());
travelEntryService.ensurePersisted(t);
});

// Including survey token for merge case.
// 11. servey token reference
if (!cloning) {
List<SurveyToken> tokens = surveyService.findBy(new SurveyTokenCriteria().caseAssignedTo(otherCase.toReference()));
tokens.forEach(s -> {
s.setCaseAssignedTo(leadCase);
surveyService.ensurePersisted(s);
});
}
}

private void copyDtoValues(CaseDataDto leadCaseData, CaseDataDto otherCaseData, boolean cloning) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

package de.symeda.sormas.backend.survey;

import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.criteria.CriteriaBuilder;
Expand Down Expand Up @@ -101,6 +103,26 @@ public SurveyToken getToken(SurveyTokenCriteria criteria) {
return QueryHelper.getFirstResult(em, cq);
}

/**
* Finds survey tokens based on the provided criteria. The results are ordered by assignment date in descending order.
*
* @param criteria
* @return List<SurveyToken>
*/
public List<SurveyToken> findBy(SurveyTokenCriteria criteria) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<SurveyToken> cq = cb.createQuery(SurveyToken.class);
Root<SurveyToken> root = cq.from(SurveyToken.class);
cq.select(root);
Predicate filter = CriteriaBuilderHelper.and(cb, this.buildCriteriaFilter(criteria, cb, root, new SurveyTokenJoins(root)));
if (filter != null) {
cq.where(filter);
}
cq.orderBy(cb.desc(root.get(SurveyToken.ASSIGNMENT_DATE)));

return em.createQuery(cq).getResultList();
}

public SurveyToken getBySurveyAndToken(SurveyReferenceDto survey, String token) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<SurveyToken> cq = cb.createQuery(SurveyToken.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@
import de.symeda.sormas.api.sormastosormas.share.incoming.ShareRequestStatus;
import de.symeda.sormas.api.specialcaseaccess.SpecialCaseAccessDto;
import de.symeda.sormas.api.survey.SurveyDto;
import de.symeda.sormas.api.survey.SurveyTokenDto;
import de.symeda.sormas.api.systemevents.SystemEventDto;
import de.symeda.sormas.api.systemevents.SystemEventStatus;
import de.symeda.sormas.api.systemevents.SystemEventType;
Expand Down Expand Up @@ -2476,6 +2477,19 @@ public SurveyDto createSurvey(String name, Disease disease) {
return beanTest.getSurveyFacade().save(survey);
}

/**
*
* @param caze
* @return
*/
public SurveyTokenDto createSurveyToken(CaseReferenceDto caze) {
SurveyDto survey = this.createSurvey("Malaria-Survey", Disease.MALARIA);
SurveyTokenDto token = SurveyTokenDto.build(survey.toReference());
token.setToken("MALA01");
token.setCaseAssignedTo(caze);
return beanTest.getSurveyTokenFacade().save(token);
}

public NotifierDto createNotifier(String firstName, String lastName, String email, String phone, String address, String registrationNumber) {
NotifierDto notifier = new NotifierDto();
notifier.setFirstName(firstName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* SORMAS® - Surveillance Outbreak Response Management & Analysis System
* Copyright © 2016-2026 SORMAS Foundation gGmbH
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.symeda.sormas.backend.survey;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.is;

import java.util.List;

import org.junit.jupiter.api.Test;

import de.symeda.sormas.api.Disease;
import de.symeda.sormas.api.caze.CaseDataDto;
import de.symeda.sormas.api.survey.SurveyTokenCriteria;
import de.symeda.sormas.api.user.UserDto;
import de.symeda.sormas.backend.AbstractBeanTest;
import de.symeda.sormas.backend.TestDataCreator;

/**
* Test class for testing the SurveyService.
*/
public class SurveyServiceTest extends AbstractBeanTest {

private UserDto surveillanceOfficer;
private TestDataCreator.RDCF rdcf;

/**
* @see AbstractBeanTest#init()
* Initializing the primary data for the test.
*/
@Override
public void init() {
super.init();
rdcf = creator.createRDCF("Region", "District", "Community", "Facility");
surveillanceOfficer = creator.createSurveillanceOfficer(rdcf);
}

/**
* Test method for {@link de.symeda.sormas.backend.survey.SurveyService#findBy(de.symeda.sormas.api.survey.SurveyTokenCriteria)}.
*
*/
@Test
public void testSurveyTokens() {
CaseDataDto caze = creator.createCase(surveillanceOfficer.toReference(), rdcf, (c) -> {
c.setDisease(Disease.MALARIA);
});
creator.createSurveyToken(caze.toReference());
List<SurveyToken> tokenList = getSurveyTokenService().findBy(new SurveyTokenCriteria());
assertThat(tokenList.size(), is(greaterThan(0)));
assertThat(tokenList.get(0).getToken(), is(equalTo("MALA01")));
}
Comment on lines +52 to +65

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Test may be flaky due to unfiltered query and incorrect Javadoc reference.

  1. Incorrect Javadoc: Line 53 references SurveyService#findBy but the actual method being tested is SurveyTokenService#findBy.

  2. Test isolation concern: Using new SurveyTokenCriteria() returns ALL survey tokens in the database (per SurveyTokenService.buildCriteriaFilter which returns null when all criteria fields are null). If other tests in the suite create tokens, this test could:

    • Pass assertion at Line 63 (size > 0) but for the wrong reason
    • Fail assertion at Line 64 if another token with a newer ASSIGNMENT_DATE appears first

Consider filtering by the created case or survey to ensure test isolation:

🛡️ Suggested fix for test isolation
 /**
- * Test method for {`@link` de.symeda.sormas.backend.survey.SurveyService#findBy(de.symeda.sormas.api.survey.SurveyTokenCriteria)}.
+ * Test method for {`@link` de.symeda.sormas.backend.survey.SurveyTokenService#findBy(de.symeda.sormas.api.survey.SurveyTokenCriteria)}.
  * 
  */
 `@Test`
 public void testSurveyTokens() {
 	CaseDataDto caze = creator.createCase(surveillanceOfficer.toReference(), rdcf, (c) -> {
 		c.setDisease(Disease.MALARIA);
 	});
-	creator.createSurveyToken(caze.toReference());
-	List<SurveyToken> tokenList = getSurveyTokenService().findBy(new SurveyTokenCriteria());
+	SurveyTokenDto createdToken = creator.createSurveyToken(caze.toReference());
+	SurveyTokenCriteria criteria = new SurveyTokenCriteria();
+	criteria.setCaseAssignedTo(caze.toReference());
+	List<SurveyToken> tokenList = getSurveyTokenService().findBy(criteria);
 	assertThat(tokenList.size(), is(greaterThan(0)));
 	assertThat(tokenList.get(0).getToken(), is(equalTo("MALA01")));
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@sormas-backend/src/test/java/de/symeda/sormas/backend/survey/SurveyServiceTest.java`
around lines 52 - 65, The test has two issues: the Javadoc incorrectly
references SurveyService#findBy (update it to SurveyTokenService#findBy) and the
query uses new SurveyTokenCriteria() which returns all tokens causing flaky
ordering; fix by populating the criteria with the created case reference (use
the appropriate setter on SurveyTokenCriteria, e.g.,
setCaseRef(caze.toReference()) or equivalent) before calling
getSurveyTokenService().findBy so the result is limited to the token created by
creator.createSurveyToken(caze.toReference()) and update assertions accordingly.

}
Loading