TSK-1764: added filter parameter to WorkbasketPriorityReport API.

This commit is contained in:
holgerhagen 2021-11-02 20:25:54 +01:00 committed by holgerhagen
parent e05120cc93
commit 2bdfe4dbc3
11 changed files with 1218 additions and 44 deletions

View File

@ -3,10 +3,10 @@ INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000000', 'ETI:0000000
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000001', 'ETI:000000000000000000000000000000000001', RELATIVE_DATE(-2) , RELATIVE_DATE(0) , null , RELATIVE_DATE(0) , null , RELATIVE_DATE(-2) , RELATIVE_DATE(0) , 'Task01' , 'creator_user_id' , 'Lorem ipsum was n Quatsch dolor sit amet.', 'Some custom Note' , 2 , -1 , 'CLAIMED' , 'EXTERN' , 'L110102' , 'CLI:100000000000000000000000000000000005', 'WBI:100000000000000000000000000000000006' , 'USER-1-1' , 'DOMAIN_A', 'BPI21' , 'PBPI21' , 'user-1-1' , 'MyCompany1', 'MySystem1', 'MyInstance1' , 'MyType1', 'MyValue1' , true , false , null , 'NONE' , null , 'pqr' , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000002', 'ETI:000000000000000000000000000000000002', RELATIVE_DATE(-2) , RELATIVE_DATE(0) , null , RELATIVE_DATE(0) , RELATIVE_DATE(0) , RELATIVE_DATE(-2) , RELATIVE_DATE(0) , 'Task02' , 'creator_user_id' , 'Lorem ipsum was n Quatsch t. Aber stimmt.', 'Some custom Note' , 2 , -1 , 'CLAIMED' , 'MANUAL' , 'T2000' , 'CLI:100000000000000000000000000000000016', 'WBI:100000000000000000000000000000000006' , 'USER-1-1' , 'DOMAIN_A', 'BPI21' , 'PBPI21' , 'user-1-1' , 'MyCompany1', 'MySystem1', 'MyInstance1' , 'MyType1', 'MyValue1' , true , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000003', 'ETI:000000000000000000000000000000000003', RELATIVE_DATE(-2) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(0) , RELATIVE_DATE(-2) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000003' , 'DOC_0000000000000000003' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , 'efg' , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000004', 'ETI:000000000000000000000000000000000004', RELATIVE_DATE(-3) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000004' , 'DOC_0000000000000000004' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , 'ade' , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000005', 'ETI:000000000000000000000000000000000005', RELATIVE_DATE(-4) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(-4) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000005' , 'DOC_0000000000000000005' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000006', 'ETI:000000000000000000000000000000000006', RELATIVE_DATE(-5) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(-5) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000006' , 'DOC_0000000000000000006' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000007', 'ETI:000000000000000000000000000000000007', RELATIVE_DATE(-6) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(-6) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000007' , 'DOC_0000000000000000007' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , null , 'ffg' , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000004', 'ETI:000000000000000000000000000000000004', RELATIVE_DATE(-3) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000004' , 'DOC_0000000000000000004' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , 'ade' , null , null , null , '074' , '' , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000005', 'ETI:000000000000000000000000000000000005', RELATIVE_DATE(-4) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(-4) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000005' , 'DOC_0000000000000000005' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , null , null , null , null , '074' , '' , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000006', 'ETI:000000000000000000000000000000000006', RELATIVE_DATE(-5) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(-5) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2000 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000006' , 'DOC_0000000000000000006' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , null , null , null , null , '075' , '' , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000007', 'ETI:000000000000000000000000000000000007', RELATIVE_DATE(-6) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(-6) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000007' , 'DOC_0000000000000000007' , null , '00' , 'PASystem' , '00' , 'VNR' , '11223344' , false , false , null , 'NONE' , null , null , null , 'ffg' , null , null , '075' , '20' , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000008', 'ETI:000000000000000000000000000000000008', RELATIVE_DATE(-6) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(-6) , RELATIVE_DATE(0) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000008' , 'DOC_0000000000000000008' , null , '00' , 'PASystem' , '00' , 'VNR' , '22334455' , false , false , null , 'NONE' , null , null , null , null , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000009', 'ETI:000000000000000000000000000000000009', RELATIVE_DATE(-7) , null , null , RELATIVE_DATE(0) , RELATIVE_DATE(-3) , RELATIVE_DATE(-7) , RELATIVE_DATE(-4) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000009' , 'DOC_0000000000000000009' , null , '00' , 'PASystem' , '00' , 'VNR' , '22334455' , false , false , null , 'NONE' , null , null , null , 'rty99' , null , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );
INSERT INTO TASK VALUES('TKI:000000000000000000000000000000000010', 'ETI:000000000000000000000000000000000010', RELATIVE_DATE(-8) , null , null , RELATIVE_DATE(-2) , RELATIVE_DATE(-3) , RELATIVE_DATE(-8) , RELATIVE_DATE(-2) , 'Widerruf' , 'creator_user_id' , 'Widerruf' , null , 2 , -1 , 'READY' , 'EXTERN' , 'L1050' , 'CLI:100000000000000000000000000000000003', 'WBI:100000000000000000000000000000000001' , 'GPK_KSC' , 'DOMAIN_A', 'PI_0000000000010' , 'DOC_0000000000000000010' , null , '00' , 'PASystem' , '00' , 'VNR' , '22334455' , false , false , null , 'NONE' , null , null , null , null , '99rty' , null , null , null , null , null , null , null , null , null , 'abc' , null , null , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 );

View File

