TSK-314 Recalculate due timestamp and prio when a classification is updated
This commit is contained in:
parent
439390adee
commit
4bc7b6bad1
|
@ -14,6 +14,15 @@ public interface ClassificationQuery extends BaseQuery<ClassificationSummary> {
|
|||
*/
|
||||
ClassificationQuery keyIn(String... key);
|
||||
|
||||
/**
|
||||
* Add your Id to your query.
|
||||
*
|
||||
* @param id
|
||||
* as String
|
||||
* @return the query
|
||||
*/
|
||||
ClassificationQuery idIn(String... id);
|
||||
|
||||
/**
|
||||
* Add your parentIds to your query.
|
||||
*
|
||||
|
|
|
@ -107,6 +107,15 @@ public interface TaskQuery extends BaseQuery<TaskSummary> {
|
|||
*/
|
||||
TaskQuery classificationKeyLike(String... classificationKeys);
|
||||
|
||||
/**
|
||||
* Add your classificationId to your query.
|
||||
*
|
||||
* @param classificationIds
|
||||
* the classification Ids
|
||||
* @return the query
|
||||
*/
|
||||
TaskQuery classificationIdIn(String... classificationIds);
|
||||
|
||||
/**
|
||||
* Add your classificationCategory to your query.
|
||||
*
|
||||
|
|
|
@ -97,4 +97,17 @@ public class BulkOperationResults<K, V> {
|
|||
public void clearErrors() {
|
||||
this.errorMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all errors from another BulkOperationResult to this.
|
||||
*
|
||||
* @param log
|
||||
* the other log
|
||||
*/
|
||||
public void addAllErrors(BulkOperationResults<K, V> log) {
|
||||
List<K> failedIds = log.getFailedIds();
|
||||
for (K id : failedIds) {
|
||||
addError(id, log.getErrorForId(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ public class ClassificationQueryImpl implements ClassificationQuery {
|
|||
private TaskanaEngineImpl taskanaEngine;
|
||||
private String columnName;
|
||||
private String[] key;
|
||||
private String[] idIn;
|
||||
private String[] parentId;
|
||||
private String[] category;
|
||||
private String[] type;
|
||||
|
@ -74,6 +75,12 @@ public class ClassificationQueryImpl implements ClassificationQuery {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassificationQuery idIn(String... id) {
|
||||
this.idIn = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassificationQuery parentIdIn(String... parentId) {
|
||||
this.parentId = parentId;
|
||||
|
@ -459,6 +466,10 @@ public class ClassificationQueryImpl implements ClassificationQuery {
|
|||
return key;
|
||||
}
|
||||
|
||||
public String[] getIdIn() {
|
||||
return idIn;
|
||||
}
|
||||
|
||||
public String[] getparentId() {
|
||||
return parentId;
|
||||
}
|
||||
|
@ -594,6 +605,8 @@ public class ClassificationQueryImpl implements ClassificationQuery {
|
|||
builder.append(columnName);
|
||||
builder.append(", key=");
|
||||
builder.append(Arrays.toString(key));
|
||||
builder.append(", idIn=");
|
||||
builder.append(Arrays.toString(idIn));
|
||||
builder.append(", parentId=");
|
||||
builder.append(Arrays.toString(parentId));
|
||||
builder.append(", category=");
|
||||
|
|
|
@ -3,7 +3,9 @@ package pro.taskana.impl;
|
|||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -22,7 +24,9 @@ import pro.taskana.exceptions.NotAuthorizedException;
|
|||
import pro.taskana.exceptions.NotAuthorizedToQueryWorkbasketException;
|
||||
import pro.taskana.exceptions.SystemException;
|
||||
import pro.taskana.impl.util.IdGenerator;
|
||||
import pro.taskana.mappings.AttachmentMapper;
|
||||
import pro.taskana.mappings.ClassificationMapper;
|
||||
import pro.taskana.mappings.JobMapper;
|
||||
import pro.taskana.mappings.TaskMapper;
|
||||
|
||||
/**
|
||||
|
@ -138,8 +142,8 @@ public class ClassificationServiceImpl implements ClassificationService {
|
|||
if (oldClassification.getCategory() != classificationImpl.getCategory()) {
|
||||
List<TaskSummary> taskSumamries = taskanaEngine.getTaskService()
|
||||
.createTaskQuery()
|
||||
.classificationKeyIn(oldClassification.getKey())
|
||||
.classificationCategoryIn(oldClassification.getCategory())
|
||||
.classificationIdIn(oldClassification.getId())
|
||||
// .classificationCategoryIn(oldClassification.getCategory())
|
||||
.list();
|
||||
if (!taskSumamries.isEmpty()) {
|
||||
List<String> taskIds = new ArrayList<>();
|
||||
|
@ -155,6 +159,23 @@ public class ClassificationServiceImpl implements ClassificationService {
|
|||
}
|
||||
}
|
||||
classificationMapper.update(classificationImpl);
|
||||
boolean priorityChanged = oldClassification.getPriority() != classification.getPriority();
|
||||
boolean serviceLevelChanged = oldClassification.getServiceLevel() != classification.getServiceLevel();
|
||||
|
||||
if (priorityChanged || serviceLevelChanged) {
|
||||
Map<String, String> args = new HashMap<>();
|
||||
args.put(TaskUpdateOnClassificationChangeExecutor.CLASSIFICATION_ID, classificationImpl.getId());
|
||||
args.put(TaskUpdateOnClassificationChangeExecutor.PRIORITY_CHANGED, String.valueOf(priorityChanged));
|
||||
args.put(TaskUpdateOnClassificationChangeExecutor.SERVICE_LEVEL_CHANGED,
|
||||
String.valueOf(serviceLevelChanged));
|
||||
Job job = new Job();
|
||||
job.setCreated(Instant.now());
|
||||
job.setState(Job.State.READY);
|
||||
job.setExecutor(TaskUpdateOnClassificationChangeExecutor.class.getName());
|
||||
job.setArguments(args);
|
||||
taskanaEngine.getSqlSession().getMapper(JobMapper.class).insertJob(job);
|
||||
}
|
||||
|
||||
LOGGER.debug("Method updateClassification() updated the classification {}.",
|
||||
classificationImpl);
|
||||
return classification;
|
||||
|
@ -304,6 +325,14 @@ public class ClassificationServiceImpl implements ClassificationService {
|
|||
"The classification " + classificationKey + "wasn't found in the domain " + domain);
|
||||
}
|
||||
|
||||
List<AttachmentSummaryImpl> attachments = taskanaEngine.getSqlSession()
|
||||
.getMapper(AttachmentMapper.class)
|
||||
.findAttachmentSummariesByClassificationId(classification.getId());
|
||||
if (!attachments.isEmpty()) {
|
||||
throw new ClassificationInUseException("Classification " + classification.getId()
|
||||
+ " is used by Attachment " + attachments.get(0).getId());
|
||||
}
|
||||
|
||||
if (domain.equals("")) {
|
||||
// master mode - delete all associated classifications in every domain.
|
||||
List<String> domains = this.classificationMapper.getDomainsForClassification(classificationKey);
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
package pro.taskana.impl;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This class holds all data that go into the Job table.
|
||||
*
|
||||
* @author bbr
|
||||
*/
|
||||
public class Job {
|
||||
|
||||
private Integer jobId;
|
||||
private Instant created;
|
||||
private Instant started;
|
||||
private Instant completed;
|
||||
private State state;
|
||||
private String executor;
|
||||
Map<String, String> arguments;
|
||||
|
||||
public Integer getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
public void setJobId(Integer jobId) {
|
||||
this.jobId = jobId;
|
||||
}
|
||||
|
||||
public Instant getCreated() {
|
||||
return created;
|
||||
}
|
||||
|
||||
public void setCreated(Instant created) {
|
||||
this.created = created;
|
||||
}
|
||||
|
||||
public Instant getStarted() {
|
||||
return started;
|
||||
}
|
||||
|
||||
public void setStarted(Instant started) {
|
||||
this.started = started;
|
||||
}
|
||||
|
||||
public Instant getCompleted() {
|
||||
return completed;
|
||||
}
|
||||
|
||||
public void setCompleted(Instant completed) {
|
||||
this.completed = completed;
|
||||
}
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public String getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
public void setExecutor(String executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public Map<String, String> getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public void setArguments(Map<String, String> arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Job [jobId=");
|
||||
builder.append(jobId);
|
||||
builder.append(", created=");
|
||||
builder.append(created);
|
||||
builder.append(", started=");
|
||||
builder.append(started);
|
||||
builder.append(", completed=");
|
||||
builder.append(completed);
|
||||
builder.append(", state=");
|
||||
builder.append(state);
|
||||
builder.append(", executor=");
|
||||
builder.append(executor);
|
||||
builder.append(", arguments=");
|
||||
builder.append(arguments);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* This enum tracks the state of a job.
|
||||
*
|
||||
* @author bbr
|
||||
*/
|
||||
public enum State {
|
||||
READY,
|
||||
RUNNING,
|
||||
FAILED,
|
||||
COMPLETED
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package pro.taskana.impl;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import pro.taskana.TaskanaEngine;
|
||||
import pro.taskana.mappings.JobMapper;
|
||||
|
||||
/**
|
||||
* This is the runner for all jobs scheduled in the Job table.
|
||||
*
|
||||
* @author bbr
|
||||
*/
|
||||
public class JobRunner {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TaskServiceImpl.class);
|
||||
private TaskanaEngineImpl taskanaEngine;
|
||||
private JobMapper jobMapper;
|
||||
|
||||
public JobRunner(TaskanaEngine taskanaEngine) {
|
||||
this.taskanaEngine = (TaskanaEngineImpl) taskanaEngine;
|
||||
jobMapper = this.taskanaEngine.getSqlSession().getMapper(JobMapper.class);
|
||||
}
|
||||
|
||||
public BulkOperationResults<String, Exception> runJobs() {
|
||||
LOGGER.info("entry to runJobs()");
|
||||
BulkOperationResults<String, Exception> bulkLog = new BulkOperationResults<>();
|
||||
try {
|
||||
taskanaEngine.openConnection();
|
||||
List<Job> jobs = jobMapper.findJobsToRun();
|
||||
for (Job job : jobs) {
|
||||
BulkOperationResults<String, Exception> log = runSingleJob(job);
|
||||
bulkLog.addAllErrors(log);
|
||||
}
|
||||
return bulkLog;
|
||||
} finally {
|
||||
taskanaEngine.returnConnection();
|
||||
LOGGER.info("exit from runJobs(). Returning result {} ", bulkLog);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private BulkOperationResults<String, Exception> runSingleJob(Job job) {
|
||||
LOGGER.debug("entry to runSingleJob(job = {})", job);
|
||||
BulkOperationResults<String, Exception> bulkLog = new BulkOperationResults<>();
|
||||
if (Job.State.READY.equals(job.getState())) {
|
||||
job.setStarted(Instant.now());
|
||||
}
|
||||
job.setState(Job.State.RUNNING);
|
||||
jobMapper.update(job);
|
||||
SingleJobExecutor executor;
|
||||
try {
|
||||
executor = (SingleJobExecutor) Class.forName(job.getExecutor()).newInstance();
|
||||
bulkLog = executor.runSingleJob(job, taskanaEngine);
|
||||
|
||||
} catch (Exception e) {
|
||||
bulkLog.addError("JobId:" + job.getJobId(), e);
|
||||
job.setCompleted(Instant.now());
|
||||
job.setState(Job.State.FAILED);
|
||||
jobMapper.update(job);
|
||||
return bulkLog;
|
||||
}
|
||||
job.setCompleted(Instant.now());
|
||||
job.setState(Job.State.COMPLETED);
|
||||
jobMapper.update(job);
|
||||
|
||||
LOGGER.debug("exit from runSingleJob");
|
||||
if (bulkLog.containsErrors()) {
|
||||
LOGGER.error("Errors occurred when running job {}.", job);
|
||||
for (String id : bulkLog.getFailedIds()) {
|
||||
LOGGER.error(id + bulkLog.getErrorForId(id));
|
||||
}
|
||||
}
|
||||
return bulkLog;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package pro.taskana.impl;
|
||||
|
||||
/**
|
||||
* This interface must be implemented by classes that execut a single job.
|
||||
*
|
||||
* @author bbr
|
||||
*/
|
||||
public interface SingleJobExecutor {
|
||||
|
||||
BulkOperationResults<String, Exception> runSingleJob(Job job, TaskanaEngineImpl taskanaEngine);
|
||||
}
|
|
@ -50,6 +50,7 @@ public class TaskQueryImpl implements TaskQuery {
|
|||
private KeyDomain[] workbasketKeyDomainIn;
|
||||
private String[] workbasketIdIn;
|
||||
private TaskState[] stateIn;
|
||||
private String[] classificationIdIn;
|
||||
private String[] classificationKeyIn;
|
||||
private String[] classificationKeyLike;
|
||||
private String[] classificationCategoryIn;
|
||||
|
@ -256,6 +257,12 @@ public class TaskQueryImpl implements TaskQuery {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskQuery classificationIdIn(String... classificationId) {
|
||||
this.classificationIdIn = classificationId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskQuery classificationCategoryIn(String... classificationCategories) {
|
||||
this.classificationCategoryIn = classificationCategories;
|
||||
|
@ -1133,6 +1140,10 @@ public class TaskQueryImpl implements TaskQuery {
|
|||
return classificationKeyLike;
|
||||
}
|
||||
|
||||
public String[] getClassificationIdIn() {
|
||||
return classificationIdIn;
|
||||
}
|
||||
|
||||
public KeyDomain[] getWorkbasketKeyDomainIn() {
|
||||
return workbasketKeyDomainIn;
|
||||
}
|
||||
|
@ -1197,6 +1208,8 @@ public class TaskQueryImpl implements TaskQuery {
|
|||
builder.append(Arrays.toString(classificationKeyIn));
|
||||
builder.append(", classificationKeyLike=");
|
||||
builder.append(Arrays.toString(classificationKeyLike));
|
||||
builder.append(", classificationIdIn=");
|
||||
builder.append(Arrays.toString(classificationIdIn));
|
||||
builder.append(", classificationCategoryIn=");
|
||||
builder.append(Arrays.toString(classificationCategoryIn));
|
||||
builder.append(", classificationCategoryLike=");
|
||||
|
|
|
@ -380,8 +380,16 @@ public class TaskServiceImpl implements TaskService {
|
|||
classifications);
|
||||
resultTask.setAttachments(attachments);
|
||||
|
||||
ClassificationSummary classification = getMatchingClassificationFromList(classifications,
|
||||
resultTask.getClassificationSummary().getKey(), resultTask.getDomain());
|
||||
String classificationId = resultTask.getClassificationSummary().getId();
|
||||
ClassificationSummary classification = classifications.stream()
|
||||
.filter(c -> c.getId().equals(classificationId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (classification == null) {
|
||||
LOGGER.error("Could not find a Classification for task {} ", resultTask);
|
||||
throw new SystemException(
|
||||
"Could not find a Classification for task " + resultTask.getId());
|
||||
}
|
||||
|
||||
resultTask.setClassificationSummary(classification);
|
||||
return resultTask;
|
||||
|
@ -614,7 +622,6 @@ public class TaskServiceImpl implements TaskService {
|
|||
oldTaskImpl = (TaskImpl) getTask(newTaskImpl.getId());
|
||||
PrioDurationHolder prioDurationFromAttachments = handleAttachmentsOnTaskUpdate(oldTaskImpl, newTaskImpl);
|
||||
standardUpdateActions(oldTaskImpl, newTaskImpl, prioDurationFromAttachments);
|
||||
newTaskImpl.setModified(Instant.now());
|
||||
|
||||
taskMapper.update(newTaskImpl);
|
||||
LOGGER.debug("Method updateTask() updated task '{}' for user '{}'.", task.getId(), userId);
|
||||
|
@ -725,34 +732,21 @@ public class TaskServiceImpl implements TaskService {
|
|||
}
|
||||
// assign query results to appropriate tasks.
|
||||
for (TaskSummaryImpl task : tasks) {
|
||||
ClassificationSummary aClassification = getMatchingClassificationFromList(classifications,
|
||||
task.getClassificationSummary().getKey(),
|
||||
task.getDomain());
|
||||
// set the classification on the task object
|
||||
task.setClassificationSummary(aClassification);
|
||||
}
|
||||
}
|
||||
|
||||
private ClassificationSummary getMatchingClassificationFromList(List<ClassificationSummary> classifications,
|
||||
String taskClassKey, String taskDomain) {
|
||||
ClassificationSummary aClassification = classifications.stream()
|
||||
.filter(x -> taskClassKey != null && taskClassKey.equals(x.getKey()) && taskDomain != null
|
||||
&& taskDomain.equals(x.getDomain()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (aClassification == null) {
|
||||
// search in "" domain
|
||||
aClassification = classifications.stream()
|
||||
.filter(x -> taskClassKey != null && taskClassKey.equals(x.getKey()) && "".equals(x.getDomain()))
|
||||
String classificationId = task.getClassificationSummary().getId();
|
||||
ClassificationSummary aClassification = classifications.stream()
|
||||
.filter(c -> c.getId().equals(classificationId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (aClassification == null) {
|
||||
LOGGER.error("Could not find a Classification for task ");
|
||||
LOGGER.error("Didnt find a Classification for task ");
|
||||
throw new SystemException(
|
||||
"Could not find a Classification for task (key=" + taskClassKey + ",domain=" + taskDomain + ")");
|
||||
"Did not find a Classification for task (Id=" + task.getTaskId() + ",classification="
|
||||
+ task.getClassificationSummary().getId()
|
||||
+ ")");
|
||||
}
|
||||
// set the classification on the task object
|
||||
task.setClassificationSummary(aClassification);
|
||||
}
|
||||
return aClassification;
|
||||
}
|
||||
|
||||
private List<ClassificationSummary> findClassificationsForTasksAndAttachments(
|
||||
|
@ -763,53 +757,40 @@ public class TaskServiceImpl implements TaskService {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
Set<String> classificationDomainSet = taskSummaries.stream().map(TaskSummaryImpl::getDomain).collect(
|
||||
Set<String> classificationIdSet = taskSummaries.stream().map(t -> t.getClassificationSummary().getId()).collect(
|
||||
Collectors.toSet());
|
||||
// add "" domain in case the classification exists only there (fallback for tasks)
|
||||
classificationDomainSet.add("");
|
||||
|
||||
Set<String> classificationKeySet = taskSummaries.stream()
|
||||
.map(t -> t.getClassificationSummary().getKey())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (attachmentSummaries != null && !attachmentSummaries.isEmpty()) {
|
||||
Set<String> classificationKeysFromAttachments = attachmentSummaries.stream()
|
||||
.map(t -> t.getClassificationSummary().getKey())
|
||||
.collect(Collectors.toSet());
|
||||
classificationKeySet.addAll(classificationKeysFromAttachments);
|
||||
for (AttachmentSummaryImpl att : attachmentSummaries) {
|
||||
classificationIdSet.add(att.getClassificationSummary().getId());
|
||||
}
|
||||
}
|
||||
|
||||
return queryClassificationsForTasksAndAttachments(classificationDomainSet, classificationKeySet);
|
||||
return queryClassificationsForTasksAndAttachments(classificationIdSet);
|
||||
}
|
||||
|
||||
private List<ClassificationSummary> findClassificationForTaskImplAndAttachments(TaskImpl task,
|
||||
List<AttachmentImpl> attachmentImpls) throws NotAuthorizedException {
|
||||
|
||||
Set<String> classificationDomainSet = new HashSet<>(Arrays.asList(task.getDomain(), ""));
|
||||
Set<String> classificationKeySet = new HashSet<>(Arrays.asList(task.getClassificationKey()));
|
||||
|
||||
Set<String> classificationIdSet = new HashSet<>(Arrays.asList(task.getClassificationSummary().getId()));
|
||||
if (attachmentImpls != null && !attachmentImpls.isEmpty()) {
|
||||
Set<String> classificationKeysFromAttachments = attachmentImpls.stream()
|
||||
.map(t -> t.getClassificationSummary().getKey())
|
||||
.collect(Collectors.toSet());
|
||||
classificationKeySet.addAll(classificationKeysFromAttachments);
|
||||
for (AttachmentImpl att : attachmentImpls) {
|
||||
classificationIdSet.add(att.getClassificationSummary().getId());
|
||||
}
|
||||
}
|
||||
|
||||
return queryClassificationsForTasksAndAttachments(classificationDomainSet, classificationKeySet);
|
||||
return queryClassificationsForTasksAndAttachments(classificationIdSet);
|
||||
|
||||
}
|
||||
|
||||
private List<ClassificationSummary> queryClassificationsForTasksAndAttachments(Set<String> classificationDomainSet,
|
||||
Set<String> classificationKeySet) throws NotAuthorizedException {
|
||||
private List<ClassificationSummary> queryClassificationsForTasksAndAttachments(Set<String> classificationIdSet)
|
||||
throws NotAuthorizedException {
|
||||
|
||||
String[] classificationDomainArray = classificationDomainSet.toArray(new String[0]);
|
||||
String[] classificationKeyArray = classificationKeySet.toArray(new String[0]);
|
||||
String[] classificationIdArray = classificationIdSet.toArray(new String[0]);
|
||||
|
||||
LOGGER.debug("getClassificationsForTasksAndAttachments() about to query classifications and exit");
|
||||
// perform classification query
|
||||
return this.classificationService.createClassificationQuery()
|
||||
.domainIn(classificationDomainArray)
|
||||
.keyIn(classificationKeyArray)
|
||||
.idIn(classificationIdArray)
|
||||
.list();
|
||||
}
|
||||
|
||||
|
@ -820,25 +801,26 @@ public class TaskServiceImpl implements TaskService {
|
|||
return;
|
||||
}
|
||||
// calculate parameters for workbasket query: workbasket keys
|
||||
Set<String> workbasketKeySet = taskSummaries.stream().map(t -> t.getWorkbasketSummary().getKey()).collect(
|
||||
Set<String> workbasketIdSet = taskSummaries.stream().map(t -> t.getWorkbasketSummary().getId()).collect(
|
||||
Collectors.toSet());
|
||||
String[] workbasketKeyArray = workbasketKeySet.toArray(new String[0]);
|
||||
String[] workbasketIdArray = workbasketIdSet.toArray(new String[0]);
|
||||
// perform workbasket query
|
||||
LOGGER.debug("addWorkbasketSummariesToTaskSummaries() about to query workbaskets");
|
||||
WorkbasketQueryImpl query = (WorkbasketQueryImpl) workbasketService.createWorkbasketQuery();
|
||||
query.setUsedToAugmentTasks(true);
|
||||
|
||||
List<WorkbasketSummary> workbaskets = query
|
||||
.keyIn(workbasketKeyArray)
|
||||
.idIn(workbasketIdArray)
|
||||
.list();
|
||||
// assign query results to appropriate tasks.
|
||||
Iterator<TaskSummaryImpl> taskIterator = taskSummaries.iterator();
|
||||
while (taskIterator.hasNext()) {
|
||||
TaskSummaryImpl task = taskIterator.next();
|
||||
String workbasketKey = task.getWorkbasketSummaryImpl().getKey();
|
||||
String workbasketId = task.getWorkbasketSummaryImpl().getId();
|
||||
|
||||
// find the appropriate workbasket from the query result
|
||||
WorkbasketSummary aWorkbasket = workbaskets.stream()
|
||||
.filter(x -> workbasketKey != null && workbasketKey.equals(x.getKey()))
|
||||
.filter(x -> workbasketId != null && workbasketId.equals(x.getId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (aWorkbasket == null) {
|
||||
|
@ -883,20 +865,9 @@ public class TaskServiceImpl implements TaskService {
|
|||
}
|
||||
// iterate over all attachment summaries an add the appropriate classification summary to each
|
||||
for (AttachmentSummaryImpl att : attachmentSummaries) {
|
||||
// find the associated task to use the correct domain
|
||||
TaskSummaryImpl aTaskSummary = taskSummaries.stream()
|
||||
.filter(x -> x.getTaskId().equals(att.getTaskId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (aTaskSummary == null) {
|
||||
LOGGER.error("Could not find a Task associated to attachment {}.", att);
|
||||
throw new SystemException("Could not find a Task associated to attachment " + att);
|
||||
}
|
||||
String domain = aTaskSummary.getDomain();
|
||||
String classificationKey = att.getClassificationSummary().getKey();
|
||||
String classificationId = att.getClassificationSummary().getId();
|
||||
ClassificationSummary aClassification = classifications.stream()
|
||||
.filter(x -> classificationKey != null && classificationKey.equals(x.getKey()) && domain != null
|
||||
&& domain.equals(x.getDomain()))
|
||||
.filter(x -> classificationId != null && classificationId.equals(x.getId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (aClassification == null) {
|
||||
|
@ -916,13 +887,11 @@ public class TaskServiceImpl implements TaskService {
|
|||
List<Attachment> result = new ArrayList<>();
|
||||
for (AttachmentImpl att : attachmentImpls) {
|
||||
// find the associated task to use the correct domain
|
||||
String domain = task.getDomain();
|
||||
String classificationKey = att.getClassificationSummary().getKey();
|
||||
ClassificationSummary aClassification = classifications.stream()
|
||||
.filter(x -> classificationKey != null && classificationKey.equals(x.getKey()) && domain != null
|
||||
&& domain.equals(x.getDomain()))
|
||||
.filter(c -> c != null & c.getId().equals(att.getClassificationSummary().getId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (aClassification == null) {
|
||||
LOGGER.error("Could not find a Classification for attachment {}.", att);
|
||||
throw new SystemException("Could not find a Classification for attachment " + att);
|
||||
|
@ -1188,7 +1157,7 @@ public class TaskServiceImpl implements TaskService {
|
|||
|
||||
private void updateClassificationRelatedProperties(TaskImpl oldTaskImpl, TaskImpl newTaskImpl,
|
||||
PrioDurationHolder prioDurationFromAttachments)
|
||||
throws WorkbasketNotFoundException, NotAuthorizedException, ClassificationNotFoundException {
|
||||
throws NotAuthorizedException, ClassificationNotFoundException {
|
||||
// insert Classification specifications if Classification is given.
|
||||
ClassificationSummary oldClassificationSummary = oldTaskImpl.getClassificationSummary();
|
||||
ClassificationSummary newClassificationSummary = newTaskImpl.getClassificationSummary();
|
||||
|
@ -1341,6 +1310,32 @@ public class TaskServiceImpl implements TaskService {
|
|||
return new PrioDurationHolder(minDuration, maxPrio);
|
||||
}
|
||||
|
||||
private PrioDurationHolder handleAttachmentsOnClassificationUpdate(Task task) {
|
||||
|
||||
Duration minDuration = MAX_DURATION;
|
||||
int maxPrio = Integer.MIN_VALUE;
|
||||
|
||||
// Iterator for removing invalid current values directly. OldAttachments can be ignored.
|
||||
Iterator<Attachment> i = task.getAttachments().iterator();
|
||||
while (i.hasNext()) {
|
||||
Attachment attachment = i.next();
|
||||
if (attachment != null) {
|
||||
ClassificationSummary classification = attachment.getClassificationSummary();
|
||||
if (classification != null) {
|
||||
PrioDurationHolder newPrioDuration = getNewPrioDuration(maxPrio, minDuration,
|
||||
classification.getPriority(), classification.getServiceLevel());
|
||||
maxPrio = newPrioDuration.getPrio();
|
||||
minDuration = newPrioDuration.getDuration();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (minDuration != null && MAX_DURATION.equals(minDuration)) {
|
||||
minDuration = null;
|
||||
}
|
||||
return new PrioDurationHolder(minDuration, maxPrio);
|
||||
}
|
||||
|
||||
private PrioDurationHolder getNewPrioDuration(int prio, Duration duration, int prioFromClassification,
|
||||
String serviceLevelFromClassification) {
|
||||
Duration minDuration = duration;
|
||||
|
@ -1415,4 +1410,71 @@ public class TaskServiceImpl implements TaskService {
|
|||
}
|
||||
}
|
||||
|
||||
BulkOperationResults<String, Exception> classificationChanged(String taskId, String classificationId)
|
||||
throws TaskNotFoundException, NotAuthorizedException, ClassificationNotFoundException {
|
||||
LOGGER.debug("entry to classificationChanged(taskId = {} , classificationId = {} )", taskId, classificationId);
|
||||
TaskImpl task = null;
|
||||
BulkOperationResults<String, Exception> bulkLog = new BulkOperationResults<>();
|
||||
try {
|
||||
taskanaEngine.openConnection();
|
||||
if (taskId == null || taskId.isEmpty() || classificationId == null || classificationId.isEmpty()) {
|
||||
return bulkLog;
|
||||
}
|
||||
|
||||
task = taskMapper.findById(taskId);
|
||||
|
||||
List<AttachmentImpl> attachmentImpls = attachmentMapper.findAttachmentsByTaskId(task.getId());
|
||||
if (attachmentImpls == null) {
|
||||
attachmentImpls = new ArrayList<>();
|
||||
}
|
||||
List<Attachment> attachments = augmentAttachmentsByClassification(attachmentImpls, bulkLog);
|
||||
task.setAttachments(attachments);
|
||||
|
||||
Classification classification = classificationService.getClassification(classificationId);
|
||||
task.setClassificationSummary(classification.asSummary());
|
||||
|
||||
PrioDurationHolder prioDurationFromAttachments = handleAttachmentsOnClassificationUpdate(task);
|
||||
|
||||
updateClassificationRelatedProperties(task, task, prioDurationFromAttachments);
|
||||
|
||||
task.setModified(Instant.now());
|
||||
taskMapper.update(task);
|
||||
return bulkLog;
|
||||
} finally {
|
||||
taskanaEngine.returnConnection();
|
||||
LOGGER.debug("exit from deleteTask(). ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private List<Attachment> augmentAttachmentsByClassification(List<AttachmentImpl> attachmentImpls,
|
||||
BulkOperationResults<String, Exception> bulkLog) {
|
||||
List<Attachment> result = new ArrayList<>();
|
||||
if (attachmentImpls == null || attachmentImpls.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
Set<String> classificationIds = attachmentImpls.stream().map(t -> t.getClassificationSummary().getId()).collect(
|
||||
Collectors.toSet());
|
||||
List<ClassificationSummary> classifications = classificationService.createClassificationQuery()
|
||||
.idIn(classificationIds.toArray(new String[0]))
|
||||
.list();
|
||||
for (AttachmentImpl att : attachmentImpls) {
|
||||
ClassificationSummary classificationSummary = classifications.stream()
|
||||
.filter(cl -> cl.getId().equals(att.getClassificationSummary().getId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (classificationSummary == null) {
|
||||
String id = att.getClassificationSummary().getId();
|
||||
bulkLog.addError(att.getClassificationSummary().getId(), new ClassificationNotFoundException(id,
|
||||
"When processing task updates due to change of classification, the classification with id " + id
|
||||
+ " was not found."));
|
||||
} else {
|
||||
att.setClassificationSummary(classificationSummary);
|
||||
result.add(att);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package pro.taskana.impl;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import pro.taskana.impl.util.LoggerUtils;
|
||||
import pro.taskana.mappings.AttachmentMapper;
|
||||
import pro.taskana.mappings.ClassificationMapper;
|
||||
import pro.taskana.mappings.TaskMapper;
|
||||
|
||||
/**
|
||||
* This class performs task updates if a classification is changed.
|
||||
*
|
||||
* @author bbr
|
||||
*/
|
||||
public class TaskUpdateOnClassificationChangeExecutor implements SingleJobExecutor {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TaskServiceImpl.class);
|
||||
public static final String CLASSIFICATION_ID = "classificationId";
|
||||
public static final String PRIORITY_CHANGED = "priorityChanged";
|
||||
public static final String SERVICE_LEVEL_CHANGED = "serviceLevelChanged";
|
||||
|
||||
private TaskanaEngineImpl taskanaEngine;
|
||||
private Job job;
|
||||
private String classificationId;
|
||||
private boolean priorityChanged;
|
||||
private boolean serviceLevelChanged;
|
||||
private TaskMapper taskMapper;
|
||||
private ClassificationMapper classificationMapper;
|
||||
private AttachmentMapper attachmentMapper;
|
||||
|
||||
public TaskUpdateOnClassificationChangeExecutor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BulkOperationResults<String, Exception> runSingleJob(Job job, TaskanaEngineImpl taskanaEngine) {
|
||||
this.job = job;
|
||||
this.taskanaEngine = taskanaEngine;
|
||||
this.taskMapper = taskanaEngine.getSqlSession().getMapper(TaskMapper.class);
|
||||
this.classificationMapper = taskanaEngine.getSqlSession().getMapper(ClassificationMapper.class);
|
||||
this.attachmentMapper = taskanaEngine.getSqlSession().getMapper(AttachmentMapper.class);
|
||||
Map<String, String> args = job.getArguments();
|
||||
classificationId = args.get(CLASSIFICATION_ID);
|
||||
priorityChanged = Boolean.getBoolean(args.get(PRIORITY_CHANGED));
|
||||
serviceLevelChanged = Boolean.getBoolean(args.get(SERVICE_LEVEL_CHANGED));
|
||||
BulkOperationResults<String, Exception> bulkLog = new BulkOperationResults<>();
|
||||
bulkLog.addAllErrors(handleAffectedTasks());
|
||||
|
||||
return bulkLog;
|
||||
}
|
||||
|
||||
private BulkOperationResults<String, Exception> handleAffectedTasks() {
|
||||
List<TaskSummaryImpl> tasks = taskMapper.findTasksAffectedByClassificationChange(classificationId);
|
||||
List<String> taskIdsFromAttachments = attachmentMapper
|
||||
.findTaskIdsAffectedByClassificationChange(classificationId);
|
||||
List<String> filteredTaskIdsFromAttachments = taskMapper.filterTaskIdsForNotCompleted(taskIdsFromAttachments);
|
||||
|
||||
Set<String> affectedTaskIds = new HashSet<>(filteredTaskIdsFromAttachments);
|
||||
for (TaskSummaryImpl task : tasks) {
|
||||
affectedTaskIds.add(task.getTaskId());
|
||||
}
|
||||
LOGGER.debug("the following tasks are affected by the update of classification {} : {}", classificationId,
|
||||
LoggerUtils.setToString(affectedTaskIds));
|
||||
TaskServiceImpl taskService = (TaskServiceImpl) taskanaEngine.getTaskService();
|
||||
BulkOperationResults<String, Exception> bulkLog = new BulkOperationResults<>();
|
||||
for (String taskId : affectedTaskIds) {
|
||||
try {
|
||||
bulkLog.addAllErrors(taskService.classificationChanged(taskId, classificationId));
|
||||
} catch (Exception e) {
|
||||
bulkLog.addError(taskId, e);
|
||||
}
|
||||
}
|
||||
return bulkLog;
|
||||
}
|
||||
|
||||
}
|
|
@ -47,6 +47,7 @@ import pro.taskana.impl.util.LoggerUtils;
|
|||
import pro.taskana.mappings.AttachmentMapper;
|
||||
import pro.taskana.mappings.ClassificationMapper;
|
||||
import pro.taskana.mappings.DistributionTargetMapper;
|
||||
import pro.taskana.mappings.JobMapper;
|
||||
import pro.taskana.mappings.ObjectReferenceMapper;
|
||||
import pro.taskana.mappings.QueryMapper;
|
||||
import pro.taskana.mappings.TaskMapper;
|
||||
|
@ -325,6 +326,7 @@ public class TaskanaEngineImpl implements TaskanaEngine {
|
|||
configuration.addMapper(ObjectReferenceMapper.class);
|
||||
configuration.addMapper(QueryMapper.class);
|
||||
configuration.addMapper(AttachmentMapper.class);
|
||||
configuration.addMapper(JobMapper.class);
|
||||
configuration.getTypeHandlerRegistry().register(MapTypeHandler.class);
|
||||
SqlSessionFactory localSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
|
||||
return SqlSessionManager.newInstance(localSessionFactory);
|
||||
|
|
|
@ -93,6 +93,24 @@ public interface AttachmentMapper {
|
|||
})
|
||||
List<AttachmentSummaryImpl> findAttachmentSummariesByTaskIds(String[] taskIds);
|
||||
|
||||
@Select("<script>SELECT ID, TASK_ID, CREATED, MODIFIED, CLASSIFICATION_KEY, CLASSIFICATION_ID, RECEIVED "
|
||||
+ "FROM ATTACHMENT "
|
||||
+ "<where>"
|
||||
+ "CLASSIFICATION_ID = #{classificationId}"
|
||||
+ "</where>"
|
||||
+ "</script>")
|
||||
@Results(value = {
|
||||
@Result(property = "id", column = "ID"),
|
||||
@Result(property = "taskId", column = "TASK_ID"),
|
||||
@Result(property = "created", column = "CREATED"),
|
||||
@Result(property = "modified", column = "MODIFIED"),
|
||||
@Result(property = "classificationSummaryImpl.key", column = "CLASSIFICATION_KEY"),
|
||||
@Result(property = "classificationSummaryImpl.id", column = "CLASSIFICATION_ID"),
|
||||
@Result(property = "received", column = "RECEIVED"),
|
||||
})
|
||||
List<AttachmentSummaryImpl> findAttachmentSummariesByClassificationId(
|
||||
@Param("classificationId") String classificationId);
|
||||
|
||||
@Delete("DELETE FROM ATTACHMENT WHERE ID=#{attachmentId}")
|
||||
void deleteAttachment(@Param("attachmentId") String attachmentId);
|
||||
|
||||
|
@ -111,4 +129,12 @@ public interface AttachmentMapper {
|
|||
javaType = String.class, typeHandler = ClobTypeHandler.class)
|
||||
})
|
||||
String getCustomAttributesAsString(@Param("attachmentId") String attachmentId);
|
||||
|
||||
@Select("<script> SELECT DISTINCT TASK_ID FROM ATTACHMENT WHERE CLASSIFICATION_ID = #{classificationId} "
|
||||
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
|
||||
+ "</script>")
|
||||
@Results(value = {
|
||||
@Result(property = "taskId", column = "TASK_ID")})
|
||||
List<String> findTaskIdsAffectedByClassificationChange(@Param("classificationId") String classificationId);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package pro.taskana.mappings;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Result;
|
||||
import org.apache.ibatis.annotations.Results;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import org.apache.ibatis.annotations.Update;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import pro.taskana.impl.Job;
|
||||
import pro.taskana.impl.persistence.MapTypeHandler;
|
||||
|
||||
/**
|
||||
* This class is the mybatis mapping of the JOB table.
|
||||
*/
|
||||
public interface JobMapper {
|
||||
|
||||
@Insert("INSERT INTO JOB (JOB_ID, CREATED, STARTED, COMPLETED, STATE, EXECUTOR, ARGUMENTS) "
|
||||
+ "VALUES (NEXT VALUE FOR JOB_SEQ, #{job.created}, #{job.started}, #{job.completed}, #{job.state}, #{job.executor}, #{job.arguments,jdbcType=CLOB, javaType=java.util.Map,typeHandler=pro.taskana.impl.persistence.MapTypeHandler} )")
|
||||
void insertJob(@Param("job") Job job);
|
||||
|
||||
@Select("SELECT JOB_ID, CREATED, STARTED, COMPLETED, STATE, EXECUTOR, ARGUMENTS "
|
||||
+ "FROM JOB "
|
||||
+ "WHERE STATE IN ( 'READY') "
|
||||
+ "ORDER BY JOB_ID ")
|
||||
@Results(value = {
|
||||
@Result(property = "jobId", column = "JOB_ID"),
|
||||
@Result(property = "created", column = "CREATED"),
|
||||
@Result(property = "started", column = "STARTED"),
|
||||
@Result(property = "completed", column = "COMPLETED"),
|
||||
@Result(property = "state", column = "STATE"),
|
||||
@Result(property = "executor", column = "EXECUTOR"),
|
||||
@Result(property = "arguments", column = "ARGUMENTS", jdbcType = JdbcType.CLOB,
|
||||
javaType = Map.class, typeHandler = MapTypeHandler.class)
|
||||
})
|
||||
List<Job> findJobsToRun();
|
||||
|
||||
@Update(
|
||||
value = "UPDATE JOB SET CREATED = #{created}, STARTED = #{started}, COMPLETED = #{completed}, STATE = #{state}, EXECUTOR = #{executor}, "
|
||||
+ "ARGUMENTS = #{arguments,jdbcType=CLOB ,javaType=java.util.Map,typeHandler=pro.taskana.impl.persistence.MapTypeHandler} "
|
||||
+ "where JOB_ID = #{jobId}")
|
||||
void update(Job job);
|
||||
}
|
|
@ -27,7 +27,7 @@ public interface QueryMapper {
|
|||
String CLASSIFICATION_FINDBYID = "pro.taskana.mappings.ClassificationMapper.findById";
|
||||
String WORKBASKET_FINDSUMMARYBYKEY = "pro.taskana.mappings.WorkbasketMapper.findSummaryByKey";
|
||||
|
||||
@Select("<script>SELECT t.ID, t.CREATED, t.CLAIMED, t.COMPLETED, t.MODIFIED, t.PLANNED, t.DUE, t.NAME, t.CREATOR, t.DESCRIPTION, t.NOTE, t.PRIORITY, t.STATE, t.CLASSIFICATION_KEY, t.CLASSIFICATION_CATEGORY, t.DOMAIN, t.WORKBASKET_KEY, t.BUSINESS_PROCESS_ID, t.PARENT_BUSINESS_PROCESS_ID, t.OWNER, t.POR_COMPANY, t.POR_SYSTEM, t.POR_INSTANCE, t.POR_TYPE, t.POR_VALUE, t.IS_READ, t.IS_TRANSFERRED, t.CUSTOM_1, t.CUSTOM_2, t.CUSTOM_3, t.CUSTOM_4, t.CUSTOM_5, t.CUSTOM_6, t.CUSTOM_7, t.CUSTOM_8, t.CUSTOM_9, t.CUSTOM_10 "
|
||||
@Select("<script>SELECT t.ID, t.CREATED, t.CLAIMED, t.COMPLETED, t.MODIFIED, t.PLANNED, t.DUE, t.NAME, t.CREATOR, t.DESCRIPTION, t.NOTE, t.PRIORITY, t.STATE, t.CLASSIFICATION_KEY, t.CLASSIFICATION_CATEGORY, t.CLASSIFICATION_ID, t.WORKBASKET_ID, t.DOMAIN, t.WORKBASKET_KEY, t.BUSINESS_PROCESS_ID, t.PARENT_BUSINESS_PROCESS_ID, t.OWNER, t.POR_COMPANY, t.POR_SYSTEM, t.POR_INSTANCE, t.POR_TYPE, t.POR_VALUE, t.IS_READ, t.IS_TRANSFERRED, t.CUSTOM_1, t.CUSTOM_2, t.CUSTOM_3, t.CUSTOM_4, t.CUSTOM_5, t.CUSTOM_6, t.CUSTOM_7, t.CUSTOM_8, t.CUSTOM_9, t.CUSTOM_10 "
|
||||
+ "FROM TASK t "
|
||||
+ "<where>"
|
||||
+ "<if test='taskIds != null'>AND t.ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>)</if> "
|
||||
|
@ -49,6 +49,7 @@ public interface QueryMapper {
|
|||
+ "<if test='workbasketKeyDomainIn != null'>AND (<foreach item='item' collection='workbasketKeyDomainIn' separator=' OR '>(t.WORKBASKET_KEY = #{item.key} AND t.DOMAIN = #{item.domain})</foreach>)</if> "
|
||||
+ "<if test='classificationKeyIn != null'>AND t.CLASSIFICATION_KEY IN(<foreach item='item' collection='classificationKeyIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationKeyLike != null'>AND (<foreach item='item' collection='classificationKeyLike' separator=' OR '>UPPER(t.CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
|
||||
+ "<if test='classificationIdIn != null'>AND t.CLASSIFICATION_ID IN(<foreach item='item' collection='classificationIdIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationCategoryIn != null'>AND t.CLASSIFICATION_CATEGORY IN(<foreach item='item' collection='classificationCategoryIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationCategoryLike != null'>AND (<foreach item='item' collection='classificationCategoryLike' separator=' OR '>UPPER(t.CLASSIFICATION_CATEGORY) LIKE #{item}</foreach>)</if> "
|
||||
+ "<if test='ownerIn != null'>AND t.OWNER IN(<foreach item='item' collection='ownerIn' separator=',' >#{item}</foreach>)</if> "
|
||||
|
@ -119,7 +120,9 @@ public interface QueryMapper {
|
|||
@Result(property = "state", column = "STATE"),
|
||||
@Result(property = "workbasketSummaryImpl.domain", column = "DOMAIN"),
|
||||
@Result(property = "workbasketSummaryImpl.key", column = "WORKBASKET_KEY"),
|
||||
@Result(property = "workbasketSummaryImpl.id", column = "WORKBASKET_ID"),
|
||||
@Result(property = "classificationSummaryImpl.key", column = "CLASSIFICATION_KEY"),
|
||||
@Result(property = "classificationSummaryImpl.id", column = "CLASSIFICATION_ID"),
|
||||
@Result(property = "classificationSummaryImpl.domain", column = "DOMAIN"),
|
||||
@Result(property = "classificationSummaryImpl.category", column = "CLASSIFICATION_CATEGORY"),
|
||||
@Result(property = "businessProcessId", column = "BUSINESS_PROCESS_ID"),
|
||||
|
@ -154,6 +157,7 @@ public interface QueryMapper {
|
|||
+ "FROM CLASSIFICATION "
|
||||
+ "<where>"
|
||||
+ "<if test='key != null'>AND KEY IN(<foreach item='item' collection='key' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='idIn != null'>AND ID IN(<foreach item='item' collection='idIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='parentId != null'>AND PARENT_ID IN(<foreach item='item' collection='parentId' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='category != null'>AND CATEGORY IN(<foreach item='item' collection='category' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='type != null'>AND TYPE IN(<foreach item='item' collection='type' separator=',' >#{item}</foreach>)</if> "
|
||||
|
@ -364,6 +368,7 @@ public interface QueryMapper {
|
|||
+ "<if test='workbasketKeyDomainIn != null'>AND (<foreach item='item' collection='workbasketKeyDomainIn' separator=' OR '>(t.WORKBASKET_KEY = #{item.key} AND t.DOMAIN = #{item.domain})</foreach>)</if> "
|
||||
+ "<if test='classificationKeyIn != null'>AND t.CLASSIFICATION_KEY IN(<foreach item='item' collection='classificationKeyIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationKeyLike != null'>AND (<foreach item='item' collection='classificationKeyLike' separator=' OR '>UPPER(t.CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
|
||||
+ "<if test='classificationIdIn != null'>AND t.CLASSIFICATION_ID IN(<foreach item='item' collection='classificationIdIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationCategoryIn != null'>AND t.CLASSIFICATION_CATEGORY IN(<foreach item='item' collection='classificationCategoryIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationCategoryLike != null'>AND (<foreach item='item' collection='classificationCategoryLike' separator=' OR '>UPPER(t.CLASSIFICATION_CATEGORY) LIKE #{item}</foreach>)</if> "
|
||||
+ "<if test='ownerIn != null'>AND t.OWNER IN(<foreach item='item' collection='ownerIn' separator=',' >#{item}</foreach>)</if> "
|
||||
|
@ -425,6 +430,7 @@ public interface QueryMapper {
|
|||
@Select("<script>SELECT COUNT(ID) FROM CLASSIFICATION "
|
||||
+ "<where>"
|
||||
+ "<if test='key != null'>AND KEY IN(<foreach item='item' collection='key' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='idIn != null'>AND ID IN(<foreach item='item' collection='idIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='parentId != null'>AND PARENT_ID IN(<foreach item='item' collection='parentId' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='category != null'>AND CATEGORY IN(<foreach item='item' collection='category' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='type != null'>AND TYPE IN(<foreach item='item' collection='type' separator=',' >#{item}</foreach>)</if> "
|
||||
|
@ -577,6 +583,7 @@ public interface QueryMapper {
|
|||
+ "<if test='workbasketKeyDomainIn != null'>AND (<foreach item='item' collection='workbasketKeyDomainIn' separator=' OR '>(t.WORKBASKET_KEY = #{item.key} AND t.DOMAIN = #{item.domain})</foreach>)</if> "
|
||||
+ "<if test='classificationKeyIn != null'>AND t.CLASSIFICATION_KEY IN(<foreach item='item' collection='classificationKeyIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationKeyLike != null'>AND (<foreach item='item' collection='classificationKeyLike' separator=' OR '>UPPER(t.CLASSIFICATION_KEY) LIKE #{item}</foreach>)</if> "
|
||||
+ "<if test='classificationIdIn != null'>AND t.CLASSIFICATION_ID IN(<foreach item='item' collection='classificationIdIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationCategoryIn != null'>AND t.CLASSIFICATION_CATEGORY IN(<foreach item='item' collection='classificationCategoryIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='classificationCategoryLike != null'>AND (<foreach item='item' collection='classificationCategoryLike' separator=' OR '>UPPER(t.CLASSIFICATION_CATEGORY) LIKE #{item}</foreach>)</if> "
|
||||
+ "<if test='ownerIn != null'>AND t.OWNER IN(<foreach item='item' collection='ownerIn' separator=',' >#{item}</foreach>)</if> "
|
||||
|
@ -639,6 +646,7 @@ public interface QueryMapper {
|
|||
+ "FROM CLASSIFICATION"
|
||||
+ "<where>"
|
||||
+ "<if test='key != null'>AND KEY IN(<foreach item='item' collection='key' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='idIn != null'>AND ID IN(<foreach item='item' collection='idIn' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='parentId != null'>AND PARENT_ID IN(<foreach item='item' collection='parentId' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='category != null'>AND CATEGORY IN(<foreach item='item' collection='category' separator=',' >#{item}</foreach>)</if> "
|
||||
+ "<if test='type != null'>AND TYPE IN(<foreach item='item' collection='type' separator=',' >#{item}</foreach>)</if> "
|
||||
|
|
|
@ -166,6 +166,61 @@ public interface TaskMapper {
|
|||
List<TaskSummaryImpl> findTasksByWorkbasketIdAndState(@Param("workbasketKey") String workbasketKey,
|
||||
@Param("taskState") TaskState taskState);
|
||||
|
||||
@Select("<script>SELECT ID, CREATED, CLAIMED, COMPLETED, MODIFIED, PLANNED, DUE, NAME, CREATOR, DESCRIPTION, PRIORITY, STATE, CLASSIFICATION_CATEGORY, CLASSIFICATION_KEY, CLASSIFICATION_ID, WORKBASKET_ID, WORKBASKET_KEY, DOMAIN, BUSINESS_PROCESS_ID, PARENT_BUSINESS_PROCESS_ID, OWNER, POR_COMPANY, POR_SYSTEM, POR_INSTANCE, POR_TYPE, POR_VALUE, IS_READ, IS_TRANSFERRED, CUSTOM_ATTRIBUTES, CUSTOM_1, CUSTOM_2, CUSTOM_3, CUSTOM_4, CUSTOM_5, CUSTOM_6, CUSTOM_7, "
|
||||
+ "CUSTOM_8, CUSTOM_9, CUSTOM_10, CUSTOM_11, CUSTOM_12, CUSTOM_13, CUSTOM_14, CUSTOM_15, CUSTOM_16 "
|
||||
+ "FROM TASK "
|
||||
+ "WHERE CLASSIFICATION_ID = #{classificationId} "
|
||||
+ "AND STATE IN ( 'READY','CLAIMED') "
|
||||
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
|
||||
+ "</script>")
|
||||
@Results(value = {
|
||||
@Result(property = "taskId", column = "ID"),
|
||||
@Result(property = "created", column = "CREATED"),
|
||||
@Result(property = "claimed", column = "CLAIMED"),
|
||||
@Result(property = "completed", column = "COMPLETED"),
|
||||
@Result(property = "modified", column = "MODIFIED"),
|
||||
@Result(property = "planned", column = "PLANNED"),
|
||||
@Result(property = "due", column = "DUE"),
|
||||
@Result(property = "name", column = "NAME"),
|
||||
@Result(property = "creator", column = "CREATOR"),
|
||||
@Result(property = "note", column = "NOTE"),
|
||||
@Result(property = "priority", column = "PRIORITY"),
|
||||
@Result(property = "state", column = "STATE"),
|
||||
@Result(property = "classificationSummaryImpl.category", column = "CLASSIFICATION_CATEGORY"),
|
||||
@Result(property = "classificationSummaryImpl.key", column = "CLASSIFICATION_KEY"),
|
||||
@Result(property = "classificationSummaryImpl.id", column = "CLASSIFICATION_ID"),
|
||||
@Result(property = "workbasketSummaryImpl.id", column = "WORKBASKET_ID"),
|
||||
@Result(property = "workbasketSummaryImpl.key", column = "WORKBASKET_KEY"),
|
||||
@Result(property = "workbasketSummaryImpl.domain", column = "DOMAIN"),
|
||||
@Result(property = "domain", column = "DOMAIN"),
|
||||
@Result(property = "businessProcessId", column = "BUSINESS_PROCESS_ID"),
|
||||
@Result(property = "parentBusinessProcessId", column = "PARENT_BUSINESS_PROCESS_ID"),
|
||||
@Result(property = "owner", column = "OWNER"),
|
||||
@Result(property = "primaryObjRef.company", column = "POR_COMPANY"),
|
||||
@Result(property = "primaryObjRef.system", column = "POR_SYSTEM"),
|
||||
@Result(property = "primaryObjRef.systemInstance", column = "POR_INSTANCE"),
|
||||
@Result(property = "primaryObjRef.type", column = "POR_TYPE"),
|
||||
@Result(property = "primaryObjRef.value", column = "POR_VALUE"),
|
||||
@Result(property = "isRead", column = "IS_READ"),
|
||||
@Result(property = "isTransferred", column = "IS_TRANSFERRED"),
|
||||
@Result(property = "custom1", column = "CUSTOM_1"),
|
||||
@Result(property = "custom2", column = "CUSTOM_2"),
|
||||
@Result(property = "custom3", column = "CUSTOM_3"),
|
||||
@Result(property = "custom4", column = "CUSTOM_4"),
|
||||
@Result(property = "custom5", column = "CUSTOM_5"),
|
||||
@Result(property = "custom6", column = "CUSTOM_6"),
|
||||
@Result(property = "custom7", column = "CUSTOM_7"),
|
||||
@Result(property = "custom8", column = "CUSTOM_8"),
|
||||
@Result(property = "custom9", column = "CUSTOM_9"),
|
||||
@Result(property = "custom10", column = "CUSTOM_10"),
|
||||
@Result(property = "custom11", column = "CUSTOM_11"),
|
||||
@Result(property = "custom12", column = "CUSTOM_12"),
|
||||
@Result(property = "custom13", column = "CUSTOM_13"),
|
||||
@Result(property = "custom14", column = "CUSTOM_14"),
|
||||
@Result(property = "custom15", column = "CUSTOM_15"),
|
||||
@Result(property = "custom16", column = "CUSTOM_16")})
|
||||
List<TaskSummaryImpl> findTasksAffectedByClassificationChange(@Param("classificationId") String classificationId);
|
||||
|
||||
@Update("<script>"
|
||||
+ " UPDATE TASK SET MODIFIED = #{referencetask.modified}, STATE = #{referencetask.state}, WORKBASKET_KEY = #{referencetask.workbasketSummary.key}, WORKBASKET_ID= #{referencetask.workbasketSummary.id}, "
|
||||
+ " DOMAIN = #{referencetask.domain}, OWNER = #{referencetask.owner}, IS_READ = #{referencetask.isRead}, IS_TRANSFERRED = #{referencetask.isTransferred}"
|
||||
|
@ -221,4 +276,13 @@ public interface TaskMapper {
|
|||
void updateTasks(@Param("taskIds") List<String> taskIds, @Param("task") TaskImpl task,
|
||||
@Param("fields") CustomPropertySelector fields);
|
||||
|
||||
@Select("<script>SELECT ID, STATE FROM TASK "
|
||||
+ "WHERE ID IN(<foreach item='item' collection='taskIds' separator=',' >#{item}</foreach>) "
|
||||
+ "AND STATE IN ( 'READY','CLAIMED') "
|
||||
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
|
||||
+ "</script>")
|
||||
@Results(value = {
|
||||
@Result(property = "taskId", column = "ID")})
|
||||
List<String> filterTaskIdsForNotCompleted(@Param("taskIds") List<String> taskIds);
|
||||
|
||||
}
|
||||
|
|
|
@ -163,3 +163,21 @@ CREATE TABLE ATTACHMENT(
|
|||
PRIMARY KEY (ID),
|
||||
CONSTRAINT ATT_CLASS FOREIGN KEY (CLASSIFICATION_ID) REFERENCES CLASSIFICATION ON DELETE NO ACTION
|
||||
);
|
||||
|
||||
CREATE TABLE JOB(
|
||||
JOB_ID INTEGER NOT NULL,
|
||||
CREATED TIMESTAMP NULL,
|
||||
STARTED TIMESTAMP NULL,
|
||||
COMPLETED TIMESTAMP NULL,
|
||||
STATE VARCHAR(32) NULL,
|
||||
EXECUTOR VARCHAR(128) NOT NULL,
|
||||
ARGUMENTS CLOB NULL,
|
||||
PRIMARY KEY (JOB_ID)
|
||||
);
|
||||
|
||||
CREATE SEQUENCE JOB_SEQ
|
||||
MINVALUE 1
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
CACHE 10;
|
||||
|
||||
|
|
|
@ -80,6 +80,25 @@ public class DeleteClassificationAccTest extends AbstractAccTest {
|
|||
@Test
|
||||
public void testDeleteMasterClassification()
|
||||
throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ClassificationInUseException {
|
||||
|
||||
classificationService.deleteClassification("L3060", "");
|
||||
|
||||
boolean classificationNotFound = false;
|
||||
try {
|
||||
classificationService.getClassification("L3060", "DOMAIN_A");
|
||||
} catch (ClassificationNotFoundException e) {
|
||||
classificationNotFound = true;
|
||||
}
|
||||
assertTrue(classificationNotFound);
|
||||
}
|
||||
|
||||
@WithAccessId(
|
||||
userName = "dummy",
|
||||
groupNames = {"businessadmin"})
|
||||
@Test(expected = ClassificationInUseException.class)
|
||||
public void testDeleteMasterClassificationWithExistingAttachment()
|
||||
throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ClassificationInUseException {
|
||||
|
||||
classificationService.deleteClassification("L12010", "");
|
||||
|
||||
boolean classificationNotFound = false;
|
||||
|
|
|
@ -94,7 +94,7 @@ public class QueryClassificationAccTest extends AbstractAccTest {
|
|||
.list();
|
||||
|
||||
assertNotNull(classifications);
|
||||
assertEquals(23, classifications.size());
|
||||
assertEquals(25, classifications.size());
|
||||
|
||||
List<ClassificationSummary> documentTypes = classifications.stream()
|
||||
.filter(c -> c.getType().equals("DOCUMENT"))
|
||||
|
@ -106,7 +106,7 @@ public class QueryClassificationAccTest extends AbstractAccTest {
|
|||
.filter(c -> c.getType().equals("TASK"))
|
||||
.collect(
|
||||
Collectors.toList());
|
||||
assertEquals(21, taskTypes.size());
|
||||
assertEquals(23, taskTypes.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -167,7 +167,7 @@ public class QueryClassificationAccTest extends AbstractAccTest {
|
|||
.domainIn("DOMAIN_A")
|
||||
.list();
|
||||
assertNotNull(classifications);
|
||||
assertEquals(13, classifications.size());
|
||||
assertEquals(14, classifications.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -180,7 +180,7 @@ public class QueryClassificationAccTest extends AbstractAccTest {
|
|||
.typeIn("TASK")
|
||||
.list();
|
||||
assertNotNull(classifications);
|
||||
assertEquals(11, classifications.size());
|
||||
assertEquals(12, classifications.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -206,7 +206,7 @@ public class QueryClassificationAccTest extends AbstractAccTest {
|
|||
.list();
|
||||
|
||||
assertNotNull(classificationSummaryList);
|
||||
assertEquals(16, classificationSummaryList.size());
|
||||
assertEquals(17, classificationSummaryList.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -93,7 +93,7 @@ public class QueryClassificationWithPaginationAccTest extends AbstractAccTest {
|
|||
results = classificationService.createClassificationQuery()
|
||||
.domainIn("DOMAIN_A")
|
||||
.listPage(pageNumber, pageSize);
|
||||
assertThat(results.size(), equalTo(16));
|
||||
assertThat(results.size(), equalTo(17));
|
||||
|
||||
// Getting last results on multiple pages
|
||||
pageNumber = 2;
|
||||
|
@ -101,7 +101,7 @@ public class QueryClassificationWithPaginationAccTest extends AbstractAccTest {
|
|||
results = classificationService.createClassificationQuery()
|
||||
.domainIn("DOMAIN_A")
|
||||
.listPage(pageNumber, pageSize);
|
||||
assertThat(results.size(), equalTo(6));
|
||||
assertThat(results.size(), equalTo(7));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -159,7 +159,7 @@ public class QueryClassificationWithPaginationAccTest extends AbstractAccTest {
|
|||
long count = classificationService.createClassificationQuery()
|
||||
.domainIn("DOMAIN_A")
|
||||
.count();
|
||||
assertThat(count, equalTo(16L));
|
||||
assertThat(count, equalTo(17L));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,12 @@ import static org.junit.Assert.assertTrue;
|
|||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -16,11 +21,17 @@ import org.junit.runner.RunWith;
|
|||
import acceptance.AbstractAccTest;
|
||||
import pro.taskana.Classification;
|
||||
import pro.taskana.ClassificationService;
|
||||
import pro.taskana.Task;
|
||||
import pro.taskana.TaskService;
|
||||
import pro.taskana.exceptions.ClassificationNotFoundException;
|
||||
import pro.taskana.exceptions.ConcurrencyException;
|
||||
import pro.taskana.exceptions.InvalidArgumentException;
|
||||
import pro.taskana.exceptions.NotAuthorizedException;
|
||||
import pro.taskana.exceptions.TaskNotFoundException;
|
||||
import pro.taskana.impl.DaysToWorkingDaysConverter;
|
||||
import pro.taskana.impl.JobRunner;
|
||||
import pro.taskana.impl.TaskImpl;
|
||||
import pro.taskana.impl.report.impl.TimeIntervalColumnHeader;
|
||||
import pro.taskana.security.JAASRunner;
|
||||
import pro.taskana.security.WithAccessId;
|
||||
|
||||
|
@ -108,7 +119,8 @@ public class UpdateClassificationAccTest extends AbstractAccTest {
|
|||
groupNames = {"group_1", "businessadmin"})
|
||||
@Test
|
||||
public void testUpdateTaskOnClassificationKeyCategoryChange()
|
||||
throws TaskNotFoundException, ClassificationNotFoundException, NotAuthorizedException, ConcurrencyException {
|
||||
throws Exception {
|
||||
setupTest();
|
||||
TaskImpl beforeTask = (TaskImpl) taskanaEngine.getTaskService()
|
||||
.getTask("TKI:000000000000000000000000000000000000");
|
||||
|
||||
|
@ -168,4 +180,71 @@ public class UpdateClassificationAccTest extends AbstractAccTest {
|
|||
classification = classificationService.updateClassification(classification);
|
||||
}
|
||||
|
||||
@WithAccessId(
|
||||
userName = "dummy",
|
||||
groupNames = {"admin"})
|
||||
@Test
|
||||
public void testUpdateClassificationPrioServiceLevel()
|
||||
throws SQLException, ClassificationNotFoundException, NotAuthorizedException, ConcurrencyException,
|
||||
InterruptedException, TaskNotFoundException, InvalidArgumentException {
|
||||
String newEntryPoint = "updated EntryPoint";
|
||||
Instant before = Instant.now();
|
||||
ClassificationService classificationService = taskanaEngine.getClassificationService();
|
||||
Classification classification = classificationService
|
||||
.getClassification("CLI:100000000000000000000000000000000003");
|
||||
Instant createdBefore = classification.getCreated();
|
||||
Instant modifiedBefore = classification.getModified();
|
||||
classification.setPriority(1000);
|
||||
classification.setServiceLevel("P15D");
|
||||
|
||||
classificationService.updateClassification(classification);
|
||||
Thread.sleep(100);
|
||||
JobRunner runner = new JobRunner(taskanaEngine);
|
||||
runner.runJobs();
|
||||
// Get and check the new value
|
||||
Classification updatedClassification = classificationService
|
||||
.getClassification("CLI:100000000000000000000000000000000003");
|
||||
assertNotNull(updatedClassification);
|
||||
|
||||
assertTrue(modifiedBefore.isBefore(updatedClassification.getModified()));
|
||||
List<String> affectedTasks = new ArrayList<>(
|
||||
Arrays.asList("TKI:000000000000000000000000000000000000", "TKI:000000000000000000000000000000000003",
|
||||
"TKI:000000000000000000000000000000000004", "TKI:000000000000000000000000000000000005",
|
||||
"TKI:000000000000000000000000000000000006", "TKI:000000000000000000000000000000000007",
|
||||
"TKI:000000000000000000000000000000000008", "TKI:000000000000000000000000000000000009",
|
||||
"TKI:000000000000000000000000000000000010", "TKI:000000000000000000000000000000000011",
|
||||
"TKI:000000000000000000000000000000000012", "TKI:000000000000000000000000000000000013",
|
||||
"TKI:000000000000000000000000000000000014", "TKI:000000000000000000000000000000000015",
|
||||
"TKI:000000000000000000000000000000000016", "TKI:000000000000000000000000000000000017",
|
||||
"TKI:000000000000000000000000000000000018", "TKI:000000000000000000000000000000000019",
|
||||
"TKI:000000000000000000000000000000000020", "TKI:000000000000000000000000000000000021",
|
||||
"TKI:000000000000000000000000000000000022", "TKI:000000000000000000000000000000000023",
|
||||
"TKI:000000000000000000000000000000000024", "TKI:000000000000000000000000000000000025",
|
||||
"TKI:000000000000000000000000000000000026", "TKI:000000000000000000000000000000000027",
|
||||
"TKI:000000000000000000000000000000000028", "TKI:000000000000000000000000000000000029",
|
||||
"TKI:000000000000000000000000000000000030", "TKI:000000000000000000000000000000000031",
|
||||
"TKI:000000000000000000000000000000000032", "TKI:000000000000000000000000000000000033",
|
||||
"TKI:000000000000000000000000000000000034", "TKI:000000000000000000000000000000000035",
|
||||
"TKI:000000000000000000000000000000000053", "TKI:000000000000000000000000000000000054",
|
||||
"TKI:000000000000000000000000000000000055", "TKI:000000000000000000000000000000000100",
|
||||
"TKI:000000000000000000000000000000000101", "TKI:000000000000000000000000000000000102",
|
||||
"TKI:000000000000000000000000000000000103"));
|
||||
TaskService taskService = taskanaEngine.getTaskService();
|
||||
|
||||
DaysToWorkingDaysConverter converter = DaysToWorkingDaysConverter
|
||||
.initialize(Collections.singletonList(new TimeIntervalColumnHeader(0)), Instant.now());
|
||||
|
||||
for (String taskId : affectedTasks) {
|
||||
Task task = taskService.getTask(taskId);
|
||||
assertTrue(task.getModified().isAfter(before));
|
||||
assertTrue(task.getPriority() == 1000);
|
||||
long calendarDays = converter.convertWorkingDaysToDays(task.getPlanned(), 15);
|
||||
if (!taskId.equals("TKI:000000000000000000000000000000000008")
|
||||
&& !taskId.equals("TKI:000000000000000000000000000000000053")) {
|
||||
assertTrue(task.getDue().equals(task.getPlanned().plus(Duration.ofDays(calendarDays))));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ public class ClassificationQueryAccTest extends AbstractAccTest {
|
|||
.list();
|
||||
|
||||
assertNotNull(classificationSummaryList);
|
||||
assertEquals(16, classificationSummaryList.size());
|
||||
assertEquals(17, classificationSummaryList.size());
|
||||
}
|
||||
|
||||
@WithAccessId(userName = "businessadmin")
|
||||
|
@ -52,7 +52,7 @@ public class ClassificationQueryAccTest extends AbstractAccTest {
|
|||
.list();
|
||||
|
||||
assertNotNull(classificationSummaryList);
|
||||
assertEquals(16, classificationSummaryList.size());
|
||||
assertEquals(17, classificationSummaryList.size());
|
||||
}
|
||||
|
||||
@WithAccessId(userName = "admin")
|
||||
|
@ -65,7 +65,7 @@ public class ClassificationQueryAccTest extends AbstractAccTest {
|
|||
.list();
|
||||
|
||||
assertNotNull(classificationSummaryList);
|
||||
assertEquals(16, classificationSummaryList.size());
|
||||
assertEquals(17, classificationSummaryList.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -189,12 +189,8 @@ public class QueryTasksAccTest extends AbstractAccTest {
|
|||
.idIn("TKI:000000000000000000000000000000000000")
|
||||
.list();
|
||||
assertThat(results.size(), equalTo(1));
|
||||
assertThat(results.get(0).getAttachmentSummaries().size(), equalTo(1));
|
||||
assertThat(results.get(0).getAttachmentSummaries().size(), equalTo(3));
|
||||
AttachmentSummary att = results.get(0).getAttachmentSummaries().get(0);
|
||||
assertThat(att.getClassificationSummary(), equalTo(attachment.getClassificationSummary()));
|
||||
assertThat(att.getCreated(), equalTo(task.getAttachments().get(0).getCreated()));
|
||||
assertThat(att.getModified(), equalTo(task.getAttachments().get(0).getModified()));
|
||||
|
||||
}
|
||||
|
||||
@WithAccessId(
|
||||
|
|
|
@ -61,6 +61,8 @@ public class TestDataGenerator {
|
|||
new InputStreamReader(this.getClass().getResourceAsStream("/sql/distribution-targets.sql")));
|
||||
runner.runScript(
|
||||
new InputStreamReader(this.getClass().getResourceAsStream("/sql/object-reference.sql")));
|
||||
runner.runScript(
|
||||
new InputStreamReader(this.getClass().getResourceAsStream("/sql/attachment.sql")));
|
||||
} finally {
|
||||
|
||||
runner.closeConnection();
|
||||
|
|
|
@ -692,8 +692,7 @@ public class TaskServiceImplTest {
|
|||
doReturn(null).when(attachmentMapperMock).findAttachmentsByTaskId(task.getId());
|
||||
doReturn(task).when(cutSpy).completeTask(task.getId(), isForced);
|
||||
doReturn(classificationQueryImplMock).when(classificationServiceImplMock).createClassificationQuery();
|
||||
doReturn(classificationQueryImplMock).when(classificationQueryImplMock).domainIn(any());
|
||||
doReturn(classificationQueryImplMock).when(classificationQueryImplMock).keyIn(any());
|
||||
doReturn(classificationQueryImplMock).when(classificationQueryImplMock).idIn(any());
|
||||
doReturn(new ArrayList<>()).when(classificationQueryImplMock).list();
|
||||
List<ClassificationSummaryImpl> classificationList = Arrays
|
||||
.asList((ClassificationSummaryImpl) dummyClassification.asSummary());
|
||||
|
@ -714,8 +713,7 @@ public class TaskServiceImplTest {
|
|||
verify(taskMapperMock, times(1)).findById(task.getId());
|
||||
verify(attachmentMapperMock, times(1)).findAttachmentsByTaskId(task.getId());
|
||||
verify(classificationServiceImplMock, times(1)).createClassificationQuery();
|
||||
verify(classificationQueryImplMock, times(1)).domainIn(any());
|
||||
verify(classificationQueryImplMock, times(1)).keyIn(any());
|
||||
verify(classificationQueryImplMock, times(1)).idIn(any());
|
||||
verify(classificationQueryImplMock, times(1)).list();
|
||||
verify(taskMapperMock, times(1)).update(any());
|
||||
verify(taskanaEngineMock, times(2)).returnConnection();
|
||||
|
@ -1146,8 +1144,7 @@ public class TaskServiceImplTest {
|
|||
doReturn(null).when(attachmentMapperMock).findAttachmentsByTaskId(expectedTask.getId());
|
||||
|
||||
doReturn(classificationQueryImplMock).when(classificationServiceImplMock).createClassificationQuery();
|
||||
doReturn(classificationQueryImplMock).when(classificationQueryImplMock).domainIn(any());
|
||||
doReturn(classificationQueryImplMock).when(classificationQueryImplMock).keyIn(any());
|
||||
doReturn(classificationQueryImplMock).when(classificationQueryImplMock).idIn(any());
|
||||
doReturn(workbasketQueryImplMock).when(workbasketServiceMock).createWorkbasketQuery();
|
||||
doReturn(workbasketQueryImplMock).when(workbasketQueryImplMock).idIn(any());
|
||||
List<WorkbasketSummary> wbList = new ArrayList<>();
|
||||
|
@ -1167,8 +1164,7 @@ public class TaskServiceImplTest {
|
|||
verify(taskMapperMock, times(1)).findById(expectedTask.getId());
|
||||
verify(attachmentMapperMock, times(1)).findAttachmentsByTaskId(expectedTask.getId());
|
||||
verify(classificationServiceImplMock, times(1)).createClassificationQuery();
|
||||
verify(classificationQueryImplMock, times(1)).domainIn(any());
|
||||
verify(classificationQueryImplMock, times(1)).keyIn(any());
|
||||
verify(classificationQueryImplMock, times(1)).idIn(any());
|
||||
verify(classificationQueryImplMock, times(1)).list();
|
||||
verify(workbasketServiceMock, times(1)).createWorkbasketQuery();
|
||||
verify(workbasketQueryImplMock, times(1)).idIn(any());
|
||||
|
@ -1379,6 +1375,7 @@ public class TaskServiceImplTest {
|
|||
classification.setName("dummy-classification");
|
||||
classification.setDomain("dummy-domain");
|
||||
classification.setKey("dummy-classification-key");
|
||||
classification.setId("DummyClassificationId");
|
||||
return classification;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,11 @@ public class TestClassificationQuery implements ClassificationQuery {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassificationQuery idIn(String... id) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassificationQuery parentIdIn(String... parentId) {
|
||||
this.parentId = parentId;
|
||||
|
@ -287,4 +292,5 @@ public class TestClassificationQuery implements ClassificationQuery {
|
|||
public List<String> listValues(String dbColumnName, SortDirection sortDirection) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
-- ATTACHMENT TABLE (ID , task_ID , CREATED , MODIFIED , classif key, classif Id , refCompany, ref sys, ref inst,ref type, ref val, channel,received, custAtts)
|
||||
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000000','TKI:000000000000000000000000000000000000', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'L1050' , 'CLI:100000000000000000000000000000000003', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000001','TKI:000000000000000000000000000000000001', '2018-01-29 15:55:01', '2018-01-30 15:55:00', 'L10303' , 'CLI:000000000000000000000000000000000002', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000002','TKI:000000000000000000000000000000000001', '2018-01-29 15:55:02', '2018-01-30 15:55:00', 'L1050' , 'CLI:000000000000000000000000000000000003', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000003','TKI:000000000000000000000000000000000002', '2018-01-29 15:55:03', null , 'L11010' , 'CLI:000000000000000000000000000000000004', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000004','TKI:000000000000000000000000000000000002', '2018-01-29 15:55:04', null , 'L110102' , 'CLI:000000000000000000000000000000000005', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000005','TKI:000000000000000000000000000000000002', '2018-01-29 15:55:05', null , 'L110105' , 'CLI:000000000000000000000000000000000006', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000006','TKI:000000000000000000000000000000000002', '2018-01-29 15:55:06', null , 'L110107' , 'CLI:000000000000000000000000000000000007', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000007','TKI:000000000000000000000000000000000002', '2018-01-29 15:55:07', null , 'L12010' , 'CLI:000000000000000000000000000000000008', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000008','TKI:000000000000000000000000000000000008', '2018-01-29 15:55:08', null , 'L140101' , 'CLI:000000000000000000000000000000000009', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000009','TKI:000000000000000000000000000000000000', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'L1050' , 'CLI:100000000000000000000000000000000003', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000010','TKI:000000000000000000000000000000000053', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'L1050' , 'CLI:100000000000000000000000000000000003', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000011','TKI:000000000000000000000000000000000053', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'L1050' , 'CLI:100000000000000000000000000000000003', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000012','TKI:000000000000000000000000000000000054', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'L1050' , 'CLI:100000000000000000000000000000000003', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
||||
INSERT INTO ATTACHMENT VALUES('TAI:000000000000000000000000000000000013','TKI:000000000000000000000000000000000055', '2018-01-29 15:55:00', '2018-01-30 15:55:00', 'L1050' , 'CLI:100000000000000000000000000000000003', 'novatec' , 'novasys', 'nvinst', 'typ1', 'val1', 'ch1', null, null);
|
|
@ -13,6 +13,7 @@ INSERT INTO CLASSIFICATION VALUES('CLI:000000000000000000000000000000000010', 'T
|
|||
INSERT INTO CLASSIFICATION VALUES('CLI:000000000000000000000000000000000011', 'T6310', '', 'AUTOMATIC', 'TASK', '', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'T-GUK Honorarrechnung erstellen', 'Generali Unterstützungskasse Honorar wird fällig', 2, 'P11D', '', 'VNR', '', '', '', '', '', '', '');
|
||||
INSERT INTO CLASSIFICATION VALUES('CLI:000000000000000000000000000000000013', 'DOCTYPE_DEFAULT', '', 'EXTERN', 'DOCUMENT', '', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'EP allgemein', 'EP allgemein', 99, 'P2000D', '', 'VNR', '', '', '', '', '', '', '');
|
||||
INSERT INTO CLASSIFICATION VALUES('CLI:000000000000000000000000000000000017', 'L1060', '', 'EXTERN', 'TASK', '', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'Widerruf neu', 'Widerruf neu', 1, 'P1D', '', 'VNR,RVNR,KOLVNR', '', '', '', '', '', '', '');
|
||||
INSERT INTO CLASSIFICATION VALUES('CLI:300000000000000000000000000000000017', 'L3060', '', 'EXTERN', 'TASK', '', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'Widerruf neu', 'Widerruf neu', 1, 'P1D', '', 'VNR,RVNR,KOLVNR', '', '', '', '', '', '', '');
|
||||
|
||||
-- DOMAIN_A CLASSIFICATIONS
|
||||
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000002', 'L10303', '', 'EXTERN', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'Beratungsprotokoll', 'Beratungsprotokoll', 101, 'PT7H', '', 'VNR,RVNR,KOLVNR, ANR', '', '', '', '', '', '', '');
|
||||
|
@ -29,6 +30,7 @@ INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000013', 'D
|
|||
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000014', 'L10000', '', 'EXTERN', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'BUZ-Leistungsfall', 'BUZ-Leistungsfall', 1, 'P1D', '', 'VNR,RVNR,KOLVNR', 'VNR', 'VNR', 'VNR', '', '', '', '');
|
||||
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000016', 'T2000', '', 'MANUAL', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'T-Vertragstermin', 'T-Vertragstermin', 1, 'P1D', '', 'VNR,KOLVNR,RVNR', 'CUSTOM_2', 'Custom_3', 'custom_4', '', '', '', '');
|
||||
INSERT INTO CLASSIFICATION VALUES('CLI:100000000000000000000000000000000017', 'L1060', '', 'EXTERN', 'TASK', 'DOMAIN_A', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'Widerruf neu', 'Widerruf neu', 1, 'P1D', '', 'VNR,RVNR,KOLVNR', '', '', '', '', '', '', '');
|
||||
INSERT INTO CLASSIFICATION VALUES('CLI:400000000000000000000000000000000017', 'L3060', '', 'EXTERN', 'TASK', 'DOMAIN_A', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'Widerruf neu', 'Widerruf neu', 1, 'P1D', '', 'VNR,RVNR,KOLVNR', '', '', '', '', '', '', '');
|
||||
|
||||
-- DOMAIN_B CLASSIFICATIONS
|
||||
INSERT INTO CLASSIFICATION VALUES('CLI:200000000000000000000000000000000015', 'T2100', '', 'MANUAL', 'TASK', 'DOMAIN_B', TRUE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'T-Vertragstermin VERA', 'T-Vertragstermin VERA', 22, 'P2D', '', 'VNR', '', '', '', '', '', '', '');
|
||||
|
|
|
@ -5,4 +5,5 @@ DELETE FROM CLASSIFICATION;
|
|||
DELETE FROM WORKBASKET_ACCESS_LIST;
|
||||
DELETE FROM OBJECT_REFERENCE;
|
||||
DELETE FROM ATTACHMENT;
|
||||
DELETE FROM JOB;
|
||||
COMMIT;
|
||||
|
|
|
@ -6,4 +6,6 @@ DROP TABLE CLASSIFICATION;
|
|||
DROP TABLE WORKBASKET_ACCESS_LIST;
|
||||
DROP TABLE OBJECT_REFERENCE;
|
||||
DROP TABLE ATTACHMENT;
|
||||
DROP TABLE JOB;
|
||||
DROP SEQUENCE JOB_SEQ;
|
||||
COMMIT;
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
import pro.taskana.sampledata.SampleDataGenerator;
|
||||
|
||||
|
@ -16,6 +17,7 @@ import pro.taskana.sampledata.SampleDataGenerator;
|
|||
* Example Application showing the implementation of taskana-rest-spring.
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
@Import(RestConfiguration.class)
|
||||
public class ExampleRestApplication {
|
||||
|
||||
|
@ -24,7 +26,7 @@ public class ExampleRestApplication {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@DependsOn("taskanaEngineConfiguration") //generate sample data after schema was inserted
|
||||
@DependsOn("taskanaEngineConfiguration") // generate sample data after schema was inserted
|
||||
public SampleDataGenerator generateSampleData(DataSource dataSource) throws SQLException {
|
||||
SampleDataGenerator sampleDataGenerator = new SampleDataGenerator(dataSource);
|
||||
sampleDataGenerator.generateSampleData();
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package pro.taskana.rest;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import pro.taskana.TaskanaEngine;
|
||||
import pro.taskana.impl.BulkOperationResults;
|
||||
import pro.taskana.impl.JobRunner;
|
||||
import pro.taskana.impl.util.LoggerUtils;
|
||||
|
||||
/**
|
||||
* This class invokes the JobRunner periodically to schedule long running jobs.
|
||||
*
|
||||
* @author bbr
|
||||
*/
|
||||
@Component
|
||||
public class JobScheduler {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JobScheduler.class);
|
||||
@Autowired
|
||||
private TaskanaEngine taskanaEngine;
|
||||
|
||||
@Scheduled(fixedRate = 60000)
|
||||
public void triggerJobs() {
|
||||
JobRunner runner = new JobRunner(taskanaEngine);
|
||||
LOGGER.info("Running Jobs");
|
||||
BulkOperationResults<String, Exception> result = runner.runJobs();
|
||||
Map<String, Exception> errors = result.getErrorMap();
|
||||
LOGGER.info("Job run completed. Result = {} ", LoggerUtils.mapToString(errors));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue