diff --git a/CHANGELOG.md b/CHANGELOG.md index cf40d341..45064a26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [x.x.x] - unreleased +### Added +- Added support for PATCH /reports/{reportId}/definition endpoint, Update Report Definition ## [3.10.0] - 2025-12-04 ### Added diff --git a/src/main/java/com/smartsheet/api/ReportResources.java b/src/main/java/com/smartsheet/api/ReportResources.java index 973ed703..707976b3 100644 --- a/src/main/java/com/smartsheet/api/ReportResources.java +++ b/src/main/java/com/smartsheet/api/ReportResources.java @@ -19,6 +19,7 @@ import com.smartsheet.api.models.PagedResult; import com.smartsheet.api.models.PaginationParameters; import com.smartsheet.api.models.Report; +import com.smartsheet.api.models.ReportDefinition; import com.smartsheet.api.models.ReportPublish; import com.smartsheet.api.models.SheetEmail; import com.smartsheet.api.models.enums.ReportInclusion; @@ -212,6 +213,29 @@ Report getReport( */ ReportPublish updatePublishStatus(long id, ReportPublish reportPublish) throws SmartsheetException; + /** + *

Updates a report's definition (filters, grouping, summarize, and sorting).

+ * + *

It mirrors to the following Smartsheet REST API method: PUT /reports/{id}/definition

+ * + *

This endpoint supports partial updates only on root level properties of the report definition, + * such as {@code filters}, {@code groupingCriteria}, and {@code summarizingCriteria}. For example, + * you can update the report's filters without affecting its grouping criteria. However, nested + * properties within these objects, such as a specific filter or grouping criterion, cannot be + * updated individually and require a full replacement of the respective section. + *

