TSK-1812: Added details in task-history for claim/cancel

Detect changes and pass them in the specific event in TaskServiceImpl class. For saving the old state of the specified task, I had to use copy() since getTask returns the same object reference, thus no changes can be detected. 
In the specified events details are accepted as parameters.
Extended Tests for Claim and Cancel Events to check correct details.
This commit is contained in:
Yakup Ensar Evli 2022-05-31 12:46:35 +02:00
parent db88d93017
commit 43ed441daf
5 changed files with 118 additions and 19 deletions

View File

@ -3,7 +3,10 @@ package acceptance.events.task;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import acceptance.AbstractAccTest; import acceptance.AbstractAccTest;
import java.time.Instant;
import java.util.List; import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -29,17 +32,19 @@ class CreateHistoryEventOnTaskCancelClaimAccTest extends AbstractAccTest {
void should_CreateCancelClaimedHistoryEvent_When_TaskIsCancelClaimed() throws Exception { void should_CreateCancelClaimedHistoryEvent_When_TaskIsCancelClaimed() throws Exception {
final String taskId = "TKI:000000000000000000000000000000000043"; final String taskId = "TKI:000000000000000000000000000000000043";
Task task = taskService.getTask(taskId);
final Instant oldModified = task.getModified();
final Instant oldClaimed = task.getClaimed();
TaskHistoryQueryMapper taskHistoryQueryMapper = getHistoryQueryMapper(); TaskHistoryQueryMapper taskHistoryQueryMapper = getHistoryQueryMapper();
List<TaskHistoryEvent> events = List<TaskHistoryEvent> events =
taskHistoryQueryMapper.queryHistoryEvents( taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId)); (TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId));
assertThat(events).isEmpty(); assertThat(events).isEmpty();
assertThat(taskService.getTask(taskId).getState()).isEqualTo(TaskState.CLAIMED); assertThat(task.getState()).isEqualTo(TaskState.CLAIMED);
Task task = taskService.forceCancelClaim(taskId); task = taskService.forceCancelClaim(taskId);
assertThat(task.getState()).isEqualTo(TaskState.READY); assertThat(task.getState()).isEqualTo(TaskState.READY);
events = events =
@ -48,8 +53,41 @@ class CreateHistoryEventOnTaskCancelClaimAccTest extends AbstractAccTest {
assertThat(events).hasSize(1); assertThat(events).hasSize(1);
String eventType = events.get(0).getEventType(); TaskHistoryEvent event = events.get(0);
assertThat(eventType).isEqualTo(TaskHistoryEventType.CLAIM_CANCELLED.getName()); assertThat(event.getEventType()).isEqualTo(TaskHistoryEventType.CLAIM_CANCELLED.getName());
event = historyService.getTaskHistoryEvent(event.getId());
assertThat(event.getDetails()).isNotNull();
JSONArray changes = new JSONObject(event.getDetails()).getJSONArray("changes");
JSONObject expectedClaimed =
new JSONObject()
.put("newValue", "")
.put("fieldName", "claimed")
.put("oldValue", oldClaimed.toString());
JSONObject expectedModified =
new JSONObject()
.put("newValue", task.getModified().toString())
.put("fieldName", "modified")
.put("oldValue", oldModified.toString());
JSONObject expectedState =
new JSONObject()
.put("newValue", "READY")
.put("fieldName", "state")
.put("oldValue", "CLAIMED");
JSONObject expectedOwner =
new JSONObject().put("newValue", "").put("fieldName", "owner").put("oldValue", "user-b-1");
JSONArray expectedChanges =
new JSONArray()
.put(expectedClaimed)
.put(expectedModified)
.put(expectedState)
.put(expectedOwner);
assertThat(changes.similar(expectedChanges)).isTrue();
} }
} }

View File

