Closes #2378 - Add DeleteHistoryEvent for Task

This commit is contained in:
jamesrdi 2023-09-14 17:48:02 +02:00 committed by Elena Mokeeva
parent 5b04d2ca74
commit dee57ab1af
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 // 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. // 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( throw new SystemException(
String.format( String.format(
"The classes differ between the oldObject(%s) and newObject(%s). " "The classes differ between the oldObject(%s) and newObject(%s). "

View File

@ -91,7 +91,12 @@
<version>${version.oracle}</version> <version>${version.oracle}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>pro.taskana</groupId>
<artifactId>taskana-test-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </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.TaskHistoryQueryImpl;
import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper; import pro.taskana.simplehistory.impl.task.TaskHistoryQueryMapper;
import pro.taskana.spi.history.api.events.task.TaskHistoryEvent; 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; import pro.taskana.task.api.exceptions.TaskNotFoundException;
@ExtendWith(JaasExtension.class) @ExtendWith(JaasExtension.class)
@ -47,7 +48,8 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
listEvents = listEvents =
taskHistoryQueryMapper.queryHistoryEvents( taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskid)); (TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskid));
assertThat(listEvents).isEmpty(); assertThat(listEvents).hasSize(1);
assertThat(listEvents.get(0).getEventType()).isEqualTo(TaskHistoryEventType.DELETED.getName());
} }
@Test @Test
@ -87,7 +89,9 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
taskHistoryQueryMapper.queryHistoryEvents( taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) (TaskHistoryQueryImpl)
historyService.createTaskHistoryQuery().taskIdIn(taskId_1, taskId_2)); 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 @Test
@ -119,7 +123,7 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
listEvents = listEvents =
taskHistoryQueryMapper.queryHistoryEvents( taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId)); (TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId));
assertThat(listEvents).hasSize(2); assertThat(listEvents).hasSize(3);
} }
@Test @Test
@ -152,7 +156,7 @@ class DeleteHistoryEventsOnTaskDeletionAccTest extends AbstractAccTest {
taskHistoryQueryMapper.queryHistoryEvents( taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) (TaskHistoryQueryImpl)
historyService.createTaskHistoryQuery().taskIdIn(taskId_1, taskId_2)); historyService.createTaskHistoryQuery().taskIdIn(taskId_1, taskId_2));
assertThat(listEvents).hasSize(2); assertThat(listEvents).hasSize(4);
} }
private void createTaskanaEngineWithNewConfig(boolean deleteHistoryOnTaskDeletionEnabled) 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"), COMPLETED("COMPLETED"),
CANCELLED("CANCELLED"), CANCELLED("CANCELLED"),
TERMINATED("TERMINATED"), TERMINATED("TERMINATED"),
TRANSFERRED("TRANSFERRED"); TRANSFERRED("TRANSFERRED"),
DELETED("DELETED");
private String name; 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.TaskClaimedEvent;
import pro.taskana.spi.history.api.events.task.TaskCompletedEvent; 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.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.TaskRequestChangesEvent;
import pro.taskana.spi.history.api.events.task.TaskRequestReviewEvent; import pro.taskana.spi.history.api.events.task.TaskRequestReviewEvent;
import pro.taskana.spi.history.api.events.task.TaskTerminatedEvent; import pro.taskana.spi.history.api.events.task.TaskTerminatedEvent;
@ -704,6 +705,9 @@ public class TaskServiceImpl implements TaskService {
.isDeleteHistoryEventsOnTaskDeletionEnabled()) { .isDeleteHistoryEventsOnTaskDeletionEnabled()) {
historyEventManager.deleteEvents(taskIds); historyEventManager.deleteEvents(taskIds);
} }
if (historyEventManager.isEnabled()) {
taskIds.forEach(this::createTaskDeletedEvent);
}
} }
return bulkLog; return bulkLog;
} finally { } finally {
@ -1709,6 +1713,10 @@ public class TaskServiceImpl implements TaskService {
historyEventManager.deleteEvents(Collections.singletonList(taskId)); historyEventManager.deleteEvents(Collections.singletonList(taskId));
} }
if (historyEventManager.isEnabled()) {
createTaskDeletedEvent(taskId);
}
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Task {} deleted.", taskId); LOGGER.debug("Task {} deleted.", taskId);
} }
@ -2241,6 +2249,15 @@ public class TaskServiceImpl implements TaskService {
taskanaEngine.getEngine().getCurrentUserContext().getUserid()))); 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) { private TaskImpl duplicateTaskExactly(TaskImpl task) {
TaskImpl oldTask = task.copy(); TaskImpl oldTask = task.copy();
oldTask.setId(task.getId()); oldTask.setId(task.getId());