@ -2,11 +2,14 @@ package pro.taskana.monitor.api.reports;
import java.util.List;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.monitor.api.reports.header.ColumnHeader;
import pro.taskana.monitor.api.reports.header.PriorityColumnHeader;
import pro.taskana.monitor.api.reports.item.PriorityQueryItem;
import pro.taskana.monitor.api.reports.row.Row;
import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskState;
import pro.taskana.task.api.models.Task;
import pro.taskana.workbasket.api.WorkbasketType;
import pro.taskana.workbasket.api.models.Workbasket;
@ -39,6 +42,111 @@ public class WorkbasketPriorityReport extends Report<PriorityQueryItem, Priority
*/
Builder workbasketTypeIn(WorkbasketType... workbasketTypes);
/**
* Adds a list of workbasket ids to the builder. The created report contains only tasks with a
* workbasket id in this list.
*
* @param workbasketIds a list of workbasket ids
* @return the TimeIntervalReportBuilder
*/
Builder workbasketIdIn(List<String> workbasketIds);
/**
* Adds a list of states to the builder. The created report contains only tasks with a state in
* this list.
*
* @param states a list of states
* @return the TimeIntervalReportBuilder
*/
Builder stateIn(List<TaskState> states);
/**
* Adds a list of classificationCategories to the builder. The created report contains only
* tasks with a category in this list.
*
* @param classificationCategory a list of classificationCategories
* @return the TimeIntervalReportBuilder
*/
Builder classificationCategoryIn(List<String> classificationCategory);
/**
* Adds a list of classificationIds to the builder. The created report contains only tasks with
* a classificationId in this list.
*
* @param classificationIds a list of classificationIds
* @return the TimeIntervalReportBuilder
*/
Builder classificationIdIn(List<String> classificationIds);
/**
* Adds a list of excludedClassificationIds to the builder. The created report contains only
* tasks with a classificationId NOT in this list.
*
* @param excludedClassificationIds a list of excludedClassificationIds
* @return the TimeIntervalReportBuilder
*/
Builder excludedClassificationIdIn(List<String> excludedClassificationIds);
/**
* Adds a list of domains to the builder. The created report contains only tasks with a domain
* in this list.
*
* @param domains a list of domains
* @return the TimeIntervalReportBuilder
*/
Builder domainIn(List<String> domains);
/**
* Adds the values of a certain {@linkplain TaskCustomField} for exact matching to the builder.
*
* <p>The created report contains only tasks with a {@linkplain
* Task#getCustomAttribute(TaskCustomField) custom attribute} value exactly matching one of the
* items in the list.
*
* @param customField the specified {@linkplain TaskCustomField}
* @param strings the values the specified {@linkplain Task#getCustomAttribute(TaskCustomField)
* custom attribute} should match
* @return the modified {@linkplain TimeIntervalReportBuilder}
* @throws InvalidArgumentException if filter values are not given
*/
Builder customAttributeIn(TaskCustomField customField, String... strings)
throws InvalidArgumentException;
/**
* Excludes the values of a certain {@linkplain TaskCustomField} to the builder.
*
* <p>The created report contains only tasks with a {@linkplain
* Task#getCustomAttribute(TaskCustomField) custom attribute} value not matching one of the
* items in the list.
*
* @param customField the specified {@linkplain TaskCustomField}
* @param strings the values the specified {@linkplain Task#getCustomAttribute(TaskCustomField)
* custom attribute} should not match
* @return the modified {@linkplain TimeIntervalReportBuilder}
* @throws InvalidArgumentException if filter values are not given
*/
Builder customAttributeNotIn(TaskCustomField customField, String... strings)
throws InvalidArgumentException;
/**
* Adds the values of a certain {@linkplain TaskCustomField} for pattern matching to the
* builder.
*
* <p>The created report contains only tasks with a {@linkplain
* Task#getCustomAttribute(TaskCustomField) custom attribute} value pattern-matching one of the
* items in the list. They will be compared in SQL with the LIKE operator. You may use a
* wildcard like % to specify the pattern. If you specify multiple arguments they are combined
* with the OR keyword.
*
* @param customField the specified {@linkplain TaskCustomField}
* @param strings the values the specified {@linkplain Task#getCustomAttribute(TaskCustomField)
* custom attribute} should match
* @return the modified {@linkplain TimeIntervalReportBuilder}
* @throws InvalidArgumentException if filter values are not given
*/
Builder customAttributeLike(TaskCustomField customField, String... strings)
throws InvalidArgumentException;
/**
* Adds a list of {@linkplain PriorityColumnHeader}s to the builder to subdivide the report into
* clusters.
@ -47,5 +155,12 @@ public class WorkbasketPriorityReport extends Report<PriorityQueryItem, Priority
* @return the builder
*/
Builder withColumnHeaders(List<PriorityColumnHeader> columnHeaders);
/**
* If this filter is used, the days of the report are counted in working days.
*
* @return the TimeIntervalReportBuilder
*/
Builder inWorkingDays();
}
}

View File