@ -3,7 +3,10 @@ package acceptance.events.task;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import acceptance.AbstractAccTest; import acceptance.AbstractAccTest;
import java.time.Instant;
import java.util.List; import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -27,8 +30,8 @@ class CreateHistoryEventOnTaskClaimAccTest extends AbstractAccTest {
@WithAccessId(user = "admin") @WithAccessId(user = "admin")
@Test @Test
void should_CreateClaimedHistoryEvent_When_TaskIsClaimed() throws Exception { void should_CreateClaimedHistoryEvent_When_TaskIsClaimed() throws Exception {
final String taskId = "TKI:000000000000000000000000000000000047"; final String taskId = "TKI:000000000000000000000000000000000047";
final Instant oldModified = taskService.getTask(taskId).getModified();
TaskHistoryQueryMapper taskHistoryQueryMapper = getHistoryQueryMapper(); TaskHistoryQueryMapper taskHistoryQueryMapper = getHistoryQueryMapper();
@ -40,14 +43,51 @@ class CreateHistoryEventOnTaskClaimAccTest extends AbstractAccTest {
assertThat(taskService.getTask(taskId).getState()).isEqualTo(TaskState.READY); assertThat(taskService.getTask(taskId).getState()).isEqualTo(TaskState.READY);
Task task = taskService.claim(taskId); Task task = taskService.claim(taskId);
assertThat(task.getState()).isEqualTo(TaskState.CLAIMED); assertThat(task.getState()).isEqualTo(TaskState.CLAIMED);
events = events =
taskHistoryQueryMapper.queryHistoryEvents( taskHistoryQueryMapper.queryHistoryEvents(
(TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId)); (TaskHistoryQueryImpl) historyService.createTaskHistoryQuery().taskIdIn(taskId));
String eventType = events.get(0).getEventType(); TaskHistoryEvent event = events.get(0);
assertThat(eventType).isEqualTo(TaskHistoryEventType.CLAIMED.getName()); assertThat(event.getEventType()).isEqualTo(TaskHistoryEventType.CLAIMED.getName());
event = historyService.getTaskHistoryEvent(event.getId());
assertThat(event.getDetails()).isNotNull();
JSONArray changes = new JSONObject(event.getDetails()).getJSONArray("changes");
JSONObject expectedClaimed =
new JSONObject()
.put("newValue", task.getModified().toString())
.put("fieldName", "claimed")
.put("oldValue", "");
JSONObject expectedModified =
new JSONObject()
.put("newValue", task.getModified().toString())
.put("fieldName", "modified")
.put("oldValue", oldModified.toString());
JSONObject expectedState =
new JSONObject()
.put("newValue", "CLAIMED")
.put("fieldName", "state")
.put("oldValue", "READY");
JSONObject expectedOwner =
new JSONObject().put("newValue", "admin").put("fieldName", "owner").put("oldValue", "");
JSONObject expectedIsRead =
new JSONObject().put("newValue", true).put("fieldName", "isRead").put("oldValue", false);
JSONArray expectedChanges =
new JSONArray()
.put(expectedClaimed)
.put(expectedModified)
.put(expectedState)
.put(expectedOwner)
.put(expectedIsRead);
assertThat(changes.similar(expectedChanges)).isTrue();
} }
} }

View File

