Closes #2378 - Add DeleteHistoryEvent for Task

This commit is contained in:
jamesrdi 2023-09-14 17:48:02 +02:00
parent 9aebda65b7
commit a4e8fbbe64
7 changed files with 174 additions and 7 deletions

View File

@ -40,7 +40,8 @@ public class ObjectAttributeChangeDetector {
// this has to be checked after we deal with List data types, because
// we want to allow different implementations of the List interface to work as well.
if (!oldObject.getClass().equals(newObject.getClass())) {
if (!oldObject.getClass().equals(newObject.getClass())
&& !oldObject.getClass().isAssignableFrom(newObject.getClass())) {
throw new SystemException(
String.format(
"The classes differ between the oldObject(%s) and newObject(%s). "

View File

@ -91,7 +91,12 @@
<version>${version.oracle}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>pro.taskana</groupId>
<artifactId>taskana-test-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,121 @@
package acceptance.events.task;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import pro.taskana.classification.api.ClassificationService;
import pro.taskana.classification.api.models.ClassificationSummary;
import pro.taskana.common.api.TaskanaEngine;
import pro.taskana.common.test.security.JaasExtension;
import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.simplehistory.impl.SimpleHistoryServiceImpl;
import pro.taskana.spi.history.api.TaskanaHistory;
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent;
import pro.taskana.spi.history.api.events.task.TaskHistoryEventType;
import pro.taskana.task.api.TaskService;
import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.models.Task;
import pro.taskana.testapi.DefaultTestEntities;
import pro.taskana.testapi.TaskanaInject;
import pro.taskana.testapi.TaskanaIntegrationTest;
import pro.taskana.testapi.WithServiceProvider;
import pro.taskana.testapi.builder.TaskBuilder;
import pro.taskana.workbasket.api.WorkbasketService;
import pro.taskana.workbasket.api.models.WorkbasketSummary;
@WithServiceProvider(
serviceProviderInterface = TaskanaHistory.class,
serviceProviders = SimpleHistoryServiceImpl.class)
@TaskanaIntegrationTest
@ExtendWith(JaasExtension.class)
class CreateHistoryEventOnTaskDeletionAccTest {
@TaskanaInject TaskanaEngine taskanaEngine;
@TaskanaInject TaskService taskService;
@TaskanaInject WorkbasketService workbasketService;
@TaskanaInject ClassificationService classificationService;
ClassificationSummary defaultClassificationSummary;
WorkbasketSummary defaultWorkbasketSummary;
Task task1;
Task task2;
Task task3;
Task task4;
SimpleHistoryServiceImpl historyService;
@WithAccessId(user = "admin")
@BeforeAll
void setUp() throws Exception {
historyService = new SimpleHistoryServiceImpl();
historyService.initialize(taskanaEngine);
defaultClassificationSummary =
DefaultTestEntities.defaultTestClassification()
.buildAndStoreAsSummary(classificationService);
defaultWorkbasketSummary =
DefaultTestEntities.defaultTestWorkbasket().buildAndStoreAsSummary(workbasketService);
task1 = createTask().buildAndStore(taskService);
task2 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
task3 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
task4 = createTask().state(TaskState.COMPLETED).buildAndStore(taskService);
}
@WithAccessId(user = "admin")
@Test
void should_CreateDeleteHistoryEvent_When_TaskIsDeleted() throws Exception {
historyService.deleteHistoryEventsByTaskIds(List.of(task4.getId()));
taskService.deleteTask(task4.getId());
List<TaskHistoryEvent> events =
historyService.createTaskHistoryQuery().taskIdIn(task4.getId()).list();
assertThat(events).hasSize(1);
assertDeleteHistoryEvent(events.get(0).getId(), "admin", task4.getId());
}
@WithAccessId(user = "admin")
@Test
void should_CreateDeleteHistoryEvent_When_TaskIsForceDeleted() throws Exception {
historyService.deleteHistoryEventsByTaskIds(List.of(task1.getId()));
taskService.forceDeleteTask(task1.getId());
List<TaskHistoryEvent> events =
historyService.createTaskHistoryQuery().taskIdIn(task1.getId()).list();
assertThat(events).hasSize(1);
assertDeleteHistoryEvent(events.get(0).getId(), "admin", task1.getId());
}
@WithAccessId(user = "admin")
@Test
void should_CreateDeleteHistoryEvents_When_MultipleTasksAreDeleted() throws Exception {
List<String> taskIds = List.of(task2.getId(), task3.getId());
historyService.deleteHistoryEventsByTaskIds(taskIds);
taskService.deleteTasks(taskIds);
TaskHistoryEvent eventTask2 =
historyService.createTaskHistoryQuery().taskIdIn(task2.getId()).single();
TaskHistoryEvent eventTask3 =
historyService.createTaskHistoryQuery().taskIdIn(task3.getId()).single();
assertDeleteHistoryEvent(eventTask2.getId(), "admin", task2.getId());
assertDeleteHistoryEvent(eventTask3.getId(), "admin", task3.getId());
}
private void assertDeleteHistoryEvent(String eventId, String expectedUser, String taskId)
throws Exception {
TaskHistoryEvent event = historyService.getTaskHistoryEvent(eventId);
assertThat(event.getUserId()).isEqualTo(expectedUser);
assertThat(event.getEventType()).isEqualTo(TaskHistoryEventType.DELETED.getName());
assertThat(event.getTaskId()).isEqualTo(taskId);
}
private TaskBuilder createTask() {
return TaskBuilder.newTask()
.classificationSummary(defaultClassificationSummary)
.workbasketSummary(defaultWorkbasketSummary)
.primaryObjRef(DefaultTestEntities.defaultTestObjectReference().build());
}
}

View File

@ -15,6 +15,7 @@ import pro.taskana.common.test.security.WithAccessId;
import pro.taskana.simplehistory.impl.TaskHistoryQueryImpl;
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent;
import pro.taskana.spi.history.api.events.task.TaskHistoryEventType;
import pro.taskana.task.api.exceptions.TaskNotFoundException;
@ExtendWith(JaasExtension.class)
@ -47,7 +48,8 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
listEvents =
taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskid));
assertThat(listEvents).isEmpty();
assertThat(listEvents).hasSize(1);
assertThat(listEvents.get(0).getEventType()).isEqualTo(TaskHistoryEventType.DELETED.getName());
}
@Test
@ -87,7 +89,9 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl)
historyService.createTaskHistoryQuery().taskIdIn(taskId_1, taskId_2));
assertThat(listEvents).isEmpty();
assertThat(listEvents).hasSize(2);
assertThat(listEvents.get(0).getEventType()).isEqualTo(TaskHistoryEventType.DELETED.getName());
assertThat(listEvents.get(1).getEventType()).isEqualTo(TaskHistoryEventType.DELETED.getName());
}
@Test
@ -119,7 +123,7 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
listEvents =
taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId));
assertThat(listEvents).hasSize(2);
assertThat(listEvents).hasSize(3);
}
@Test
@ -152,7 +156,7 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl)
historyService.createTaskHistoryQuery().taskIdIn(taskId_1, taskId_2));
assertThat(listEvents).hasSize(2);
assertThat(listEvents).hasSize(4);
}
private void createTaskanaEngineWithNewConfig(boolean deleteHistoryOnTaskDeletionEnabled)

