Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
import uk.gov.hmcts.reform.dashboard.utilities.StringUtility;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Stream;

@Service
@Slf4j
Expand Down Expand Up @@ -83,42 +85,61 @@ public TaskListEntity updateTaskListItem(UUID taskItemIdentifier) {
}).orElseThrow(() -> new IllegalArgumentException("Invalid task item identifier " + taskItemIdentifier));
}

private void makeProgressAbleTasksInactiveForCaseIdentifierAndRole(String caseIdentifier, String role, String excludedCategory, String excludedTemplate) {
private void makeProgressAbleTasksInactiveForCaseIdentifierAndRole(String caseIdentifier, String role, List<String> excludedCategories, String excludedTemplate) {
log.info(
"makeProgressAbleTasksInactiveForCaseIdentifierAndRole caseIdentifier:{} role: {} excludedCategory: {} excludedTemplate: {}",
"makeProgressAbleTasksInactiveForCaseIdentifierAndRole caseIdentifier:{} role: {} excludedCategories: {} excludedTemplate: {}",
caseIdentifier,
role,
excludedCategory,
excludedCategories,
excludedTemplate
);
List<TaskListEntity> tasks = new ArrayList<>();
if (Objects.nonNull(excludedCategory)) {
List<TaskItemTemplateEntity> categories = taskItemTemplateRepository.findByCategoryEnAndRole(
excludedCategory,
role
);
if (Objects.nonNull(categories)) {
List<Long> catIds = categories.stream().map(TaskItemTemplateEntity::getId).toList();
List<Integer> statusesToSkip = List.of(
TaskStatus.AVAILABLE.getPlaceValue(),
TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
);
if (Objects.nonNull(excludedCategories) && !excludedCategories.isEmpty()) {
List<Long> catIds = excludedCategories.stream()
.filter(Objects::nonNull)
.flatMap(category -> {
List<TaskItemTemplateEntity> templates = taskItemTemplateRepository.findByCategoryEnAndRole(
category,
role
);
return Objects.nonNull(templates) ? templates.stream() : Stream.of();
})
.map(TaskItemTemplateEntity::getId)
.distinct()
.toList();
if (!catIds.isEmpty()) {
tasks = taskListRepository.findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotInAndTaskItemTemplate_IdNotIn(
caseIdentifier, role, List.of(
TaskStatus.AVAILABLE.getPlaceValue(), TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
), catIds
caseIdentifier,
role,
statusesToSkip,
catIds
);
} else {
log.info("No task templates found for categories {} and role {} - defaulting to all progressable tasks",
excludedCategories, role);
tasks = taskListRepository.findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotIn(
caseIdentifier,
role,
statusesToSkip
);
}
} else if (Objects.nonNull(excludedTemplate)) {
tasks = taskListRepository.findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotInAndTaskItemTemplateTemplateNameNot(
caseIdentifier, role, List.of(
TaskStatus.AVAILABLE.getPlaceValue(), TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
), excludedTemplate
caseIdentifier,
role,
statusesToSkip,
excludedTemplate
);
} else {
tasks = taskListRepository.findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotIn(
caseIdentifier, role, List.of(
TaskStatus.AVAILABLE.getPlaceValue(), TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
)
caseIdentifier,
role,
statusesToSkip
);
}
tasks.forEach(t -> {
Expand All @@ -143,16 +164,16 @@ public void makeProgressAbleTasksInactiveForCaseIdentifierAndRole(String caseIde
caseIdentifier,
role
);
makeProgressAbleTasksInactiveForCaseIdentifierAndRole(caseIdentifier, role, null, null);
makeProgressAbleTasksInactiveForCaseIdentifierAndRole(caseIdentifier, role, List.of(), null);
}

@Transactional
public void makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingCategory(String caseIdentifier, String role, String excludedCategory) {
public void makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingCategory(String caseIdentifier, String role, String... excludedCategories) {
log.info(
"makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingCategory caseIdentifier:{} role: {} excludedCategory: {}",
caseIdentifier, role, excludedCategory
"makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingCategory caseIdentifier:{} role: {} excludedCategories: {}",
caseIdentifier, role, Arrays.toString(excludedCategories)
);
makeProgressAbleTasksInactiveForCaseIdentifierAndRole(caseIdentifier, role, excludedCategory, null);
makeProgressAbleTasksInactiveForCaseIdentifierAndRole(caseIdentifier, role, normaliseCategories(excludedCategories), null);
}

@Transactional
Expand All @@ -161,7 +182,7 @@ public void makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingTempla
"makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingTemplate caseIdentifier:{} role: {} excludedTemplate: {}",
caseIdentifier, role, excludedTemplate
);
makeProgressAbleTasksInactiveForCaseIdentifierAndRole(caseIdentifier, role, null, excludedTemplate);
makeProgressAbleTasksInactiveForCaseIdentifierAndRole(caseIdentifier, role, List.of(), excludedTemplate);
}

@Transactional
Expand All @@ -188,4 +209,14 @@ private void makeViewDocumentTaskAvailable(String caseIdentifier, String role) {
taskListRepository.save(task);
});
}

private List<String> normaliseCategories(String... categories) {
if (categories == null || categories.length == 0) {
return List.of();
}
return Arrays.stream(categories)
.filter(Objects::nonNull)
.filter(category -> !category.isBlank())
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
Expand All @@ -26,6 +28,8 @@
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
Expand All @@ -45,6 +49,11 @@ class TaskListServiceTest {
@InjectMocks
private TaskListService taskListService;

@BeforeEach
void resetMocks() {
reset(taskListRepository, taskItemTemplateRepository);
}

@Test
void shouldReturnEmpty_whenTaskListIsNotPresent() {

Expand Down Expand Up @@ -120,9 +129,7 @@ void shouldThrowExceptionWhenExceptionInGetTaskList() {
//then
assertThrows(
RuntimeException.class,
() -> {
taskListRepository.findByReferenceAndTaskItemTemplateRole(any(), any());
}
() -> taskListRepository.findByReferenceAndTaskItemTemplateRole(any(), any())
);

}
Expand Down Expand Up @@ -337,13 +344,13 @@ void shouldMakeProgressAbleTaskListInactive_Except_Ga_whenTaskListIsPresent() {
TaskStatus.AVAILABLE.getPlaceValue(), TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
),
List.of(Long.valueOf(123))
List.of(123L)
))
.thenReturn(tasks);

List<TaskItemTemplateEntity> categories = new ArrayList<>();
categories.add(TaskItemTemplateEntity.builder()
.id(Long.valueOf(123)).taskNameCy("TaskNameCy")
.id(123L).taskNameCy("TaskNameCy")
.taskNameEn("TaskNameEn")
.scenarioName("Scenario.hearing")
.templateName("Hearing.view")
Expand Down Expand Up @@ -372,7 +379,7 @@ void shouldMakeProgressAbleTaskListInactive_Except_Ga_whenTaskListIsPresent() {
TaskStatus.AVAILABLE.getPlaceValue(), TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
),
List.of(Long.valueOf(123))
List.of(123L)
);

verify(taskListRepository, atLeast(5)).save(ArgumentMatchers.argThat(
Expand All @@ -394,6 +401,138 @@ void shouldMakeProgressAbleTaskListInactive_Except_Ga_whenTaskListIsPresent() {
));
}

@Test
void shouldMakeProgressAbleTaskListInactiveForMultipleCategories_whenTaskListIsPresent() {

List<TaskListEntity> tasks = new ArrayList<>();
tasks.add(getTaskListEntity(UUID.randomUUID()).toBuilder()
.currentStatus(TaskStatus.ACTION_NEEDED.getPlaceValue())
.taskNameEn("<a href=\"somewhere\">Link name</A >")
.taskNameCy("<A href=\"somewhere\">Link name Welsh</A>")
.build());

when(taskListRepository.findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotInAndTaskItemTemplate_IdNotIn(
"123", "Claimant",
List.of(
TaskStatus.AVAILABLE.getPlaceValue(), TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
),
List.of(123L, 456L)
)).thenReturn(tasks);

List<TaskItemTemplateEntity> categoryA = List.of(TaskItemTemplateEntity.builder().id(123L).role("Claimant").build());
List<TaskItemTemplateEntity> categoryB = List.of(TaskItemTemplateEntity.builder().id(456L).role("Claimant").build());

when(taskItemTemplateRepository.findByCategoryEnAndRole("CategoryA", "Claimant")).thenReturn(categoryA);
when(taskItemTemplateRepository.findByCategoryEnAndRole("CategoryB", "Claimant")).thenReturn(categoryB);

taskListService.makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingCategory(
"123",
"Claimant",
"CategoryA",
"CategoryB"
);

verify(taskItemTemplateRepository).findByCategoryEnAndRole("CategoryA", "Claimant");
verify(taskItemTemplateRepository).findByCategoryEnAndRole("CategoryB", "Claimant");
verify(taskListRepository).findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotInAndTaskItemTemplate_IdNotIn(
"123", "Claimant",
List.of(
TaskStatus.AVAILABLE.getPlaceValue(), TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
),
List.of(123L, 456L)
);
}

@Test
void shouldFallbackToDefaultProgressQueryWhenCategoryTemplatesMissing() {
List<TaskListEntity> tasks = List.of(getTaskListEntity(UUID.randomUUID()).toBuilder()
.currentStatus(TaskStatus.IN_PROGRESS.getPlaceValue())
.build());

when(taskItemTemplateRepository.findByCategoryEnAndRole("CategoryEn", "Claimant")).thenReturn(List.of());
when(taskListRepository.findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotIn(
"123",
"Claimant",
List.of(
TaskStatus.AVAILABLE.getPlaceValue(),
TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
)
)).thenReturn(tasks);

taskListService.makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingCategory(
"123",
"Claimant",
"CategoryEn"
);

verify(taskItemTemplateRepository).findByCategoryEnAndRole("CategoryEn", "Claimant");
verify(taskListRepository).findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotIn(
"123",
"Claimant",
List.of(
TaskStatus.AVAILABLE.getPlaceValue(),
TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
)
);
verify(taskListRepository, never()).findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotInAndTaskItemTemplate_IdNotIn(
any(),
any(),
any(),
any()
);
verify(taskListRepository, atLeast(1)).save(ArgumentMatchers.argThat(
a -> a.getCurrentStatus() == TaskStatus.INACTIVE.getPlaceValue()
));
}

@Test
void shouldTreatEmptyExcludedCategoriesAsNoExclusions() {
List<TaskListEntity> tasks = List.of(getTaskListEntity(UUID.randomUUID()).toBuilder()
.currentStatus(TaskStatus.ACTION_NEEDED.getPlaceValue())
.build());

when(taskListRepository.findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotIn(
"123",
"Claimant",
List.of(
TaskStatus.AVAILABLE.getPlaceValue(),
TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
)
)).thenReturn(tasks);

taskListService.makeProgressAbleTasksInactiveForCaseIdentifierAndRoleExcludingCategory(
"123",
"Claimant",
null,
" "
);

verify(taskItemTemplateRepository, never()).findByCategoryEnAndRole(any(), any());
verify(taskListRepository).findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotIn(
"123",
"Claimant",
List.of(
TaskStatus.AVAILABLE.getPlaceValue(),
TaskStatus.DONE.getPlaceValue(),
TaskStatus.NOT_AVAILABLE_YET.getPlaceValue()
)
);
verify(taskListRepository, never()).findByReferenceAndTaskItemTemplateRoleAndCurrentStatusNotInAndTaskItemTemplate_IdNotIn(
any(),
any(),
any(),
any()
);
verify(taskListRepository, atLeast(1)).save(ArgumentMatchers.argThat(
a -> a.getCurrentStatus() == TaskStatus.INACTIVE.getPlaceValue()
));
}

@Test
public void shouldDeleteWhenThereWereDuplicateEntriesInTheRepository() {
TaskListEntity task = getTaskListEntity(UUID.randomUUID()).toBuilder()
Expand Down Expand Up @@ -442,8 +581,8 @@ void shouldMakeProgressAbleTaskListActiveExcludingTemplate() {
//given
List<TaskListEntity> tasks = new ArrayList<>();
tasks.add(getTaskListEntity(UUID.randomUUID()).toBuilder()
.taskNameEn("<a href=\"somewhere\">Link name</A >")
.taskNameCy("<A href=\"somewhere\">Link name Welsh</A>")
.taskNameEn("<a>Link name</a>")
.taskNameCy("<a>Link name Welsh</a>")
.currentStatus(TaskStatus.NOT_AVAILABLE_YET.getPlaceValue())
.build());
tasks.add(getTaskListEntity(UUID.randomUUID()).toBuilder()
Expand Down Expand Up @@ -490,6 +629,18 @@ void shouldMakeProgressAbleTaskListActiveExcludingTemplate() {
any(),
any()
);

ArgumentCaptor<TaskListEntity> captor = ArgumentCaptor.forClass(TaskListEntity.class);
verify(taskListRepository, times(2)).save(captor.capture());
List<TaskListEntity> savedTasks = captor.getAllValues();
savedTasks.forEach(saved -> {
assertThat(saved.getCurrentStatus()).isEqualTo(TaskStatus.AVAILABLE.getPlaceValue());
assertThat(saved.getNextStatus()).isEqualTo(TaskStatus.AVAILABLE.getPlaceValue());
assertThat(saved.getHintTextCy()).isEmpty();
assertThat(saved.getHintTextEn()).isEmpty();
assertThat(saved.getTaskNameEn()).isEqualTo("<a class=\"govuk-link\" href=\"{VIEW_EVIDENCE_UPLOAD_DOCUMENTS}\">Link name</a>");
assertThat(saved.getTaskNameCy()).isEqualTo("<a class=\"govuk-link\" href=\"{VIEW_EVIDENCE_UPLOAD_DOCUMENTS}\">Link name Welsh</a>");
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public abstract class DashboardScenarioService {

protected static final String DEFENDANT_ROLE = "DEFENDANT";
protected static final String CLAIMANT_ROLE = "CLAIMANT";
public static final String HEARING_TASK_CATEGORY = "Hearing";

protected DashboardScenarioService(DashboardScenariosService dashboardScenariosService,
DashboardNotificationsParamsMapper mapper) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void notifyFinalOrder(CaseData caseData, String authToken) {
@Override
protected String getScenario(CaseData caseData) {

dashboardTasksHelper.deleteNotificationAndInactiveTasksForDefendant(caseData);
dashboardTasksHelper.deleteNotificationAndInactiveTasksForClaimant(caseData, HEARING_TASK_CATEGORY);

final String scenario;

Expand Down
Loading
Loading