@ -5,8 +5,8 @@ import pro.taskana.task.api.models.Task;
/** Event fired if a task is cancelled to be claimed. */ /** Event fired if a task is cancelled to be claimed. */
public class TaskClaimCancelledEvent extends TaskHistoryEvent { public class TaskClaimCancelledEvent extends TaskHistoryEvent {
public TaskClaimCancelledEvent(String id, Task task, String userId) { public TaskClaimCancelledEvent(String id, Task task, String userId, String details) {
super(id, task, userId, null); super(id, task, userId, details);
eventType = TaskHistoryEventType.CLAIM_CANCELLED.getName(); eventType = TaskHistoryEventType.CLAIM_CANCELLED.getName();
created = task.getModified(); created = task.getModified();
} }

View File

@ -5,8 +5,8 @@ import pro.taskana.task.api.models.Task;
/** Event fired if a task is claimed. */ /** Event fired if a task is claimed. */
public class TaskClaimedEvent extends TaskHistoryEvent { public class TaskClaimedEvent extends TaskHistoryEvent {
public TaskClaimedEvent(String id, Task task, String userId) { public TaskClaimedEvent(String id, Task task, String userId, String details) {
super(id, task, userId, null); super(id, task, userId, details);
eventType = (TaskHistoryEventType.CLAIMED.getName()); eventType = (TaskHistoryEventType.CLAIMED.getName());
created = task.getClaimed(); created = task.getClaimed();
} }

View File

@ -1162,6 +1162,10 @@ public class TaskServiceImpl implements TaskService {
try { try {
taskanaEngine.openConnection(); taskanaEngine.openConnection();
task = (TaskImpl) getTask(taskId); task = (TaskImpl) getTask(taskId);
TaskImpl oldTask = task.copy();
oldTask.setId(taskId);
oldTask.setExternalId(task.getExternalId());
Instant now = Instant.now(); Instant now = Instant.now();
checkPreconditionsForClaimTask(task, forceClaim); checkPreconditionsForClaimTask(task, forceClaim);
@ -1171,11 +1175,15 @@ public class TaskServiceImpl implements TaskService {
LOGGER.debug("Task '{}' claimed by user '{}'.", taskId, userId); LOGGER.debug("Task '{}' claimed by user '{}'.", taskId, userId);
} }
if (historyEventManager.isEnabled()) { if (historyEventManager.isEnabled()) {
String changeDetails =
ObjectAttributeChangeDetector.determineChangesInAttributes(oldTask, task);
historyEventManager.createEvent( historyEventManager.createEvent(
new TaskClaimedEvent( new TaskClaimedEvent(
IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_TASK_HISTORY_EVENT), IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_TASK_HISTORY_EVENT),
task, task,
taskanaEngine.getEngine().getCurrentUserContext().getUserid())); taskanaEngine.getEngine().getCurrentUserContext().getUserid(),
changeDetails));
} }
} finally { } finally {
taskanaEngine.returnConnection(); taskanaEngine.returnConnection();
@ -1191,6 +1199,14 @@ public class TaskServiceImpl implements TaskService {
task.setState(TaskState.CLAIMED); task.setState(TaskState.CLAIMED);
} }
private static void cancelClaimActionsOnTask(TaskSummaryImpl task, Instant now) {
task.setOwner(null);
task.setModified(now);
task.setClaimed(null);
task.setRead(true);
task.setState(TaskState.READY);
}
private static void completeActionsOnTask(TaskSummaryImpl task, String userId, Instant now) { private static void completeActionsOnTask(TaskSummaryImpl task, String userId, Instant now) {
task.setCompleted(now); task.setCompleted(now);
task.setModified(now); task.setModified(now);
@ -1249,6 +1265,11 @@ public class TaskServiceImpl implements TaskService {
try { try {
taskanaEngine.openConnection(); taskanaEngine.openConnection();
task = (TaskImpl) getTask(taskId); task = (TaskImpl) getTask(taskId);
TaskImpl oldTask = task.copy();
oldTask.setId(taskId);
oldTask.setExternalId(task.getExternalId());
TaskState state = task.getState(); TaskState state = task.getState();
if (state.isEndState()) { if (state.isEndState()) {
throw new InvalidTaskStateException( throw new InvalidTaskStateException(
@ -1258,21 +1279,21 @@ public class TaskServiceImpl implements TaskService {
throw new InvalidOwnerException(userId, taskId); throw new InvalidOwnerException(userId, taskId);
} }
Instant now = Instant.now(); Instant now = Instant.now();
task.setOwner(null); cancelClaimActionsOnTask(task, now);
task.setModified(now);
task.setClaimed(null);
task.setRead(true);
task.setState(TaskState.READY);
taskMapper.update(task); taskMapper.update(task);
if (LOGGER.isDebugEnabled()) { if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Task '{}' unclaimed by user '{}'.", taskId, userId); LOGGER.debug("Task '{}' unclaimed by user '{}'.", taskId, userId);
} }
if (historyEventManager.isEnabled()) { if (historyEventManager.isEnabled()) {
String changeDetails =
ObjectAttributeChangeDetector.determineChangesInAttributes(oldTask, task);
historyEventManager.createEvent( historyEventManager.createEvent(
new TaskClaimCancelledEvent( new TaskClaimCancelledEvent(
IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_TASK_HISTORY_EVENT), IdGenerator.generateWithPrefix(IdGenerator.ID_PREFIX_TASK_HISTORY_EVENT),
task, task,
taskanaEngine.getEngine().getCurrentUserContext().getUserid())); taskanaEngine.getEngine().getCurrentUserContext().getUserid(),
changeDetails));
} }
} finally { } finally {
taskanaEngine.returnConnection(); taskanaEngine.returnConnection();