@ -31,7 +31,7 @@ public class MonitorMapperSqlProvider {
+ "</if> "
+ "FROM TASK AS T LEFT JOIN ATTACHMENT AS A ON T.ID = A.TASK_ID "
+ OPENING_WHERE_TAG
+ timeIntervalWhereStatements()
+ taskWhereStatements()
+ "<if test=\"report.combinedClassificationFilter != null\">"
+ "AND <foreach collection='report.combinedClassificationFilter' "
+ "item='item' separator='OR'> "
@ -65,7 +65,7 @@ public class MonitorMapperSqlProvider {
+ "</if> "
+ "FROM TASK T "
+ OPENING_WHERE_TAG
+ timeIntervalWhereStatements()
+ taskWhereStatements()
+ "AND ${timestamp} IS NOT NULL "
+ CLOSING_WHERE_TAG
+ ") AS B "
@ -90,7 +90,7 @@ public class MonitorMapperSqlProvider {
+ "</if> "
+ "FROM TASK T "
+ OPENING_WHERE_TAG
+ timeIntervalWhereStatements()
+ taskWhereStatements()
+ "AND ${timestamp} IS NOT NULL "
+ CLOSING_WHERE_TAG
+ ") AS B "
@ -116,7 +116,7 @@ public class MonitorMapperSqlProvider {
+ "</if> "
+ "FROM TASK AS T LEFT JOIN ATTACHMENT AS A ON T.ID = A.TASK_ID "
+ OPENING_WHERE_TAG
+ timeIntervalWhereStatements()
+ taskWhereStatements()
+ "AND T.${timestamp} IS NOT NULL "
+ CLOSING_WHERE_TAG
+ ") AS B "
@ -140,7 +140,7 @@ public class MonitorMapperSqlProvider {
+ "</if> "
+ "FROM TASK T "
+ OPENING_WHERE_TAG
+ timeIntervalWhereStatements()
+ taskWhereStatements()
+ "AND ${timestamp} IS NOT NULL "
+ CLOSING_WHERE_TAG
+ ") AS B "
@ -156,7 +156,7 @@ public class MonitorMapperSqlProvider {
+ "LEFT JOIN ATTACHMENT A ON T.ID = A.TASK_ID "
+ "</if>"
+ OPENING_WHERE_TAG
+ timeIntervalWhereStatements()
+ taskWhereStatements()
+ "<if test=\"combinedClassificationFilter != null\">"
+ "AND <foreach collection='combinedClassificationFilter' item='item' separator='OR'> "
+ "T.CLASSIFICATION_ID = #{item.taskClassificationId} "
@ -197,7 +197,7 @@ public class MonitorMapperSqlProvider {
public static String getTasksCountByState() {
return OPENING_SCRIPT_TAG
+ "SELECT WORKBASKET_KEY, STATE, COUNT(STATE) as COUNT "
+ "FROM TASK "
+ "FROM TASK AS T"
+ OPENING_WHERE_TAG
+ whereIn("domains", "DOMAIN")
+ whereIn("states", "STATE")
@ -237,11 +237,7 @@ public class MonitorMapperSqlProvider {
+ "<if test=\"status.name() == 'COMPLETED'\">"
+ "T.COMPLETED IS NOT NULL "
+ "</if>"
+ whereIn("report.classificationCategory", "T.CLASSIFICATION_CATEGORY")
+ whereIn("report.domains", "T.DOMAIN")
+ whereIn("report.classificationIds", "T.CLASSIFICATION_ID")
+ whereNotIn("report.excludedClassificationIds", "T.CLASSIFICATION_ID")
+ whereCustomStatements("report.custom", "T.CUSTOM", 16)
+ taskWhereStatements()
+ CLOSING_WHERE_TAG
+ ") AS A "
+ "GROUP BY A.AGE_IN_DAYS, A.ORG_LEVEL_1, A.ORG_LEVEL_2, A.ORG_LEVEL_3, A.ORG_LEVEL_4 "
@ -257,7 +253,7 @@ public class MonitorMapperSqlProvider {
+ "LEFT JOIN ATTACHMENT A ON T.ID = A.TASK_ID "
+ "</if>"
+ OPENING_WHERE_TAG
+ timeIntervalWhereStatements()
+ taskWhereStatements()
+ "<if test=\"combinedClassificationFilter != null\">"
+ "AND <foreach collection='combinedClassificationFilter' item='item' separator='OR'> "
+ "T.CLASSIFICATION_ID = #{item.taskClassificationId} "
@ -277,7 +273,8 @@ public class MonitorMapperSqlProvider {
+ "FROM TASK as T "
+ "INNER JOIN WORKBASKET as W ON W.ID = T.WORKBASKET_ID "
+ OPENING_WHERE_TAG
+ whereIn("report.workbasketType", "W.TYPE")
+ taskWhereStatements()
+ workbasketWhereStatements()
+ CLOSING_WHERE_TAG
+ "GROUP BY T.WORKBASKET_KEY, T.PRIORITY"
+ CLOSING_SCRIPT_TAG;
@ -301,15 +298,21 @@ public class MonitorMapperSqlProvider {
return whereCustomStatements(baseCollection, baseColumn, customBound, new StringBuilder());
}
private static StringBuilder timeIntervalWhereStatements() {
private static StringBuilder taskWhereStatements() {
StringBuilder sb = new StringBuilder();
SqlProviderUtil.whereIn("report.workbasketIds", "T.WORKBASKET_ID", sb);
SqlProviderUtil.whereIn("report.states", "T.STATE", sb);
SqlProviderUtil.whereIn("report.classificationCategory", "T.CLASSIFICATION_CATEGORY", sb);
SqlProviderUtil.whereIn("report.classificationCategories", "T.CLASSIFICATION_CATEGORY", sb);
SqlProviderUtil.whereIn("report.domains", "T.DOMAIN", sb);
SqlProviderUtil.whereIn("report.classificationIds", "T.CLASSIFICATION_ID", sb);
SqlProviderUtil.whereNotIn("report.excludedClassificationIds", "T.CLASSIFICATION_ID", sb);
whereCustomStatements("report.custom", "T.CUSTOM", 16, sb);
return sb;
}
private static StringBuilder workbasketWhereStatements() {
StringBuilder sb = new StringBuilder();
SqlProviderUtil.whereIn("report.workbasketTypes", "W.TYPE", sb);
return sb;
}
}

View File

@ -43,7 +43,7 @@ abstract class TimeIntervalReportBuilderImpl<
protected boolean inWorkingDays;
protected List<String> workbasketIds;
protected List<TaskState> states;
protected List<String> classificationCategory;
protected List<String> classificationCategories;
protected List<String> domains;
protected List<String> classificationIds;
protected List<String> excludedClassificationIds;
@ -129,8 +129,8 @@ abstract class TimeIntervalReportBuilderImpl<
}
@Override
public B classificationCategoryIn(List<String> classificationCategory) {
this.classificationCategory = new ArrayList<>(classificationCategory);
public B classificationCategoryIn(List<String> classificationCategories) {
this.classificationCategories = new ArrayList<>(classificationCategories);
return _this();
}

View File

@ -1,28 +1,88 @@
package pro.taskana.monitor.internal.reports;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import pro.taskana.common.api.TaskanaRole;
import pro.taskana.common.api.WorkingDaysToDaysConverter;
import pro.taskana.common.api.exceptions.InvalidArgumentException;
import pro.taskana.common.api.exceptions.NotAuthorizedException;
import pro.taskana.common.api.exceptions.SystemException;
import pro.taskana.common.internal.InternalTaskanaEngine;
import pro.taskana.monitor.api.reports.WorkbasketPriorityReport;
import pro.taskana.monitor.api.reports.WorkbasketPriorityReport.Builder;
import pro.taskana.monitor.api.reports.header.PriorityColumnHeader;
import pro.taskana.monitor.api.reports.item.PriorityQueryItem;
import pro.taskana.monitor.internal.MonitorMapper;
import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskState;
import pro.taskana.workbasket.api.WorkbasketType;
public class WorkbasketPriorityReportBuilderImpl implements WorkbasketPriorityReport.Builder {
private final InternalTaskanaEngine taskanaEngine;
private final MonitorMapper monitorMapper;
protected List<PriorityColumnHeader> columnHeaders;
protected boolean inWorkingDays;
protected List<String> workbasketIds;
protected List<TaskState> states;
protected List<String> classificationCategories;
protected List<String> domains;
protected List<String> classificationIds;
protected List<String> excludedClassificationIds;
protected WorkingDaysToDaysConverter converter;
private WorkbasketType[] workbasketTypes;
private String[] custom1In;
private String[] custom1NotIn;
private String[] custom1Like;
private String[] custom2In;
private String[] custom2NotIn;
private String[] custom2Like;
private String[] custom3In;
private String[] custom3NotIn;
private String[] custom3Like;
private String[] custom4In;
private String[] custom4NotIn;
private String[] custom4Like;
private String[] custom5In;
private String[] custom5NotIn;
private String[] custom5Like;
private String[] custom6In;
private String[] custom6NotIn;
private String[] custom6Like;
private String[] custom7In;
private String[] custom7NotIn;
private String[] custom7Like;
private String[] custom8In;
private String[] custom8NotIn;
private String[] custom8Like;
private String[] custom9In;
private String[] custom9NotIn;
private String[] custom9Like;
private String[] custom10In;
private String[] custom10NotIn;
private String[] custom10Like;
private String[] custom11In;
private String[] custom11NotIn;
private String[] custom11Like;
private String[] custom12In;
private String[] custom12NotIn;
private String[] custom12Like;
private String[] custom13In;
private String[] custom13NotIn;
private String[] custom13Like;
private String[] custom14In;
private String[] custom14NotIn;
private String[] custom14Like;
private String[] custom15In;
private String[] custom15NotIn;
private String[] custom15Like;
private String[] custom16In;
private String[] custom16NotIn;
private String[] custom16Like;
@SuppressWarnings("unused")
private WorkbasketType[] workbasketType;
private List<PriorityColumnHeader> columnHeaders;
public WorkbasketPriorityReportBuilderImpl(
InternalTaskanaEngine taskanaEngine, MonitorMapper monitorMapper) {
this.taskanaEngine = taskanaEngine;
@ -36,15 +96,14 @@ public class WorkbasketPriorityReportBuilderImpl implements WorkbasketPriorityRe
WorkbasketPriorityReport report = new WorkbasketPriorityReport(columnHeaders);
List<PriorityQueryItem> items =
taskanaEngine.executeInDatabaseConnection(
() -> monitorMapper.getTaskCountByPriority(this));
taskanaEngine.executeInDatabaseConnection(() -> monitorMapper.getTaskCountByPriority(this));
report.addItems(items);
return report;
}
@Override
public Builder workbasketTypeIn(WorkbasketType... workbasketTypes) {
this.workbasketType = workbasketTypes;
this.workbasketTypes = workbasketTypes;
return this;
}
@ -53,4 +112,251 @@ public class WorkbasketPriorityReportBuilderImpl implements WorkbasketPriorityRe
this.columnHeaders = columnHeaders;
return this;
}
@Override
public Builder inWorkingDays() {
this.inWorkingDays = true;
return this;
}
@Override
public Builder workbasketIdIn(List<String> workbasketIds) {
this.workbasketIds = new ArrayList<>(workbasketIds);
return this;
}
@Override
public Builder stateIn(List<TaskState> states) {
this.states = new ArrayList<>(states);
return this;
}
@Override
public Builder classificationCategoryIn(List<String> classificationCategories) {
this.classificationCategories = new ArrayList<>(classificationCategories);
return this;
}
@Override
public Builder classificationIdIn(List<String> classificationIds) {
this.classificationIds = new ArrayList<>(classificationIds);
return this;
}
@Override
public Builder excludedClassificationIdIn(List<String> excludedClassificationIds) {
this.excludedClassificationIds = new ArrayList<>(excludedClassificationIds);
return this;
}
@Override
public Builder domainIn(List<String> domains) {
this.domains = new ArrayList<>(domains);
return this;
}
@Override
public Builder customAttributeIn(TaskCustomField customField, String... strings)
throws InvalidArgumentException {
if (strings.length == 0) {
throw new InvalidArgumentException(
"At least one string has to be provided as a search parameter");
}
switch (customField) {
case CUSTOM_1:
this.custom1In = strings;
break;
case CUSTOM_2:
this.custom2In = strings;
break;
case CUSTOM_3:
this.custom3In = strings;
break;
case CUSTOM_4:
this.custom4In = strings;
break;
case CUSTOM_5:
this.custom5In = strings;
break;
case CUSTOM_6:
this.custom6In = strings;
break;
case CUSTOM_7:
this.custom7In = strings;
break;
case CUSTOM_8:
this.custom8In = strings;
break;
case CUSTOM_9:
this.custom9In = strings;
break;
case CUSTOM_10:
this.custom10In = strings;
break;
case CUSTOM_11:
this.custom11In = strings;
break;
case CUSTOM_12:
this.custom12In = strings;
break;
case CUSTOM_13:
this.custom13In = strings;
break;
case CUSTOM_14:
this.custom14In = strings;
break;
case CUSTOM_15:
this.custom15In = strings;
break;
case CUSTOM_16:
this.custom16In = strings;
break;
default:
throw new SystemException("Unknown custom attribute '" + customField + "'");
}
return this;
}
@Override
public Builder customAttributeNotIn(TaskCustomField customField, String... strings)
throws InvalidArgumentException {
if (strings.length == 0) {
throw new InvalidArgumentException(
"At least one string has to be provided as a search parameter");
}
switch (customField) {
case CUSTOM_1:
this.custom1NotIn = strings;
break;
case CUSTOM_2:
this.custom2NotIn = strings;
break;
case CUSTOM_3:
this.custom3NotIn = strings;
break;
case CUSTOM_4:
this.custom4NotIn = strings;
break;
case CUSTOM_5:
this.custom5NotIn = strings;
break;
case CUSTOM_6:
this.custom6NotIn = strings;
break;
case CUSTOM_7:
this.custom7NotIn = strings;
break;
case CUSTOM_8:
this.custom8NotIn = strings;
break;
case CUSTOM_9:
this.custom9NotIn = strings;
break;
case CUSTOM_10:
this.custom10NotIn = strings;
break;
case CUSTOM_11:
this.custom11NotIn = strings;
break;
case CUSTOM_12:
this.custom12NotIn = strings;
break;
case CUSTOM_13:
this.custom13NotIn = strings;
break;
case CUSTOM_14:
this.custom14NotIn = strings;
break;
case CUSTOM_15:
this.custom15NotIn = strings;
break;
case CUSTOM_16:
this.custom16NotIn = strings;
break;
default:
throw new SystemException("Unknown custom attribute '" + customField + "'");
}
return this;
}
@Override
public Builder customAttributeLike(TaskCustomField customField, String... strings)
throws InvalidArgumentException {
if (strings.length == 0) {
throw new InvalidArgumentException(
"At least one string has to be provided as a search parameter");
}
switch (customField) {
case CUSTOM_1:
this.custom1Like = toUpperCopy(strings);
break;
case CUSTOM_2:
this.custom2Like = toUpperCopy(strings);
break;
case CUSTOM_3:
this.custom3Like = toUpperCopy(strings);
break;
case CUSTOM_4:
this.custom4Like = toUpperCopy(strings);
break;
case CUSTOM_5:
this.custom5Like = toUpperCopy(strings);
break;
case CUSTOM_6:
this.custom6Like = toUpperCopy(strings);
break;
case CUSTOM_7:
this.custom7Like = toUpperCopy(strings);
break;
case CUSTOM_8:
this.custom8Like = toUpperCopy(strings);
break;
case CUSTOM_9:
this.custom9Like = toUpperCopy(strings);
break;
case CUSTOM_10:
this.custom10Like = toUpperCopy(strings);
break;
case CUSTOM_11:
this.custom11Like = toUpperCopy(strings);
break;
case CUSTOM_12:
this.custom12Like = toUpperCopy(strings);
break;
case CUSTOM_13:
this.custom13Like = toUpperCopy(strings);
break;
case CUSTOM_14:
this.custom14Like = toUpperCopy(strings);
break;
case CUSTOM_15:
this.custom15Like = toUpperCopy(strings);
break;
case CUSTOM_16:
this.custom16Like = toUpperCopy(strings);
break;
default:
throw new SystemException("Unknown custom field '" + customField + "'");
}
return this;
}
private String[] toUpperCopy(String... source) {
if (source == null || source.length == 0) {
// we are currently aware that this is a code smell. Unfortunately the resolution of this
// would cause havoc in our queries, since we do not have a concept
// for a user input validation yet. As soon as that is done we can resolve this code smell.
return null;
} else {
String[] target = new String[source.length];
for (int i = 0; i < source.length; i++) {
target[i] = source[i].toUpperCase();
}
return target;
}
}
}

View File

@ -18,6 +18,8 @@ import pro.taskana.monitor.api.reports.Report;
import pro.taskana.monitor.api.reports.WorkbasketPriorityReport;
import pro.taskana.monitor.api.reports.header.PriorityColumnHeader;
import pro.taskana.monitor.api.reports.row.Row;
import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskState;
import pro.taskana.workbasket.api.WorkbasketType;
/** Acceptance test for all "workbasket priority report" scenarios. */
@ -83,4 +85,149 @@ class ProvideWorkbasketPriorityReportAccTest extends AbstractReportAccTest {
.extracting(Row::getCells)
.isEqualTo(expectedCells);
}
@WithAccessId(user = "monitor")
@Test
void should_ReturnItemsOfWorkbasketReport_When_FilteringWithCustomAttributeIn() throws Exception {
WorkbasketPriorityReport report =
MONITOR_SERVICE
.createWorkbasketPriorityReportBuilder()
.withColumnHeaders(DEFAULT_TEST_HEADERS)
.customAttributeIn(TaskCustomField.CUSTOM_1, "Geschaeftsstelle B")
.inWorkingDays()
.buildReport();
assertThat(report).isNotNull();
assertThat(report.getSumRow().getTotalValue()).isEqualTo(11);
assertThat(report.rowSize()).isEqualTo(3);
int[] row1 = report.getRow("USER-1-1").getCells();
assertThat(row1).isEqualTo(new int[] {5, 0, 0});
int[] row2 = report.getRow("USER-1-2").getCells();
assertThat(row2).isEqualTo(new int[] {5, 0, 0});
int[] row3 = report.getRow("GPK-1").getCells();
assertThat(row3).isEqualTo(new int[] {0, 1, 0});
}
@WithAccessId(user = "monitor")
@Test
void should_ReturnItemsOfWorkbasketReport_When_FilteringWithCustomAttributeNotIn()
throws Exception {
WorkbasketPriorityReport report =
MONITOR_SERVICE
.createWorkbasketPriorityReportBuilder()
.withColumnHeaders(DEFAULT_TEST_HEADERS)
.customAttributeNotIn(
TaskCustomField.CUSTOM_1, "Geschaeftsstelle A", "Geschaeftsstelle C")
.inWorkingDays()
.buildReport();
assertThat(report).isNotNull();
assertThat(report.getSumRow().getTotalValue()).isEqualTo(11);
assertThat(report.rowSize()).isEqualTo(3);
int[] row1 = report.getRow("USER-1-1").getCells();
assertThat(row1).isEqualTo(new int[] {5, 0, 0});
int[] row2 = report.getRow("USER-1-2").getCells();
assertThat(row2).isEqualTo(new int[] {5, 0, 0});
int[] row3 = report.getRow("GPK-1").getCells();
assertThat(row3).isEqualTo(new int[] {0, 1, 0});
}
@WithAccessId(user = "monitor")
@Test
void should_ReturnItemsOfWorkbasketReport_When_FilteringWithCustomAttributeLike()
throws Exception {
WorkbasketPriorityReport report =
MONITOR_SERVICE
.createWorkbasketPriorityReportBuilder()
.withColumnHeaders(DEFAULT_TEST_HEADERS)
.customAttributeLike(TaskCustomField.CUSTOM_1, "%ftsstelle B")
.inWorkingDays()
.buildReport();
assertThat(report).isNotNull();
assertThat(report.getSumRow().getTotalValue()).isEqualTo(11);
assertThat(report.rowSize()).isEqualTo(3);
int[] row1 = report.getRow("USER-1-1").getCells();
assertThat(row1).isEqualTo(new int[] {5, 0, 0});
int[] row2 = report.getRow("USER-1-2").getCells();
assertThat(row2).isEqualTo(new int[] {5, 0, 0});
int[] row3 = report.getRow("GPK-1").getCells();
assertThat(row3).isEqualTo(new int[] {0, 1, 0});
}
@WithAccessId(user = "monitor")
@Test
void should_ReturnItemsOfWorkbasketReport_When_FilteringWithStateIn() throws Exception {
List<TaskState> states = List.of(TaskState.READY);
WorkbasketPriorityReport report =
MONITOR_SERVICE
.createWorkbasketPriorityReportBuilder()
.withColumnHeaders(DEFAULT_TEST_HEADERS)
.stateIn(states)
.inWorkingDays()
.buildReport();
assertThat(report).isNotNull();
assertThat(report.rowSize()).isEqualTo(4);
int[] row1 = report.getRow("USER-1-1").getCells();
assertThat(row1).isEqualTo(new int[] {18, 0, 0});
int[] row2 = report.getRow("USER-1-2").getCells();
assertThat(row2).isEqualTo(new int[] {19, 0, 0});
int[] row3 = report.getRow("USER-1-3").getCells();
assertThat(row3).isEqualTo(new int[] {4, 0, 0});
int[] row4 = report.getRow("GPK-1").getCells();
assertThat(row4).isEqualTo(new int[] {0, 1, 0});
}
@WithAccessId(user = "monitor")
@Test
void should_ReturnItemsOfWorkbasketReport_When_FilteringWithDomainIn() throws Exception {
List<String> domains = List.of("DOMAIN_A");
WorkbasketPriorityReport report =
MONITOR_SERVICE
.createWorkbasketPriorityReportBuilder()
.withColumnHeaders(DEFAULT_TEST_HEADERS)
.domainIn(domains)
.inWorkingDays()
.buildReport();
assertThat(report).isNotNull();
assertThat(report.rowSize()).isEqualTo(4);
int[] row1 = report.getRow("USER-1-1").getCells();
assertThat(row1).isEqualTo(new int[] {12, 0, 0});
int[] row2 = report.getRow("USER-1-2").getCells();
assertThat(row2).isEqualTo(new int[] {10, 0, 0});
int[] row3 = report.getRow("USER-1-3").getCells();
assertThat(row3).isEqualTo(new int[] {4, 0, 0});
int[] row4 = report.getRow("TPK-VIP-1").getCells();
assertThat(row4).isEqualTo(new int[] {0, 1, 0});
}
@WithAccessId(user = "monitor")
@Test
void should_ReturnItemsOfWorkbasketReport_When_FilteringWithClassificationCategoryIn()
throws Exception {
List<String> categories = List.of("AUTOMATIC", "MANUAL");
WorkbasketPriorityReport report =
MONITOR_SERVICE
.createWorkbasketPriorityReportBuilder()
.withColumnHeaders(DEFAULT_TEST_HEADERS)
.classificationCategoryIn(categories)
.inWorkingDays()
.buildReport();
assertThat(report).isNotNull();
assertThat(report.rowSize()).isEqualTo(4);
int[] row1 = report.getRow("USER-1-1").getCells();
assertThat(row1).isEqualTo(new int[] {8, 0, 0});
int[] row2 = report.getRow("USER-1-2").getCells();
assertThat(row2).isEqualTo(new int[] {4, 0, 0});
int[] row3 = report.getRow("USER-1-3").getCells();
assertThat(row3).isEqualTo(new int[] {5, 0, 0});
int[] row4 = report.getRow("TPK-VIP-1").getCells();
assertThat(row4).isEqualTo(new int[] {0, 1, 0});
}
}

View File

@ -28,6 +28,7 @@ import pro.taskana.monitor.api.reports.header.PriorityColumnHeader;
import pro.taskana.monitor.rest.assembler.PriorityColumnHeaderRepresentationModelAssembler;
import pro.taskana.monitor.rest.assembler.ReportRepresentationModelAssembler;
import pro.taskana.monitor.rest.models.PriorityColumnHeaderRepresentationModel;
import pro.taskana.monitor.rest.models.PriorityReportFilterParameter;
import pro.taskana.monitor.rest.models.ReportRepresentationModel;
import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskState;
@ -107,6 +108,7 @@ public class MonitorController {
@GetMapping(path = RestEndpoints.URL_MONITOR_WORKBASKET_PRIORITY_REPORT)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<ReportRepresentationModel> computePriorityWorkbasketReport(
PriorityReportFilterParameter filterParameter,
@RequestParam(name = "workbasket-type", required = false) WorkbasketType[] workbasketTypes,
@RequestParam(name = "columnHeader", required = false)
PriorityColumnHeaderRepresentationModel[] columnHeaders)
@ -114,6 +116,7 @@ public class MonitorController {
WorkbasketPriorityReport.Builder builder =
monitorService.createWorkbasketPriorityReportBuilder().workbasketTypeIn(workbasketTypes);
filterParameter.apply(builder);
if (columnHeaders != null) {
List<PriorityColumnHeader> priorityColumnHeaders =
@ -125,7 +128,7 @@ public class MonitorController {
ReportRepresentationModel report =
reportRepresentationModelAssembler.toModel(
builder.buildReport(), workbasketTypes, columnHeaders);
builder.buildReport(), filterParameter, workbasketTypes, columnHeaders);
return ResponseEntity.status(HttpStatus.OK).body(report);
}
@ -289,9 +292,9 @@ public class MonitorController {
@GetMapping(path = RestEndpoints.URL_MONITOR_TASK_STATUS_REPORT)
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<ReportRepresentationModel> computeTaskStatusReport(
@RequestParam(required = false) List<String> domains,
@RequestParam(required = false) List<TaskState> states,
@RequestParam(name = "workbasket-ids", required = false) List<String> workbasketIds,
@RequestParam(name = "domain", required = false) List<String> domains,
@RequestParam(name = "state", required = false) List<TaskState> states,
@RequestParam(name = "workbasket-id", required = false) List<String> workbasketIds,
@RequestParam(name = "priority-minimum", required = false) Integer priorityMinimum)
throws NotAuthorizedException {

View File

@ -33,6 +33,7 @@ import pro.taskana.monitor.api.reports.row.SingleRow;
import pro.taskana.monitor.rest.MonitorController;
import pro.taskana.monitor.rest.TimeIntervalReportFilterParameter;
import pro.taskana.monitor.rest.models.PriorityColumnHeaderRepresentationModel;
import pro.taskana.monitor.rest.models.PriorityReportFilterParameter;
import pro.taskana.monitor.rest.models.ReportRepresentationModel;
import pro.taskana.monitor.rest.models.ReportRepresentationModel.RowRepresentationModel;
import pro.taskana.task.api.TaskCustomField;
@ -61,6 +62,7 @@ public class ReportRepresentationModelAssembler {
@NonNull
public ReportRepresentationModel toModel(
@NonNull WorkbasketPriorityReport report,
@NonNull PriorityReportFilterParameter filterParameter,
WorkbasketType[] workbasketTypes,
PriorityColumnHeaderRepresentationModel[] columnHeaders)
throws InvalidArgumentException, NotAuthorizedException {
@ -68,7 +70,8 @@ public class ReportRepresentationModelAssembler {
resource.add(
linkTo(
methodOn(MonitorController.class)
.computePriorityWorkbasketReport(workbasketTypes, columnHeaders))
.computePriorityWorkbasketReport(
filterParameter, workbasketTypes, columnHeaders))
.withSelfRel());
return resource;
}
@ -137,8 +140,8 @@ public class ReportRepresentationModelAssembler {
@NonNull
public ReportRepresentationModel toModel(
@NonNull TaskStatusReport report,
@NonNull List<String> domains,
@NonNull List<TaskState> states,
@NonNull List<String> domain,
@NonNull List<TaskState> state,
@NonNull List<String> workbasketIds,
@NonNull Integer priorityMinimum)
throws NotAuthorizedException {
@ -146,7 +149,7 @@ public class ReportRepresentationModelAssembler {
resource.add(
linkTo(
methodOn(MonitorController.class)
.computeTaskStatusReport(domains, states, workbasketIds, priorityMinimum))
.computeTaskStatusReport(domain, state, workbasketIds, priorityMinimum))
.withSelfRel());
return resource;
}

View File

@ -0,0 +1,573 @@
package pro.taskana.monitor.rest.models;
import static pro.taskana.common.internal.util.CheckedConsumer.wrap;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.beans.ConstructorProperties;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import pro.taskana.common.internal.util.Pair;
import pro.taskana.common.rest.QueryParameter;
import pro.taskana.monitor.api.reports.WorkbasketPriorityReport;
import pro.taskana.monitor.api.reports.header.PriorityColumnHeader;
import pro.taskana.task.api.TaskCustomField;
import pro.taskana.task.api.TaskState;
public class PriorityReportFilterParameter
implements QueryParameter<WorkbasketPriorityReport.Builder, Void> {
/** Determine weather the report should convert the age of the tasks into working days. */
@JsonProperty("in-working-days")
private final Boolean inWorkingDays;
/** Filter by workbasket id of the task. This is an exact match. */
@JsonProperty("workbasket-id")
private final String[] workbasketId;
/** Filter by the task state. This is an exact match. */
@JsonProperty("state")
private final TaskState[] state;
/** Filter by the classification category of the task. This is an exact match. */
@JsonProperty("classification-category")
private final String[] classificationCategory;
/** Filter by domain of the task. This is an exact match. */
@JsonProperty("domain")
private final String[] domain;
/** Filter by the classification id of the task. This is an exact match. */
@JsonProperty("classification-id")
private final String[] classificationId;
/** Filter by the classification id of the task. This is an exact match. */
@JsonProperty("excluded-classification-id")
private final String[] excludedClassificationId;
/** Filter by the value of the field custom1 of the task. This is an exact match. */
@JsonProperty("custom-1")
private final String[] custom1;
/**
* Filter by the custom1 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-1-like")
private final String[] custom1Like;
/** Filter out by values of the field custom1 of the task. This is an exact match. */
@JsonProperty("custom-1-not-in")
private final String[] custom1NotIn;
/** Filter by the value of the field custom2 of the task. This is an exact match. */
@JsonProperty("custom-2")
private final String[] custom2;
/**
* Filter by the custom2 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-2-like")
private final String[] custom2Like;
/** Filter out by values of the field custom2 of the task. This is an exact match. */
@JsonProperty("custom-2-not-in")
private final String[] custom2NotIn;
/** Filter by the value of the field custom3 of the task. This is an exact match. */
@JsonProperty("custom-3")
private final String[] custom3;
/**
* Filter by the custom3 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-3-like")
private final String[] custom3Like;
/** Filter out by values of the field custom3 of the task. This is an exact match. */
@JsonProperty("custom-3-not-in")
private final String[] custom3NotIn;
/** Filter by the value of the field custom4 of the task. This is an exact match. */
@JsonProperty("custom-4")
private final String[] custom4;
/**
* Filter by the custom4 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-4-like")
private final String[] custom4Like;
/** Filter out by values of the field custom4 of the task. This is an exact match. */
@JsonProperty("custom-4-not-in")
private final String[] custom4NotIn;
/** Filter by the value of the field custom5 of the task. This is an exact match. */
@JsonProperty("custom-5")
private final String[] custom5;
/**
* Filter by the custom5 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-5-like")
private final String[] custom5Like;
/** Filter out by values of the field custom5 of the task. This is an exact match. */
@JsonProperty("custom-5-not-in")
private final String[] custom5NotIn;
/** Filter by the value of the field custom6 of the task. This is an exact match. */
@JsonProperty("custom-6")
private final String[] custom6;
/**
* Filter by the custom6 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-6-like")
private final String[] custom6Like;
/** Filter out by values of the field custom6 of the task. This is an exact match. */
@JsonProperty("custom-6-not-in")
private final String[] custom6NotIn;
/** Filter by the value of the field custom7 of the task. This is an exact match. */
@JsonProperty("custom-7")
private final String[] custom7;
/**
* Filter by the custom7 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-7-like")
private final String[] custom7Like;
/** Filter out by values of the field custom7 of the task. This is an exact match. */
@JsonProperty("custom-7-not-in")
private final String[] custom7NotIn;
/** Filter by the value of the field custom8 of the task. This is an exact match. */
@JsonProperty("custom-8")
private final String[] custom8;
/**
* Filter by the custom8 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-8-like")
private final String[] custom8Like;
/** Filter out by values of the field custom8 of the task. This is an exact match. */
@JsonProperty("custom-8-not-in")
private final String[] custom8NotIn;
/** Filter by the value of the field custom9 of the task. This is an exact match. */
@JsonProperty("custom-9")
private final String[] custom9;
/**
* Filter by the custom9 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-9-like")
private final String[] custom9Like;
/** Filter out by values of the field custom9 of the task. This is an exact match. */
@JsonProperty("custom-9-not-in")
private final String[] custom9NotIn;
/** Filter by the value of the field custom10 of the task. This is an exact match. */
@JsonProperty("custom-10")
private final String[] custom10;
/**
* Filter by the custom10 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-10-like")
private final String[] custom10Like;
/** Filter out by values of the field custom10 of the task. This is an exact match. */
@JsonProperty("custom-10-not-in")
private final String[] custom10NotIn;
/** Filter by the value of the field custom11 of the task. This is an exact match. */
@JsonProperty("custom-11")
private final String[] custom11;
/**
* Filter by the custom11 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-11-like")
private final String[] custom11Like;
/** Filter out by values of the field custom11 of the task. This is an exact match. */
@JsonProperty("custom-11-not-in")
private final String[] custom11NotIn;
/** Filter by the value of the field custom12 of the task. This is an exact match. */
@JsonProperty("custom-12")
private final String[] custom12;
/**
* Filter by the custom12 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-12-like")
private final String[] custom12Like;
/** Filter out by values of the field custom12 of the task. This is an exact match. */
@JsonProperty("custom-12-not-in")
private final String[] custom12NotIn;
/** Filter by the value of the field custom13 of the task. This is an exact match. */
@JsonProperty("custom-13")
private final String[] custom13;
/**
* Filter by the custom13 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-13-like")
private final String[] custom13Like;
/** Filter out by values of the field custom13 of the task. This is an exact match. */
@JsonProperty("custom-13-not-in")
private final String[] custom13NotIn;
/** Filter by the value of the field custom14 of the task. This is an exact match. */
@JsonProperty("custom-14")
private final String[] custom14;
/**
* Filter by the custom14 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-14-like")
private final String[] custom14Like;
/** Filter out by values of the field custom14 of the task. This is an exact match. */
@JsonProperty("custom-14-not-in")
private final String[] custom14NotIn;
/** Filter by the value of the field custom15 of the task. This is an exact match. */
@JsonProperty("custom-15")
private final String[] custom15;
/**
* Filter by the custom15 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-15-like")
private final String[] custom15Like;
/** Filter out by values of the field custom15 of the task. This is an exact match. */
@JsonProperty("custom-15-not-in")
private final String[] custom15NotIn;
/** Filter by the value of the field custom16 of the task. This is an exact match. */
@JsonProperty("custom-16")
private final String[] custom16;
/**
* Filter by the custom16 field of the task. This results in a substring search (% is appended to
* the front and end of the requested value). Further SQL "LIKE" wildcard characters will be
* resolved correctly.
*/
@JsonProperty("custom-16-like")
private final String[] custom16Like;
/** Filter out by values of the field custom16 of the task. This is an exact match. */
@JsonProperty("custom-16-not-in")
private final String[] custom16NotIn;
@ConstructorProperties({
"in-working-days",
"workbasket-id",
"state",
"classification-category",
"domain",
"classification-id",
"excluded-classification-id",
"custom-1",
"custom-1-like",
"custom-1-not-in",
"custom-2",
"custom-2-like",
"custom-2-not-in",
"custom-3",
"custom-3-like",
"custom-3-not-in",
"custom-4",
"custom-4-like",
"custom-4-not-in",
"custom-5",
"custom-5-like",
"custom-5-not-in",
"custom-6",
"custom-6-like",
"custom-6-not-in",
"custom-7",
"custom-7-like",
"custom-7-not-in",
"custom-8",
"custom-8-like",
"custom-8-not-in",
"custom-9",
"custom-9-like",
"custom-9-not-in",
"custom-10",
"custom-10-like",
"custom-10-not-in",
"custom-11",
"custom-11-like",
"custom-11-not-in",
"custom-12",
"custom-12-like",
"custom-12-not-in",
"custom-13",
"custom-13-like",
"custom-13-not-in",
"custom-14",
"custom-14-like",
"custom-14-not-in",
"custom-15",
"custom-15-like",
"custom-15-not-in",
"custom-16",
"custom-16-like",
"custom-16-not-in"
})
public PriorityReportFilterParameter(
Boolean inWorkingDays,
String[] workbasketId,
TaskState[] state,
String[] classificationCategory,
String[] domain,
String[] classificationId,
String[] excludedClassificationId,
String[] custom1,
String[] custom1Like,
String[] custom1NotIn,
String[] custom2,
String[] custom2Like,
String[] custom2NotIn,
String[] custom3,
String[] custom3Like,
String[] custom3NotIn,
String[] custom4,
String[] custom4Like,
String[] custom4NotIn,
String[] custom5,
String[] custom5Like,
String[] custom5NotIn,
String[] custom6,
String[] custom6Like,
String[] custom6NotIn,
String[] custom7,
String[] custom7Like,
String[] custom7NotIn,
String[] custom8,
String[] custom8Like,
String[] custom8NotIn,
String[] custom9,
String[] custom9Like,
String[] custom9NotIn,
String[] custom10,
String[] custom10Like,
String[] custom10NotIn,
String[] custom11,
String[] custom11Like,
String[] custom11NotIn,
String[] custom12,
String[] custom12Like,
String[] custom12NotIn,
String[] custom13,
String[] custom13Like,
String[] custom13NotIn,
String[] custom14,
String[] custom14Like,
String[] custom14NotIn,
String[] custom15,
String[] custom15Like,
String[] custom15NotIn,
String[] custom16,
String[] custom16Like,
String[] custom16NotIn) {
this.inWorkingDays = inWorkingDays;
this.workbasketId = workbasketId;
this.state = state;
this.classificationCategory = classificationCategory;
this.domain = domain;
this.classificationId = classificationId;
this.excludedClassificationId = excludedClassificationId;
this.custom1 = custom1;
this.custom1Like = custom1Like;
this.custom1NotIn = custom1NotIn;
this.custom2 = custom2;
this.custom2Like = custom2Like;
this.custom2NotIn = custom2NotIn;
this.custom3 = custom3;
this.custom3Like = custom3Like;
this.custom3NotIn = custom3NotIn;
this.custom4 = custom4;
this.custom4Like = custom4Like;
this.custom4NotIn = custom4NotIn;
this.custom5 = custom5;
this.custom5Like = custom5Like;
this.custom5NotIn = custom5NotIn;
this.custom6 = custom6;
this.custom6Like = custom6Like;
this.custom6NotIn = custom6NotIn;
this.custom7 = custom7;
this.custom7Like = custom7Like;
this.custom7NotIn = custom7NotIn;
this.custom8 = custom8;
this.custom8Like = custom8Like;
this.custom8NotIn = custom8NotIn;
this.custom9 = custom9;
this.custom9Like = custom9Like;
this.custom9NotIn = custom9NotIn;
this.custom10 = custom10;
this.custom10Like = custom10Like;
this.custom10NotIn = custom10NotIn;
this.custom11 = custom11;
this.custom11Like = custom11Like;
this.custom11NotIn = custom11NotIn;
this.custom12 = custom12;
this.custom12Like = custom12Like;
this.custom12NotIn = custom12NotIn;
this.custom13 = custom13;
this.custom13Like = custom13Like;
this.custom13NotIn = custom13NotIn;
this.custom14 = custom14;
this.custom14Like = custom14Like;
this.custom14NotIn = custom14NotIn;
this.custom15 = custom15;
this.custom15Like = custom15Like;
this.custom15NotIn = custom15NotIn;
this.custom16 = custom16;
this.custom16Like = custom16Like;
this.custom16NotIn = custom16NotIn;
}
@Override
public Void apply(WorkbasketPriorityReport.Builder builder) {
builder.withColumnHeaders(defaultColumnHeaders());
Optional.ofNullable(inWorkingDays)
.ifPresent(
bool -> {
if (bool) {
builder.inWorkingDays();
}
});
Optional.ofNullable(workbasketId).map(Arrays::asList).ifPresent(builder::workbasketIdIn);
Optional.ofNullable(state).map(Arrays::asList).ifPresent(builder::stateIn);
Optional.ofNullable(classificationCategory)
.map(Arrays::asList)
.ifPresent(builder::classificationCategoryIn);
Optional.ofNullable(domain).map(Arrays::asList).ifPresent(builder::domainIn);
Optional.ofNullable(classificationId)
.map(Arrays::asList)
.ifPresent(builder::classificationIdIn);
Optional.ofNullable(excludedClassificationId)
.map(Arrays::asList)
.ifPresent(builder::excludedClassificationIdIn);
Stream.of(
Pair.of(TaskCustomField.CUSTOM_1, custom1),
Pair.of(TaskCustomField.CUSTOM_2, custom2),
Pair.of(TaskCustomField.CUSTOM_3, custom3),
Pair.of(TaskCustomField.CUSTOM_4, custom4),
Pair.of(TaskCustomField.CUSTOM_5, custom5),
Pair.of(TaskCustomField.CUSTOM_6, custom6),
Pair.of(TaskCustomField.CUSTOM_7, custom7),
Pair.of(TaskCustomField.CUSTOM_8, custom8),
Pair.of(TaskCustomField.CUSTOM_9, custom9),
Pair.of(TaskCustomField.CUSTOM_10, custom10),
Pair.of(TaskCustomField.CUSTOM_11, custom11),
Pair.of(TaskCustomField.CUSTOM_12, custom12),
Pair.of(TaskCustomField.CUSTOM_13, custom13),
Pair.of(TaskCustomField.CUSTOM_14, custom14),
Pair.of(TaskCustomField.CUSTOM_15, custom15),
Pair.of(TaskCustomField.CUSTOM_16, custom16))
.forEach(
pair ->
Optional.ofNullable(pair.getRight())
.ifPresent(wrap(l -> builder.customAttributeIn(pair.getLeft(), l))));
Stream.of(
Pair.of(TaskCustomField.CUSTOM_1, custom1Like),
Pair.of(TaskCustomField.CUSTOM_2, custom2Like),
Pair.of(TaskCustomField.CUSTOM_3, custom3Like),
Pair.of(TaskCustomField.CUSTOM_4, custom4Like),
Pair.of(TaskCustomField.CUSTOM_5, custom5Like),
Pair.of(TaskCustomField.CUSTOM_6, custom6Like),
Pair.of(TaskCustomField.CUSTOM_7, custom7Like),
Pair.of(TaskCustomField.CUSTOM_8, custom8Like),
Pair.of(TaskCustomField.CUSTOM_9, custom9Like),
Pair.of(TaskCustomField.CUSTOM_10, custom10Like),
Pair.of(TaskCustomField.CUSTOM_11, custom11Like),
Pair.of(TaskCustomField.CUSTOM_12, custom12Like),
Pair.of(TaskCustomField.CUSTOM_13, custom13Like),
Pair.of(TaskCustomField.CUSTOM_14, custom14Like),
Pair.of(TaskCustomField.CUSTOM_15, custom15Like),
Pair.of(TaskCustomField.CUSTOM_16, custom16Like))
.forEach(
pair ->
Optional.ofNullable(pair.getRight())
.map(this::wrapElementsInLikeStatement)
.ifPresent(wrap(l -> builder.customAttributeLike(pair.getLeft(), l))));
Stream.of(
Pair.of(TaskCustomField.CUSTOM_1, custom1NotIn),
Pair.of(TaskCustomField.CUSTOM_2, custom2NotIn),
Pair.of(TaskCustomField.CUSTOM_3, custom3NotIn),
Pair.of(TaskCustomField.CUSTOM_4, custom4NotIn),
Pair.of(TaskCustomField.CUSTOM_5, custom5NotIn),
Pair.of(TaskCustomField.CUSTOM_6, custom6NotIn),
Pair.of(TaskCustomField.CUSTOM_7, custom7NotIn),
Pair.of(TaskCustomField.CUSTOM_8, custom8NotIn),
Pair.of(TaskCustomField.CUSTOM_9, custom9NotIn),
Pair.of(TaskCustomField.CUSTOM_10, custom10NotIn),
Pair.of(TaskCustomField.CUSTOM_11, custom11NotIn),
Pair.of(TaskCustomField.CUSTOM_12, custom12NotIn),
Pair.of(TaskCustomField.CUSTOM_13, custom13NotIn),
Pair.of(TaskCustomField.CUSTOM_14, custom14NotIn),
Pair.of(TaskCustomField.CUSTOM_15, custom15NotIn),
Pair.of(TaskCustomField.CUSTOM_16, custom16NotIn))
.forEach(
pair ->
Optional.ofNullable(pair.getRight())
.ifPresent(wrap(l -> builder.customAttributeNotIn(pair.getLeft(), l))));
return null;
}
private List<PriorityColumnHeader> defaultColumnHeaders() {
return Arrays.asList(
new PriorityColumnHeader(Integer.MIN_VALUE, 249),
new PriorityColumnHeader(250, 500),
new PriorityColumnHeader(501, Integer.MAX_VALUE));
}
}

View File

@ -41,8 +41,8 @@ class MonitorControllerIntTest {
void should_ReturnAllOpenTasksByState_When_QueryingForAWorkbasketAndReadyAndClaimedState() {
String url =
restHelper.toUrl(RestEndpoints.URL_MONITOR_TASK_STATUS_REPORT)
+ "?workbasket-ids=WBI:100000000000000000000000000000000007"
+ "&states=READY&states=CLAIMED";
+ "?workbasket-id=WBI:100000000000000000000000000000000007"
+ "&state=READY&state=CLAIMED";
HttpEntity<String> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("admin"));
ResponseEntity<ReportRepresentationModel> response =
@ -70,8 +70,8 @@ class MonitorControllerIntTest {
ResponseEntity<ReportRepresentationModel> response =
TEMPLATE.exchange(
url
+ "?workbasket-ids=WBI:100000000000000000000000000000000007"
+ "&states=READY&priority-minimum=1",
+ "?workbasket-id=WBI:100000000000000000000000000000000007"
+ "&state=READY&priority-minimum=1",
HttpMethod.GET,
auth,
ParameterizedTypeReference.forType(ReportRepresentationModel.class));
@ -156,6 +156,30 @@ class MonitorControllerIntTest {
assertThat(report.getSumRow()).extracting(RowRepresentationModel::getTotal).containsExactly(26);
}
@Test
void should_ApplyComplexFilterCombination_When_QueryingForAWorkbasketPriorityReport() {
String url =
restHelper.toUrl(RestEndpoints.URL_MONITOR_WORKBASKET_PRIORITY_REPORT)
+ "?workbasket-type=TOPIC&workbasket-type=GROUP"
+ "&state=READY&state=CLAIMED"
+ "&custom-6=074&custom-6=075"
+ "&custom-7-not-in=20";
HttpEntity<?> auth = new HttpEntity<>(RestHelper.generateHeadersForUser("monitor"));
ResponseEntity<ReportRepresentationModel> response =
TEMPLATE.exchange(
url,
HttpMethod.GET,
auth,
ParameterizedTypeReference.forType(ReportRepresentationModel.class));
ReportRepresentationModel report = response.getBody();
assertThat(report).isNotNull();
assertThat(report.getSumRow())
.extracting(RowRepresentationModel::getCells)
.containsExactly(new int[] {2, 0, 1});
}
@Test
void should_DetectPriorityColumnHeader_When_HeaderIsPassedAsQueryParameter() throws Exception {
PriorityColumnHeaderRepresentationModel columnHeader =

View File

@ -16,7 +16,7 @@ class MonitorControllerRestDocTest extends BaseRestDocTest {
.perform(
get(
RestEndpoints.URL_MONITOR_WORKBASKET_REPORT
+ "?states=READY&states=CLAIMED&states=COMPLETED"))
+ "?state=READY&state=CLAIMED&state=COMPLETED"))
.andExpect(MockMvcResultMatchers.status().isOk());
}
@ -62,7 +62,7 @@ class MonitorControllerRestDocTest extends BaseRestDocTest {
@Test
void computeTaskStatusReportDocTest() throws Exception {
mockMvc
.perform(get(RestEndpoints.URL_MONITOR_TASK_STATUS_REPORT))
.perform(get(RestEndpoints.URL_MONITOR_TASK_STATUS_REPORT + "?state=READY"))
.andExpect(MockMvcResultMatchers.status().isOk());
}