View File

@ -0,0 +1,18 @@
package pro.taskana.spi.history.api.events.task;
import java.time.Instant;
import pro.taskana.task.api.models.TaskSummary;
public class TaskDeletedEvent extends TaskHistoryEvent {
public TaskDeletedEvent(
String id,
TaskSummary taskSummary,
String taskId,
String userId) {
super(id, taskSummary, userId, null);
eventType = TaskHistoryEventType.DELETED.getName();
created = Instant.now();
super.taskId = taskId;
}
}

View File

@ -10,7 +10,8 @@ public enum TaskHistoryEventType {
COMPLETED("COMPLETED"),
CANCELLED("CANCELLED"),
TERMINATED("TERMINATED"),
TRANSFERRED("TRANSFERRED");
TRANSFERRED("TRANSFERRED"),
DELETED("DELETED");
private String name;

View File

@ -46,6 +46,7 @@ import pro.taskana.spi.history.api.events.task.TaskClaimCancelledEvent;
import pro.taskana.spi.history.api.events.task.TaskClaimedEvent;
import pro.taskana.spi.history.api.events.task.TaskCompletedEvent;
import pro.taskana.spi.history.api.events.task.TaskCreatedEvent;
import pro.taskana.spi.history.api.events.task.TaskDeletedEvent;
import pro.taskana.spi.history.api.events.task.TaskRequestChangesEvent;
import pro.taskana.spi.history.api.events.task.TaskRequestReviewEvent;
import pro.taskana.spi.history.api.events.task.TaskTerminatedEvent;
@ -704,6 +705,9 @@ public class TaskServiceImpl implements TaskService {
.isDeleteHistoryEventsOnTaskDeletionEnabled()) {
historyEventManager.deleteEvents(taskIds);
}
if (historyEventManager.isEnabled()) {
taskIds.forEach(this::createTaskDeletedEvent);
}
}
return bulkLog;
} finally {
@ -1709,6 +1713,10 @@ public class TaskServiceImpl implements TaskService {
historyEventManager.deleteEvents(Collections.singletonList(taskId));
}
if (historyEventManager.isEnabled()) {
createTaskDeletedEvent(taskId);
}
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Task {} deleted.", taskId);
}
@ -2241,6 +2249,15 @@ public class TaskServiceImpl implements TaskService {
taskanaEngine.getEngine().getCurrentUserContext().getUserid())));
}
private void createTaskDeletedEvent(String taskId) {
historyEventManager.createEvent(
new TaskDeletedEvent(
IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_TASK_HISTORY_EVENT),
newTask().asSummary(),
taskId,
taskanaEngine.getEngine().getCurrentUserContext().getUserid()));
}
private TaskImpl duplicateTaskExactly(TaskImpl task) {
TaskImpl oldTask = task.copy();
oldTask.setId(task.getId());