+ * + * @param id the ID of the report + * @param definition the ReportDefinition object containing the updated definition + * @throws IllegalArgumentException if any argument is null + * @throws InvalidRequestException if there is any problem with the REST API request + * @throws AuthorizationException if there is any problem with the REST API authorization (access token) + * @throws ResourceNotFoundException if the resource cannot be found + * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting) + * @throws SmartsheetException if there is any other error during the operation + */ + void updateReportDefinition(long id, ReportDefinition definition) throws SmartsheetException; + /** *

Creates an object of ShareResources.

* diff --git a/src/main/java/com/smartsheet/api/internal/AbstractResources.java b/src/main/java/com/smartsheet/api/internal/AbstractResources.java index a884fcf7..0afc4f47 100644 --- a/src/main/java/com/smartsheet/api/internal/AbstractResources.java +++ b/src/main/java/com/smartsheet/api/internal/AbstractResources.java @@ -756,6 +756,58 @@ protected List postAndReceiveList(String path, T objectToPost, Class + * Exceptions: + * IllegalArgumentException : if any argument is null, or path is empty string + * InvalidRequestException : if there is any problem with the REST API request + * AuthorizationException : if there is any problem with the REST API authorization(access token) + * ResourceNotFoundException : if the resource can not be found + * ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting) + * SmartsheetRestException : if there is any other REST API related error occurred during the operation + * SmartsheetException : if there is any other error occurred during the operation + * + * @param the generic type + * @param path the relative path of the resource + * @param objectClass the resource object class + * @param object the object to patch + * @return the updated resource + * @throws SmartsheetException the smartsheet exception + */ + protected T putResource(String path, Class objectClass, Object object) throws SmartsheetException { + Util.throwIfNull(path, object); + Util.throwIfEmpty(path); + + HttpRequest request; + request = createHttpRequest(smartsheet.getBaseURI().resolve(path), HttpMethod.PUT); + + ByteArrayOutputStream objectBytesStream = new ByteArrayOutputStream(); + this.smartsheet.getJsonSerializer().serialize(object, objectBytesStream); + HttpEntity entity = new HttpEntity(); + entity.setContentType(JSON_CONTENT_TYPE); + entity.setContent(new ByteArrayInputStream(objectBytesStream.toByteArray())); + entity.setContentLength(objectBytesStream.size()); + request.setEntity(entity); + + T obj = null; + try { + HttpResponse response = this.smartsheet.getHttpClient().request(request); + if (response.getStatusCode() == 200) { + obj = this.smartsheet.getJsonSerializer().deserialize(objectClass, + response.getEntity().getContent()); + } else { + handleError(response); + } + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + smartsheet.getHttpClient().releaseConnection(); + } + + return obj; + } + /** * Partially update a resource using Smartsheet REST API with PATCH method. *

diff --git a/src/main/java/com/smartsheet/api/internal/ReportResourcesImpl.java b/src/main/java/com/smartsheet/api/internal/ReportResourcesImpl.java index 1951411c..7938bd77 100644 --- a/src/main/java/com/smartsheet/api/internal/ReportResourcesImpl.java +++ b/src/main/java/com/smartsheet/api/internal/ReportResourcesImpl.java @@ -27,7 +27,9 @@ import com.smartsheet.api.models.PagedResult; import com.smartsheet.api.models.PaginationParameters; import com.smartsheet.api.models.Report; +import com.smartsheet.api.models.ReportDefinition; import com.smartsheet.api.models.ReportPublish; +import com.smartsheet.api.models.Result; import com.smartsheet.api.models.SheetEmail; import com.smartsheet.api.models.enums.ReportInclusion; @@ -53,6 +55,7 @@ public class ReportResourcesImpl extends AbstractResources implements ReportReso */ private ShareResources shares; + private static final String QUERY_PARAM_UPDATE_FILTERS = "updateFilters"; private static final String REPORTS_PATH = "reports/"; /** @@ -305,6 +308,39 @@ public ReportPublish updatePublishStatus(long id, ReportPublish reportPublish) t return this.updateResource(REPORTS_PATH + id + "/publish", ReportPublish.class, reportPublish); } + /** + * Updates a report's definition (filters, grouping, summarizing, and sorting). + *

+ * It mirrors to the following Smartsheet REST API method: PUT /reports/{id}/definition + *

+ * This endpoint supports partial updates only on root level properties of the report definition, + * such as filters, groupingCriteria, and summarizingCriteria. For example, you can update the + * report's filters without affecting its grouping criteria. However, nested properties within + * these objects, such as a specific filter or grouping criterion, cannot be updated individually + * and require a full replacement of the respective section. + *

+ * Exceptions: + * - InvalidRequestException : if there is any problem with the REST API request + * - AuthorizationException : if there is any problem with the REST API authorization(access token) + * - ResourceNotFoundException : if the resource can not be found + * - ServiceUnavailableException : if the REST API service is not available (possibly due to rate limiting) + * - SmartsheetRestException : if there is any other REST API related error occurred during the operation + * - SmartsheetException : if there is any other error occurred during the operation + * + * @param id the ID of the report + * @param definition the ReportDefinition object containing the updated definition + * @throws IllegalArgumentException if any argument is null + * @throws InvalidRequestException if there is any problem with the REST API request + * @throws AuthorizationException if there is any problem with the REST API authorization (access token) + * @throws ResourceNotFoundException if the resource cannot be found + * @throws ServiceUnavailableException if the REST API service is not available (possibly due to rate limiting) + * @throws SmartsheetException if there is any other error during the operation + */ + public void updateReportDefinition(long id, ReportDefinition definition) throws SmartsheetException { + String path = REPORTS_PATH + id + "/definition"; + this.putResource(path, Result.class, definition); + } + /** *

Creates an object of ShareResources.

* diff --git a/src/main/java/com/smartsheet/api/models/ReportColumnIdentifier.java b/src/main/java/com/smartsheet/api/models/ReportColumnIdentifier.java new file mode 100644 index 00000000..7cda2b62 --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/ReportColumnIdentifier.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models; + +import com.smartsheet.api.models.enums.ColumnType; +import com.smartsheet.api.models.enums.ReportSystemColumnType; + +/** + * Object used to match a sheet column for a report. + *

+ * One of [{@code type}, {@code systemColumnType}] or [{@code primary=true}] is required. + *

+ * {@code systemColumnType} should be specified if you want to match a system column. Use {@code primary=true} + * to match primary columns. When matching primary columns, {@code title} can be used to customize the primary + * column name in the rendered report. + *

+ * Note: Columns in the report are matched by the combination of {@code title} and {@code type} + * (and {@code systemColumnType} if specified). + *

+ * Note: {@code symbol} is not used for matching and as a result {@code CHECKBOX} or {@code PICKLIST} + * columns with different symbols (from different sheets) can be combined into the same column in the report. + * You cannot combine {@code CHECKBOX} with {@code PICKLIST} into the same column in the report because they + * are different types. + */ +public class ReportColumnIdentifier { + + /** + * Column title to be matched from the source sheets. + *

+ * Note: If {@code primary} is true, then this property can be used to customize the primary column title. + */ + private String title; + + /** + * Column type to be matched from the source sheets. + */ + private ColumnType type; + + /** + * System column type to be matched from the source sheets. + */ + private ReportSystemColumnType systemColumnType; + + /** + * Indicates if the matched column is primary (default: false). + */ + private Boolean primary; + + /** + * Gets the column title. + * + * @return the title + */ + public String getTitle() { + return title; + } + + /** + * Sets the column title. + *

+ * If primary is true, this can be used to customize the primary column title in the report. + * + * @param title the title + */ + public ReportColumnIdentifier setTitle(String title) { + this.title = title; + return this; + } + + /** + * Gets the column type. + * + * @return the type + */ + public ColumnType getType() { + return type; + } + + /** + * Sets the column type. + * + * @param type the type + */ + public ReportColumnIdentifier setType(ColumnType type) { + this.type = type; + return this; + } + + /** + * Gets the system column type. + * + * @return the system column type + */ + public ReportSystemColumnType getSystemColumnType() { + return systemColumnType; + } + + /** + * Sets the system column type. + * + * @param systemColumnType the system column type + */ + public ReportColumnIdentifier setSystemColumnType(ReportSystemColumnType systemColumnType) { + this.systemColumnType = systemColumnType; + return this; + } + + /** + * Gets whether this identifies the primary column. + * + * @return true if this is the primary column, false otherwise + */ + public Boolean getPrimary() { + return primary; + } + + /** + * Sets whether this identifies the primary column. + * + * @param primary true if this is the primary column, false otherwise + */ + public ReportColumnIdentifier setPrimary(Boolean primary) { + this.primary = primary; + return this; + } +} diff --git a/src/main/java/com/smartsheet/api/models/ReportDefinition.java b/src/main/java/com/smartsheet/api/models/ReportDefinition.java new file mode 100644 index 00000000..43344b1b --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/ReportDefinition.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models; + +import java.util.List; + +/** + * The report definition contains filters, grouping and sorting properties of the report. + *

+ * Note: When groupingCriteria is defined the primary column of the report will move to the + * index 0 when it is first rendered by the app. + */ +public class ReportDefinition { + + /** + * Represents the filter expression for the report. + */ + private ReportFilterExpression filters; + + /** + * Represents the list of report grouping criteria. + */ + private List groupingCriteria; + + /** + * Represents the list of report summarizing criteria. + */ + private List summarizingCriteria; + + /** + * Represents the list of report sorting criteria. + */ + private List sortingCriteria; + + /** + * Gets the filter expression. + * + * @return the filters + */ + public ReportFilterExpression getFilters() { + return filters; + } + + /** + * Sets the filter expression. + * + * @param filters the filter expression + */ + public ReportDefinition setFilters(ReportFilterExpression filters) { + this.filters = filters; + return this; + } + + /** + * Gets the list of report grouping criteria. + * + * @return the grouping criteria + */ + public List getGroupingCriteria() { + return groupingCriteria; + } + + /** + * Sets the list of report grouping criteria. + * + * @param groupingCriteria the grouping criteria + */ + public ReportDefinition setGroupingCriteria(List groupingCriteria) { + this.groupingCriteria = groupingCriteria; + return this; + } + + /** + * Gets the list of report summarizing criteria. + * + * @return the summarizing criteria + */ + public List getSummarizingCriteria() { + return summarizingCriteria; + } + + /** + * Sets the list of report summarizing criteria. + * + * @param summarizingCriteria the summarizing criteria + */ + public ReportDefinition setSummarizingCriteria(List summarizingCriteria) { + this.summarizingCriteria = summarizingCriteria; + return this; + } + + /** + * Gets the list of report sorting criteria. + * + * @return the sorting criteria + */ + public List getSortingCriteria() { + return sortingCriteria; + } + + /** + * Sets the list of report sorting criteria. + * + * @param sortingCriteria the sorting criteria + */ + public ReportDefinition setSortingCriteria(List sortingCriteria) { + this.sortingCriteria = sortingCriteria; + return this; + } +} diff --git a/src/main/java/com/smartsheet/api/models/ReportFilterCriterion.java b/src/main/java/com/smartsheet/api/models/ReportFilterCriterion.java new file mode 100644 index 00000000..864b73d9 --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/ReportFilterCriterion.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models; + +import com.smartsheet.api.models.enums.ReportFilterOperator; + +import java.util.List; + +/** + * Represents a single filter criterion. + */ +public class ReportFilterCriterion { + + /** + * The column to filter on. + */ + private ReportColumnIdentifier column; + + /** + * The condition operator. + */ + private ReportFilterOperator operator; + + /** + * List of filter values. + */ + private List values; + + /** + * Gets the column identifier. + * + * @return the column + */ + public ReportColumnIdentifier getColumn() { + return column; + } + + /** + * Sets the column identifier. + * + * @param column the column + */ + public ReportFilterCriterion setColumn(ReportColumnIdentifier column) { + this.column = column; + return this; + } + + /** + * Gets the condition operator. + * + * @return the operator + */ + public ReportFilterOperator getOperator() { + return operator; + } + + /** + * Sets the condition operator. + * + * @param operator the operator + */ + public ReportFilterCriterion setOperator(ReportFilterOperator operator) { + this.operator = operator; + return this; + } + + /** + * Gets the filter values. + * + * @return the values + */ + public List getValues() { + return values; + } + + /** + * Sets the filter values. + * + * @param values the values + */ + public ReportFilterCriterion setValues(List values) { + this.values = values; + return this; + } +} diff --git a/src/main/java/com/smartsheet/api/models/ReportFilterExpression.java b/src/main/java/com/smartsheet/api/models/ReportFilterExpression.java new file mode 100644 index 00000000..9d38673e --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/ReportFilterExpression.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models; + +import com.smartsheet.api.models.enums.ReportFilterExpressionOperator; + +import java.util.List; + +/** + * Report filter expression. It is a recursive object that allows at most 3 levels. + *

+ * At least one of {@code criteria} or {@code nestedCriteria} has to be provided in addition to {@code operator}. + *

+ * Example: A filter that matches rows where + * (Price greater than 11 AND Primary CONTAINS "PROJ-1") OR (Quantity less than 12 AND "Sold Out" IS_CHECKED) + */ +public class ReportFilterExpression { + + /** + * The boolean operator that will be applied to the list of criteria and nestedCriteria. + */ + private ReportFilterExpressionOperator operator; + + /** + * A recursive list of report filter expressions. Each item will be joined to the filter + * expression with the AND/OR operator defined on this level. + */ + private List nestedCriteria; + + /** + * Criteria objects specifying custom criteria against which to match cell values. Each item + * will be joined to the filter expression with the AND/OR operator defined on this level. + */ + private List criteria; + + /** + * Gets the boolean operator. + * + * @return the operator + */ + public ReportFilterExpressionOperator getOperator() { + return operator; + } + + /** + * Sets the boolean operator. + * + * @param operator the operator + */ + public ReportFilterExpression setOperator(ReportFilterExpressionOperator operator) { + this.operator = operator; + return this; + } + + /** + * Gets the nested criteria list. + * + * @return the nested criteria + */ + public List getNestedCriteria() { + return nestedCriteria; + } + + /** + * Sets the nested criteria list. + * + * @param nestedCriteria the nested criteria + */ + public ReportFilterExpression setNestedCriteria(List nestedCriteria) { + this.nestedCriteria = nestedCriteria; + return this; + } + + /** + * Gets the criteria list. + * + * @return the criteria + */ + public List getCriteria() { + return criteria; + } + + /** + * Sets the criteria list. + * + * @param criteria the criteria + */ + public ReportFilterExpression setCriteria(List criteria) { + this.criteria = criteria; + return this; + } +} diff --git a/src/main/java/com/smartsheet/api/models/ReportGroupingCriterion.java b/src/main/java/com/smartsheet/api/models/ReportGroupingCriterion.java new file mode 100644 index 00000000..dcb88e48 --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/ReportGroupingCriterion.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models; + +import com.smartsheet.api.models.enums.SortDirection; + +/** + * Represents a grouping criterion for a report. + */ +public class ReportGroupingCriterion { + + /** + * The column to group by. + */ + private ReportColumnIdentifier column; + + /** + * Sorting direction within the group. + */ + private SortDirection sortingDirection; + + /** + * Indicates whether the group is expanded in the UI (default: true). + */ + private Boolean isExpanded; + + /** + * Gets the column to group by. + * + * @return the column + */ + public ReportColumnIdentifier getColumn() { + return column; + } + + /** + * Sets the column to group by. + * + * @param column the column + */ + public ReportGroupingCriterion setColumn(ReportColumnIdentifier column) { + this.column = column; + return this; + } + + /** + * Gets the sorting direction within the group. + * + * @return the sorting direction + */ + public SortDirection getSortingDirection() { + return sortingDirection; + } + + /** + * Sets the sorting direction within the group. + * + * @param sortingDirection the sorting direction + */ + public ReportGroupingCriterion setSortingDirection(SortDirection sortingDirection) { + this.sortingDirection = sortingDirection; + return this; + } + + /** + * Gets whether the group is expanded in the UI. + * + * @return true if expanded, false otherwise + */ + public Boolean getIsExpanded() { + return isExpanded; + } + + /** + * Sets whether the group is expanded in the UI. + * + * @param isExpanded true if expanded, false otherwise + */ + public ReportGroupingCriterion setIsExpanded(Boolean isExpanded) { + this.isExpanded = isExpanded; + return this; + } +} diff --git a/src/main/java/com/smartsheet/api/models/ReportSortingCriterion.java b/src/main/java/com/smartsheet/api/models/ReportSortingCriterion.java new file mode 100644 index 00000000..e13041be --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/ReportSortingCriterion.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models; + +import com.smartsheet.api.models.enums.SortDirection; + +/** + * Represents a sorting criterion for a report. + */ +public class ReportSortingCriterion { + + /** + * The column to sort by. + */ + private ReportColumnIdentifier column; + + /** + * Sorting direction. + */ + private SortDirection sortingDirection; + + /** + * Gets the column to sort by. + * + * @return the column + */ + public ReportColumnIdentifier getColumn() { + return column; + } + + /** + * Sets the column to sort by. + * + * @param column the column + */ + public ReportSortingCriterion setColumn(ReportColumnIdentifier column) { + this.column = column; + return this; + } + + /** + * Gets the sorting direction. + * + * @return the sorting direction + */ + public SortDirection getSortingDirection() { + return sortingDirection; + } + + /** + * Sets the sorting direction. + * + * @param sortingDirection the sorting direction + */ + public ReportSortingCriterion setSortingDirection(SortDirection sortingDirection) { + this.sortingDirection = sortingDirection; + return this; + } +} diff --git a/src/main/java/com/smartsheet/api/models/ReportSummarizingCriterion.java b/src/main/java/com/smartsheet/api/models/ReportSummarizingCriterion.java new file mode 100644 index 00000000..35f921ab --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/ReportSummarizingCriterion.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models; + +import com.smartsheet.api.models.enums.ReportAggregationType; + +/** + * Represents an summarizing criterion for a report. + */ +public class ReportSummarizingCriterion { + + /** + * The column to summarize. + */ + private ReportColumnIdentifier column; + + /** + * Type of aggregation. + */ + private ReportAggregationType aggregationType; + + /** + * Indicates whether the group is expanded in the UI (default: true). + */ + private Boolean isExpanded; + + /** + * Gets the column to summarize. + * + * @return the column + */ + public ReportColumnIdentifier getColumn() { + return column; + } + + /** + * Sets the column to summarize. + * + * @param column the column + */ + public ReportSummarizingCriterion setColumn(ReportColumnIdentifier column) { + this.column = column; + return this; + } + + /** + * Gets the type of aggregation. + * + * @return the aggregation type + */ + public ReportAggregationType getAggregationType() { + return aggregationType; + } + + /** + * Sets the type of aggregation. + * + * @param aggregationType the aggregation type + */ + public ReportSummarizingCriterion setAggregationType(ReportAggregationType aggregationType) { + this.aggregationType = aggregationType; + return this; + } + + /** + * Gets whether the group is expanded in the UI. + * + * @return true if expanded, false otherwise + */ + public Boolean getIsExpanded() { + return isExpanded; + } + + /** + * Sets whether the group is expanded in the UI. + * + * @param isExpanded true if expanded, false otherwise + */ + public ReportSummarizingCriterion setIsExpanded(Boolean isExpanded) { + this.isExpanded = isExpanded; + return this; + } +} diff --git a/src/main/java/com/smartsheet/api/models/enums/ReportAggregationType.java b/src/main/java/com/smartsheet/api/models/enums/ReportAggregationType.java new file mode 100644 index 00000000..7598fe63 --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/enums/ReportAggregationType.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models.enums; + +/** + * Represents the type of aggregation that can be applied to report data. + */ +public enum ReportAggregationType { + SUM, + AVG, + MIN, + MAX, + COUNT, + FIRST, + LAST +} diff --git a/src/main/java/com/smartsheet/api/models/enums/ReportFilterExpressionOperator.java b/src/main/java/com/smartsheet/api/models/enums/ReportFilterExpressionOperator.java new file mode 100644 index 00000000..776811b9 --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/enums/ReportFilterExpressionOperator.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models.enums; + +/** + * Represents the boolean operator for combining filter criteria. + */ +public enum ReportFilterExpressionOperator { + AND, + OR +} diff --git a/src/main/java/com/smartsheet/api/models/enums/ReportFilterOperator.java b/src/main/java/com/smartsheet/api/models/enums/ReportFilterOperator.java new file mode 100644 index 00000000..a5fc80da --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/enums/ReportFilterOperator.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models.enums; + +/** + * Represents the condition operator for report filter criteria. + */ +public enum ReportFilterOperator { + EQUAL, + NOT_EQUAL, + GREATER_THAN, + LESS_THAN, + CONTAINS, + BETWEEN, + TODAY, + PAST, + FUTURE, + LAST_N_DAYS, + NEXT_N_DAYS, + IS_BLANK, + IS_NOT_BLANK, + IS_NUMBER, + IS_NOT_NUMBER, + IS_DATE, + IS_NOT_DATE, + IS_CHECKED, + IS_UNCHECKED, + IS_ONE_OF, + IS_NOT_ONE_OF, + LESS_THAN_OR_EQUAL, + GREATER_THAN_OR_EQUAL, + DOES_NOT_CONTAIN, + NOT_BETWEEN, + NOT_TODAY, + NOT_PAST, + NOT_FUTURE, + NOT_LAST_N_DAYS, + NOT_NEXT_N_DAYS, + HAS_ANY_OF, + HAS_NONE_OF, + HAS_ALL_OF, + NOT_ALL_OF, + MULTI_IS_EQUAL, + MULTI_IS_NOT_EQUAL +} diff --git a/src/main/java/com/smartsheet/api/models/enums/ReportSystemColumnType.java b/src/main/java/com/smartsheet/api/models/enums/ReportSystemColumnType.java new file mode 100644 index 00000000..834b3a7c --- /dev/null +++ b/src/main/java/com/smartsheet/api/models/enums/ReportSystemColumnType.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.models.enums; + +/** + * Represents the system column types. + * + * @see Column Types Help + */ +public enum ReportSystemColumnType { + + /** + * Represents the MODIFIED_DATE system column type. + */ + MODIFIED_DATE, + + /** + * Represents the MODIFIED_BY system column type. + */ + MODIFIED_BY, + + /** + * Represents the CREATED_DATE system column type. + */ + CREATED_DATE, + + /** + * Represents the CREATED_BY system column type. + */ + CREATED_BY, + + /** + * Represents the SHEET_NAME system column type (available for reports only). + */ + SHEET_NAME, +} diff --git a/src/test/java/com/smartsheet/api/sdktest/reports/TestUpdateReportDefinition.java b/src/test/java/com/smartsheet/api/sdktest/reports/TestUpdateReportDefinition.java new file mode 100644 index 00000000..02e3ee26 --- /dev/null +++ b/src/test/java/com/smartsheet/api/sdktest/reports/TestUpdateReportDefinition.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2025 Smartsheet + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.smartsheet.api.sdktest.reports; + +import com.github.tomakehurst.wiremock.http.RequestMethod; +import com.github.tomakehurst.wiremock.verification.LoggedRequest; +import com.smartsheet.api.Smartsheet; +import com.smartsheet.api.SmartsheetException; +import com.smartsheet.api.WiremockClient; +import com.smartsheet.api.WiremockClientWrapper; +import com.smartsheet.api.models.ReportColumnIdentifier; +import com.smartsheet.api.models.ReportDefinition; +import com.smartsheet.api.models.ReportFilterCriterion; +import com.smartsheet.api.models.ReportFilterExpression; +import com.smartsheet.api.models.enums.ColumnType; +import com.smartsheet.api.models.enums.ReportFilterExpressionOperator; +import com.smartsheet.api.models.enums.ReportFilterOperator; +import com.smartsheet.api.sdktest.users.Utils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.URI; +import java.util.ArrayList; +import java.util.UUID; + +import static com.smartsheet.api.sdktest.users.CommonTestConstants.TEST_REPORT_ID; +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatNoException; + +public class TestUpdateReportDefinition { + + private ReportDefinition testReportDefinition; + private String testReportDefinitionJson; + + @BeforeEach + void setUp() { + testReportDefinition = new ReportDefinition(); + testReportDefinition.setFilters( + new ReportFilterExpression() + .setOperator(ReportFilterExpressionOperator.AND) + .setCriteria(new ArrayList<>() {{ + add( + new ReportFilterCriterion() + .setOperator(ReportFilterOperator.EQUAL) + .setColumn( + new ReportColumnIdentifier() + .setPrimary(true) + .setTitle("Primary") + .setType(ColumnType.TEXT_NUMBER) + ) + ); + }}) + ); + + testReportDefinitionJson = "{\"filters\":" + + "{\"operator\":\"AND\"," + + "\"criteria\":[{\"column\":" + + "{\"title\":\"Primary\",\"type\":\"TEXT_NUMBER\",\"primary\":true}," + + "\"operator\":\"EQUAL\"}]}}"; + } + + @Test + void testUpdateReportDefinitionGeneratedUrlIsCorrect() throws SmartsheetException { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient( + "/reports/update-report-definition/all-response-body-properties", + requestId + ); + Smartsheet smartsheet = wrapper.getSmartsheet(); + WiremockClient wiremockClient = wrapper.getWiremockClient(); + + smartsheet.reportResources().updateReportDefinition(TEST_REPORT_ID, testReportDefinition); + LoggedRequest wiremockRequest = wiremockClient.findWiremockRequest(requestId); + String path = URI.create(wiremockRequest.getUrl()).getPath(); + + assertThat(path).isEqualTo("/2.0/reports/" + TEST_REPORT_ID + "/definition"); + assertThat(wiremockRequest.getMethod()).isEqualTo(RequestMethod.PUT); + + String requestBody = wiremockRequest.getBodyAsString(); + assertThat(requestBody).isEqualTo(testReportDefinitionJson); + } + + @Test + void testUpdateReportDefinitionAllResponseBodyProperties() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient( + "/reports/update-report-definition/all-response-body-properties", + requestId + ); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + assertThatNoException().isThrownBy(() -> smartsheet.reportResources().updateReportDefinition(TEST_REPORT_ID, testReportDefinition)); + } + + @Test + void testUpdateReportDefinitionInvalidArgument() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient( + "/reports/update-report-definition/all-response-body-properties", + requestId + ); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + Assertions.assertThrows(IllegalArgumentException.class, () -> { + smartsheet.reportResources().updateReportDefinition(TEST_REPORT_ID, null); + }); + } + + @Test + void testUpdateReportDefinitionError500Response() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient("/errors/500-response", requestId); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + SmartsheetException exception = Assertions.assertThrows(SmartsheetException.class, () -> { + smartsheet.reportResources().updateReportDefinition(TEST_REPORT_ID, testReportDefinition); + }); + + assertThat(exception.getMessage()).isEqualTo("Internal Server Error"); + } + + @Test + void testUpdateReportDefinitionError400Response() { + String requestId = UUID.randomUUID().toString(); + WiremockClientWrapper wrapper = Utils.createWiremockSmartsheetClient("/errors/400-response", requestId); + Smartsheet smartsheet = wrapper.getSmartsheet(); + + SmartsheetException exception = Assertions.assertThrows(SmartsheetException.class, () -> { + smartsheet.reportResources().updateReportDefinition(TEST_REPORT_ID, testReportDefinition); + }); + + assertThat(exception.getMessage()).isEqualTo("Malformed Request"); + } +} diff --git a/src/test/java/com/smartsheet/api/sdktest/users/CommonTestConstants.java b/src/test/java/com/smartsheet/api/sdktest/users/CommonTestConstants.java index 400d31b6..c889cb9b 100644 --- a/src/test/java/com/smartsheet/api/sdktest/users/CommonTestConstants.java +++ b/src/test/java/com/smartsheet/api/sdktest/users/CommonTestConstants.java @@ -19,4 +19,7 @@ public class CommonTestConstants { public static final long TEST_USER_ID = 1234567890L; public static final long TEST_PLAN_ID = 1234567890123456L; + public static final long TEST_SHEET_ID = 9876543210L; + public static final long TEST_WORKSPACE_ID = 1122334455L; + public static final long TEST_REPORT_ID = 2233445566L; }