diff --git a/src/main/java/org/gridsuite/studyconfig/server/controller/ComputationResultFiltersController.java b/src/main/java/org/gridsuite/studyconfig/server/controller/ComputationResultFiltersController.java new file mode 100644 index 00000000..45cbf155 --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/controller/ComputationResultFiltersController.java @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.gridsuite.studyconfig.server.StudyConfigApi; +import org.gridsuite.studyconfig.server.dto.*; +import org.gridsuite.studyconfig.server.dto.ComputationResultColumnFilterInfos; +import org.gridsuite.studyconfig.server.service.ComputationResultFiltersService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.UUID; + +/** + * @author Rehili Ghazwa + */ +@RestController +@RequestMapping(value = "/" + StudyConfigApi.API_VERSION + "/computation-result-filters") +@RequiredArgsConstructor +public class ComputationResultFiltersController { + private final ComputationResultFiltersService computationGlobalFiltersService; + + @PostMapping(value = "/default") + @Operation(summary = "Create a default computation result filters", + description = "Creates a default computation result filters") + @ApiResponse(responseCode = "201", description = "Default computation result filters created", + content = @Content(schema = @Schema(implementation = UUID.class))) + public ResponseEntity createDefaultComputationResultFilters() { + UUID id = computationGlobalFiltersService.createDefaultComputingResultFilters(); + return ResponseEntity.status(HttpStatus.CREATED).body(id); + } + + @GetMapping("/{computationResultFiltersId}/{computationType}") + @Operation(summary = "Get a computation result global filters", + description = "Fetches the computation result global filters for a given computation type") + @ApiResponse(responseCode = "200", description = "Computation result global filters found", + content = @Content(schema = @Schema(implementation = GlobalFilterInfos.class))) + @ApiResponse(responseCode = "404", description = "Computation result global filters not found") + public ResponseEntity> getComputingResultGlobalFilters( + @Parameter(description = "Computation result filters Id") @PathVariable UUID computationResultFiltersId, + @Parameter(description = "Computation type") @PathVariable String computationType) { + return ResponseEntity.ok(computationGlobalFiltersService.getComputingResultGlobalFilters(computationResultFiltersId, computationType)); + } + + @GetMapping("/{computationResultFiltersId}/{computationType}/{computationSubType}") + @Operation(summary = "Get a computation result column filters", + description = "Fetches the computation result column filters for a given computation type and subtype") + @ApiResponse(responseCode = "200", description = "Computation result column filters found", + content = @Content(schema = @Schema(implementation = ComputationResultColumnFilterInfos.class))) + @ApiResponse(responseCode = "404", description = "Computation result column filters not found") + public ResponseEntity> getComputingResultColumnFilters( + @Parameter(description = "Computation result filters Id") @PathVariable UUID computationResultFiltersId, + @Parameter(description = "Computation type") @PathVariable String computationType, + @Parameter(description = "Computation subtype") @PathVariable String computationSubType) { + return ResponseEntity.ok(computationGlobalFiltersService.getComputingResultColumnFilters(computationResultFiltersId, computationType, computationSubType)); + } + + @PostMapping("/{computationResultFiltersId}/{computationType}/global-filters") + @Operation(summary = "Set global filters", + description = "Replaces all existing global filters with the provided list for a computation result") + @ApiResponse(responseCode = "204", description = "Global filters set successfully") + @ApiResponse(responseCode = "404", description = "Computation result filters not found") + public ResponseEntity setGlobalFiltersForComputingResult( + @PathVariable UUID computationResultFiltersId, + @PathVariable String computationType, + @Valid @RequestBody List filters) { + computationGlobalFiltersService.setGlobalFiltersForComputationResult(computationResultFiltersId, computationType, filters); + return ResponseEntity.noContent().build(); + } + + @PutMapping("/{computationResultFiltersId}/{computationType}/{computationSubType}/columns") + @Operation(summary = "Update a column", description = "Updates an existing column") + @ApiResponse(responseCode = "204", description = "Column updated") + public ResponseEntity updateColumn( + @PathVariable UUID computationResultFiltersId, + @PathVariable String computationType, + @PathVariable String computationSubType, + @Valid @RequestBody ComputationResultColumnFilterInfos dto) { + computationGlobalFiltersService.updateColumn(computationResultFiltersId, computationType, computationSubType, dto); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/controller/SpreadsheetConfigController.java b/src/main/java/org/gridsuite/studyconfig/server/controller/SpreadsheetConfigController.java index 6f316706..faff2903 100644 --- a/src/main/java/org/gridsuite/studyconfig/server/controller/SpreadsheetConfigController.java +++ b/src/main/java/org/gridsuite/studyconfig/server/controller/SpreadsheetConfigController.java @@ -140,7 +140,7 @@ public ResponseEntity deleteSpreadsheetConfig( @Operation(summary = "Get a column", description = "Retrieves a column by its ID") @ApiResponse(responseCode = "200", description = "Column found") @ApiResponse(responseCode = "404", description = "Column not found") - public ResponseEntity getColumn( + public ResponseEntity getColumn( @Parameter(description = "ID of the spreadsheet config") @PathVariable UUID id, @Parameter(description = "ID of the column to retrieve") @PathVariable UUID columnId) { return ResponseEntity.ok(spreadsheetConfigService.getColumn(id, columnId)); @@ -151,7 +151,7 @@ public ResponseEntity getColumn( @ApiResponse(responseCode = "201", description = "Column created") public ResponseEntity createColumn( @Parameter(description = "ID of the spreadsheet config") @PathVariable UUID id, - @Valid @RequestBody ColumnInfos dto) { + @Valid @RequestBody SpreadsheetColumnInfos dto) { UUID columnId = spreadsheetConfigService.createColumn(id, dto); return ResponseEntity.status(HttpStatus.CREATED).body(columnId); } @@ -162,7 +162,7 @@ public ResponseEntity createColumn( public ResponseEntity updateColumn( @Parameter(description = "ID of the spreadsheet config") @PathVariable UUID id, @Parameter(description = "ID of the column to update") @PathVariable UUID columnId, - @Valid @RequestBody ColumnInfos dto) { + @Valid @RequestBody SpreadsheetColumnInfos dto) { spreadsheetConfigService.updateColumn(id, columnId, dto); return ResponseEntity.noContent().build(); } diff --git a/src/main/java/org/gridsuite/studyconfig/server/dto/ColumnFilterInfos.java b/src/main/java/org/gridsuite/studyconfig/server/dto/ColumnFilterInfos.java new file mode 100644 index 00000000..2ecb4884 --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/dto/ColumnFilterInfos.java @@ -0,0 +1,27 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.dto; + +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * @author Rehili Ghazwa + */ +@Schema(name = "ColumnFilterInfos", description = "Column filter infos") +public record ColumnFilterInfos( + @Schema(description = "Filter data type") + String filterDataType, + + @Schema(description = "Filter type") + String filterType, + + @Schema(description = "Filter value") + String filterValue, + + @Schema(description = "Filter tolerance for numeric comparisons") + Double filterTolerance +) { } diff --git a/src/main/java/org/gridsuite/studyconfig/server/dto/ComputationResultColumnFilterInfos.java b/src/main/java/org/gridsuite/studyconfig/server/dto/ComputationResultColumnFilterInfos.java new file mode 100644 index 00000000..d88af04b --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/dto/ComputationResultColumnFilterInfos.java @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.dto; + +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * @author Rehili Ghazwa + */ +@Schema(name = "ComputationResultColumnFilterInfos", description = "Computation Result Column filter infos") +public record ComputationResultColumnFilterInfos( + + @Schema(description = "Column id") + String columnId, + + @Schema(description = "column filter infos") + ColumnFilterInfos columnFilterInfos +) { } diff --git a/src/main/java/org/gridsuite/studyconfig/server/dto/ColumnInfos.java b/src/main/java/org/gridsuite/studyconfig/server/dto/SpreadsheetColumnInfos.java similarity index 59% rename from src/main/java/org/gridsuite/studyconfig/server/dto/ColumnInfos.java rename to src/main/java/org/gridsuite/studyconfig/server/dto/SpreadsheetColumnInfos.java index 02681948..0d7cba6f 100644 --- a/src/main/java/org/gridsuite/studyconfig/server/dto/ColumnInfos.java +++ b/src/main/java/org/gridsuite/studyconfig/server/dto/SpreadsheetColumnInfos.java @@ -16,8 +16,8 @@ /** * @author Achour BERRAHMA */ -@Schema(name = "ColumnDto", description = "Column configuration") -public record ColumnInfos( +@Schema(name = "SpreadsheetColumnInfos", description = "Column configuration") +public record SpreadsheetColumnInfos( @Schema(description = "Column UUID") UUID uuid, @@ -41,24 +41,32 @@ public record ColumnInfos( @Schema(description = "Column id") String id, - @Schema(description = "Filter data type") - String filterDataType, - - @Schema(description = "Filter type") - String filterType, - - @Schema(description = "Filter value") - String filterValue, - - @Schema(description = "Filter tolerance for numeric comparisons") - Double filterTolerance, - @Schema(description = "Column visibility", defaultValue = "true") - Boolean visible + Boolean visible, + + @Schema(description = "column filter infos") + ColumnFilterInfos columnFilterInfos ) { - public ColumnInfos { + public SpreadsheetColumnInfos { if (visible == null) { visible = true; } } + + public SpreadsheetColumnInfos( + UUID uuid, + String name, + ColumnType type, + Integer precision, + String formula, + String dependencies, + String id, + boolean visible, + String filterDataType, + String filterType, + String filterValue, + Double filterTolerance) { + this(uuid, name, type, precision, formula, dependencies, id, visible, + new ColumnFilterInfos(filterDataType, filterType, filterValue, filterTolerance)); + } } diff --git a/src/main/java/org/gridsuite/studyconfig/server/dto/SpreadsheetConfigInfos.java b/src/main/java/org/gridsuite/studyconfig/server/dto/SpreadsheetConfigInfos.java index 3419e758..ada37ba1 100644 --- a/src/main/java/org/gridsuite/studyconfig/server/dto/SpreadsheetConfigInfos.java +++ b/src/main/java/org/gridsuite/studyconfig/server/dto/SpreadsheetConfigInfos.java @@ -30,7 +30,7 @@ public record SpreadsheetConfigInfos( SheetType sheetType, @Schema(description = "Columns") - List columns, + List columns, @Schema(description = "Global filters") List globalFilters, diff --git a/src/main/java/org/gridsuite/studyconfig/server/entities/ColumnFilterEntity.java b/src/main/java/org/gridsuite/studyconfig/server/entities/ColumnFilterEntity.java new file mode 100644 index 00000000..43b6dc4d --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/entities/ColumnFilterEntity.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.entities; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.UUID; + +/** + * @author Rehili Ghazwa + */ +@Entity +@Table(name = "column_filter") +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder(toBuilder = true) +public class ColumnFilterEntity { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "uuid") + private UUID uuid; + + @Column(name = "filter_data_type", columnDefinition = "varchar(255)") + private String filterDataType; + + @Column(name = "filter_type", columnDefinition = "varchar(255)") + private String filterType; + + @Column(name = "filter_value", columnDefinition = "CLOB") + private String filterValue; + + @Column(name = "filter_tolerance") + private Double filterTolerance; + + public void resetFilter() { + this.filterDataType = null; + this.filterType = null; + this.filterTolerance = null; + this.filterValue = null; + } + + public ColumnFilterEntity copy() { + return ColumnFilterEntity.builder() + .filterDataType(this.getFilterDataType()) + .filterType(this.getFilterType()) + .filterValue(this.getFilterValue()) + .filterTolerance(this.getFilterTolerance()) + .build(); + } +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/entities/GlobalFilterEntity.java b/src/main/java/org/gridsuite/studyconfig/server/entities/GlobalFilterEntity.java index 976a80a7..451d0464 100644 --- a/src/main/java/org/gridsuite/studyconfig/server/entities/GlobalFilterEntity.java +++ b/src/main/java/org/gridsuite/studyconfig/server/entities/GlobalFilterEntity.java @@ -15,7 +15,10 @@ * @author Achour BERRAHMA */ @Entity -@Table(name = "spreadsheet_global_filter") +@Table(name = "global_filter", indexes = { + @Index(name = "idx_global_filter_spreadsheet_config_id", columnList = "spreadsheet_config_id"), + @Index(name = "idx_global_filter_computation_type_filters_id", columnList = "computation_type_filters_id")} +) @Getter @Setter @NoArgsConstructor @@ -37,7 +40,7 @@ public class GlobalFilterEntity { @Column(name = "label", nullable = false) private String label; - @Column(name = "recent") + @Column(name = "recent", nullable = false, columnDefinition = "boolean default false") private boolean recent; @Column(name = "uuid") diff --git a/src/main/java/org/gridsuite/studyconfig/server/entities/ColumnEntity.java b/src/main/java/org/gridsuite/studyconfig/server/entities/SpreadsheetColumnEntity.java similarity index 55% rename from src/main/java/org/gridsuite/studyconfig/server/entities/ColumnEntity.java rename to src/main/java/org/gridsuite/studyconfig/server/entities/SpreadsheetColumnEntity.java index a9d91cb8..545f3bd7 100644 --- a/src/main/java/org/gridsuite/studyconfig/server/entities/ColumnEntity.java +++ b/src/main/java/org/gridsuite/studyconfig/server/entities/SpreadsheetColumnEntity.java @@ -6,12 +6,11 @@ */ package org.gridsuite.studyconfig.server.entities; -import java.util.UUID; - -import org.gridsuite.studyconfig.server.constants.ColumnType; - import jakarta.persistence.*; import lombok.*; +import org.gridsuite.studyconfig.server.constants.ColumnType; + +import java.util.UUID; /** * @author Achour BERRAHMA @@ -23,7 +22,7 @@ @NoArgsConstructor @AllArgsConstructor @Builder(toBuilder = true) -public class ColumnEntity { +public class SpreadsheetColumnEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) @@ -49,42 +48,25 @@ public class ColumnEntity { @Column(name = "columnId", nullable = false, columnDefinition = "varchar(255)") private String id; - @Column(name = "filter_data_type", columnDefinition = "varchar(255)") - private String filterDataType; - - @Column(name = "filter_type", columnDefinition = "varchar(255)") - private String filterType; - - @Column(name = "filter_value", columnDefinition = "CLOB") - private String filterValue; - - @Column(name = "filter_tolerance") - private Double filterTolerance; - - @Column(name = "visible", nullable = false) + @Column(name = "visible", nullable = false, columnDefinition = "boolean default true") @Builder.Default private boolean visible = true; - public void resetFilter() { - this.filterDataType = null; - this.filterType = null; - this.filterTolerance = null; - this.filterValue = null; - } - - public ColumnEntity copy() { - return ColumnEntity.builder() - .name(getName()) - .type(getType()) - .precision(getPrecision()) - .formula(getFormula()) - .dependencies(getDependencies()) - .id(getId()) - .filterDataType(getFilterDataType()) - .filterType(getFilterType()) - .filterValue(getFilterValue()) - .filterTolerance(getFilterTolerance()) - .visible(isVisible()) - .build(); + @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @JoinColumn(name = "columnEntity_columnFilter_id", referencedColumnName = "uuid", + foreignKey = @ForeignKey(name = "columnEntity_columnFilter_fk")) + private ColumnFilterEntity columnFilter; + + public SpreadsheetColumnEntity copy() { + return SpreadsheetColumnEntity.builder() + .name(getName()) + .type(getType()) + .precision(getPrecision()) + .formula(getFormula()) + .dependencies(getDependencies()) + .id(getId()) + .columnFilter(this.columnFilter != null ? this.columnFilter.copy() : null) + .visible(isVisible()) + .build(); } } diff --git a/src/main/java/org/gridsuite/studyconfig/server/entities/SpreadsheetConfigEntity.java b/src/main/java/org/gridsuite/studyconfig/server/entities/SpreadsheetConfigEntity.java index 7f75798e..b17f45ca 100644 --- a/src/main/java/org/gridsuite/studyconfig/server/entities/SpreadsheetConfigEntity.java +++ b/src/main/java/org/gridsuite/studyconfig/server/entities/SpreadsheetConfigEntity.java @@ -43,7 +43,7 @@ public class SpreadsheetConfigEntity { @JoinColumn(name = "spreadsheet_config_id", foreignKey = @ForeignKey(name = "fk_spreadsheet_config_column")) @OrderColumn(name = "column_order") @Builder.Default - private List columns = new ArrayList<>(); + private List columns = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn(name = "spreadsheet_config_id", foreignKey = @ForeignKey(name = "fk_global_filter_spreadsheet_config")) @@ -63,6 +63,10 @@ public class SpreadsheetConfigEntity { public void resetFilters() { this.globalFilters.clear(); - getColumns().forEach(ColumnEntity::resetFilter); + this.columns.forEach(column -> { + if (column.getColumnFilter() != null) { + column.getColumnFilter().resetFilter(); + } + }); } } diff --git a/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/ColumnEntity.java b/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/ColumnEntity.java new file mode 100644 index 00000000..bd6ac108 --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/ColumnEntity.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.entities.computationresult; + +import jakarta.persistence.*; +import lombok.*; +import org.gridsuite.studyconfig.server.entities.ColumnFilterEntity; + +import java.util.UUID; + +/** + * @author Rehili Ghazwa + */ +@Entity +@Table(name = "computation_column", indexes = @Index(name = "idx_computation_sub_type_filters_id", columnList = "computation_sub_type_filters_id")) +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@Builder(toBuilder = true) +public class ColumnEntity { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "uuid") + private UUID uuid; + + @Column(name = "computation_column_id", nullable = false, columnDefinition = "varchar(255)") + private String computationColumnId; + + @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY) + @JoinColumn(name = "computationResult_columnFilter_id", referencedColumnName = "uuid", foreignKey = @ForeignKey(name = "computationResult_columnFilter_fk")) + private ColumnFilterEntity columnFilter; +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FilterSubTypeEntity.java b/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FilterSubTypeEntity.java new file mode 100644 index 00000000..73b57a2a --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FilterSubTypeEntity.java @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.entities.computationresult; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.*; + +/** + * @author Rehili Ghazwa + */ +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Entity +@Table(name = "computation_sub_type_filters", indexes = @Index(name = "idx_computation_type_computation_sub_type_id", columnList = "computation_type_computation_sub_type_id")) +public class FilterSubTypeEntity { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "uuid") + private UUID uuid; + + @Column(name = "computation_sub_type", nullable = false) + private String computationSubType; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "computation_sub_type_filters_id", foreignKey = @ForeignKey(name = "fk_computation_sub_type_filters_id")) + @Builder.Default + private List columns = new ArrayList<>(); +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FilterTypeEntity.java b/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FilterTypeEntity.java new file mode 100644 index 00000000..9b38eea4 --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FilterTypeEntity.java @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.entities.computationresult; + +import jakarta.persistence.*; +import lombok.*; +import org.gridsuite.studyconfig.server.entities.GlobalFilterEntity; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * @author Rehili Ghazwa + */ +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Entity +@Table(name = "computation_type_filters", indexes = @Index(name = "idx_computation_result_filters_id", columnList = "computation_result_filters_id")) +public class FilterTypeEntity { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "uuid") + private UUID uuid; + + @Column(name = "computation_type", nullable = false) + private String computationType; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "computation_type_filters_id", foreignKey = @ForeignKey(name = "fk_computation_type_global_filters")) + @Builder.Default + private List globalFilters = new ArrayList<>(); + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "computation_type_computation_sub_type_id", foreignKey = @ForeignKey(name = "fk_computation_type_computation_sub_type_id")) + @Builder.Default + private List computationSubTypes = new ArrayList<>(); +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FiltersEntity.java b/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FiltersEntity.java new file mode 100644 index 00000000..a9cb9981 --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/entities/computationresult/FiltersEntity.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.entities.computationresult; + +import jakarta.persistence.*; +import lombok.*; + +import java.util.*; + +/** + * @author Rehili Ghazwa + */ +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Setter +@Entity +@Table(name = "computation_result_filters") +public class FiltersEntity { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "id") + private UUID id; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name = "computation_result_filters_id", foreignKey = @ForeignKey(name = "fk_computation_result_filters_type")) + @Builder.Default + private List computationResultFilter = new ArrayList<>(); +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/mapper/ComputationResultFiltersMapper.java b/src/main/java/org/gridsuite/studyconfig/server/mapper/ComputationResultFiltersMapper.java new file mode 100644 index 00000000..962e65eb --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/mapper/ComputationResultFiltersMapper.java @@ -0,0 +1,41 @@ +/** +* Copyright (c) 2025, RTE (http://www.rte-france.com) +* This Source Code Form is subject to the terms of the Mozilla Public +* License, v. 2.0. If a copy of the MPL was not distributed with this +* file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ +package org.gridsuite.studyconfig.server.mapper; + +import org.gridsuite.studyconfig.server.dto.*; +import org.gridsuite.studyconfig.server.dto.ComputationResultColumnFilterInfos; +import org.gridsuite.studyconfig.server.entities.*; +import org.gridsuite.studyconfig.server.entities.computationresult.ColumnEntity; + +/** + * @author Rehili Ghazwa + */ +public final class ComputationResultFiltersMapper { + + private ComputationResultFiltersMapper() { } + + public static ComputationResultColumnFilterInfos toComputationColumnFilterInfos(ColumnEntity entity) { + ColumnFilterEntity filter = entity.getColumnFilter(); + return new ComputationResultColumnFilterInfos(entity.getComputationColumnId(), filter != null ? + new ColumnFilterInfos(filter.getFilterDataType(), filter.getFilterType(), filter.getFilterValue(), filter.getFilterTolerance()) + : null); + } + + public static ColumnEntity toComputationColumnFilterEntity(ComputationResultColumnFilterInfos columnFilterInfos) { + return ColumnEntity.builder() + .computationColumnId(columnFilterInfos.columnId()) + .columnFilter(columnFilterInfos.columnFilterInfos() != null ? ColumnFilterEntity.builder() + .filterDataType(columnFilterInfos.columnFilterInfos().filterDataType()) + .filterType(columnFilterInfos.columnFilterInfos().filterType()) + .filterValue(columnFilterInfos.columnFilterInfos().filterValue()) + .filterTolerance(columnFilterInfos.columnFilterInfos().filterTolerance()) + .build() : null) + .build(); + } +} + + diff --git a/src/main/java/org/gridsuite/studyconfig/server/mapper/SpreadsheetConfigMapper.java b/src/main/java/org/gridsuite/studyconfig/server/mapper/SpreadsheetConfigMapper.java index 2c83da18..a8fbcd7e 100644 --- a/src/main/java/org/gridsuite/studyconfig/server/mapper/SpreadsheetConfigMapper.java +++ b/src/main/java/org/gridsuite/studyconfig/server/mapper/SpreadsheetConfigMapper.java @@ -8,7 +8,8 @@ import org.gridsuite.studyconfig.server.constants.SortDirection; import org.gridsuite.studyconfig.server.dto.*; -import org.gridsuite.studyconfig.server.entities.ColumnEntity; +import org.gridsuite.studyconfig.server.entities.SpreadsheetColumnEntity; +import org.gridsuite.studyconfig.server.entities.ColumnFilterEntity; import org.gridsuite.studyconfig.server.entities.GlobalFilterEntity; import org.gridsuite.studyconfig.server.entities.SpreadsheetConfigEntity; @@ -69,8 +70,9 @@ public static SpreadsheetConfigEntity toEntity(SpreadsheetConfigInfos dto) { return entity; } - public static ColumnInfos toColumnDto(ColumnEntity entity) { - return new ColumnInfos( + public static SpreadsheetColumnInfos toColumnDto(SpreadsheetColumnEntity entity) { + ColumnFilterEntity filter = entity.getColumnFilter(); + return new SpreadsheetColumnInfos( entity.getUuid(), entity.getName(), entity.getType(), @@ -78,27 +80,29 @@ public static ColumnInfos toColumnDto(ColumnEntity entity) { entity.getFormula(), entity.getDependencies(), entity.getId(), - entity.getFilterDataType(), - entity.getFilterType(), - entity.getFilterValue(), - entity.getFilterTolerance(), - entity.isVisible() + entity.isVisible(), + filter != null ? filter.getFilterDataType() : null, + filter != null ? filter.getFilterType() : null, + filter != null ? filter.getFilterValue() : null, + filter != null ? filter.getFilterTolerance() : null ); } - public static ColumnEntity toColumnEntity(ColumnInfos dto) { - return ColumnEntity.builder() + public static SpreadsheetColumnEntity toColumnEntity(SpreadsheetColumnInfos dto) { + return SpreadsheetColumnEntity.builder() .name(dto.name()) .type(dto.type()) .precision(dto.precision()) .formula(dto.formula()) .dependencies(dto.dependencies()) .id(dto.id()) - .filterDataType(dto.filterDataType()) - .filterType(dto.filterType()) - .filterValue(dto.filterValue()) - .filterTolerance(dto.filterTolerance()) .visible(dto.visible()) + .columnFilter(dto.columnFilterInfos() != null ? ColumnFilterEntity.builder() + .filterDataType(dto.columnFilterInfos().filterDataType()) + .filterType(dto.columnFilterInfos().filterType()) + .filterValue(dto.columnFilterInfos().filterValue()) + .filterTolerance(dto.columnFilterInfos().filterTolerance()) + .build() : null) .build(); } diff --git a/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FilterSubTypeRepository.java b/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FilterSubTypeRepository.java new file mode 100644 index 00000000..31f0caa6 --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FilterSubTypeRepository.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.repositories.computationresult; + +import org.gridsuite.studyconfig.server.entities.computationresult.FilterSubTypeEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +/** + * @author Rehili Ghazwa + */ +@Repository +public interface FilterSubTypeRepository extends JpaRepository { +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FilterTypeRepository.java b/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FilterTypeRepository.java new file mode 100644 index 00000000..f3045cdb --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FilterTypeRepository.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.repositories.computationresult; + +import org.gridsuite.studyconfig.server.entities.computationresult.FilterTypeEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +/** + * @author Rehili Ghazwa + */ +@Repository +public interface FilterTypeRepository extends JpaRepository { +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FiltersRepository.java b/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FiltersRepository.java new file mode 100644 index 00000000..226957f2 --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/repositories/computationresult/FiltersRepository.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.repositories.computationresult; + +import org.gridsuite.studyconfig.server.entities.computationresult.FiltersEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.UUID; + +/** + * @author Rehili Ghazwa + */ +@Repository +public interface FiltersRepository extends JpaRepository { +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/service/ComputationResultFiltersService.java b/src/main/java/org/gridsuite/studyconfig/server/service/ComputationResultFiltersService.java new file mode 100644 index 00000000..eaf5c84c --- /dev/null +++ b/src/main/java/org/gridsuite/studyconfig/server/service/ComputationResultFiltersService.java @@ -0,0 +1,159 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server.service; + +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; +import org.gridsuite.studyconfig.server.dto.ComputationResultColumnFilterInfos; +import org.gridsuite.studyconfig.server.dto.GlobalFilterInfos; +import org.gridsuite.studyconfig.server.entities.GlobalFilterEntity; +import org.gridsuite.studyconfig.server.entities.computationresult.ColumnEntity; +import org.gridsuite.studyconfig.server.entities.computationresult.FilterSubTypeEntity; +import org.gridsuite.studyconfig.server.entities.computationresult.FilterTypeEntity; +import org.gridsuite.studyconfig.server.entities.computationresult.FiltersEntity; +import org.gridsuite.studyconfig.server.mapper.ComputationResultFiltersMapper; +import org.gridsuite.studyconfig.server.mapper.SpreadsheetConfigMapper; +import org.gridsuite.studyconfig.server.repositories.computationresult.FilterSubTypeRepository; +import org.gridsuite.studyconfig.server.repositories.computationresult.FilterTypeRepository; +import org.gridsuite.studyconfig.server.repositories.computationresult.FiltersRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.UUID; + +import static org.gridsuite.studyconfig.server.mapper.ComputationResultFiltersMapper.toComputationColumnFilterEntity; + + +/** + * @author Rehili Ghazwa + */ +@Service +@RequiredArgsConstructor +public class ComputationResultFiltersService { + private static final String COMPUTATION_FILTERS_NOT_FOUND = "not found"; + private final FiltersRepository filtersRepository; + private final FilterTypeRepository filterTypeRepository; + private final FilterSubTypeRepository filterSubTypeRepository; + + @Transactional + public UUID createDefaultComputingResultFilters() { + FiltersEntity filtersEntity = new FiltersEntity(); + return filtersRepository.saveAndFlush(filtersEntity).getId(); + } + + private FiltersEntity getFiltersEntity(UUID computationResultFiltersId) { + return filtersRepository.findById(computationResultFiltersId) + .orElseThrow(() -> new EntityNotFoundException(COMPUTATION_FILTERS_NOT_FOUND + computationResultFiltersId)); + } + + private FilterTypeEntity findComputationType(FiltersEntity filtersEntity, String type) { + return filtersEntity.getComputationResultFilter().stream() + .filter(t -> t.getComputationType().equals(type)) + .findFirst() + .orElse(null); + } + + private FilterSubTypeEntity findComputationSubType(FilterTypeEntity typeEntity, String subType) { + return typeEntity.getComputationSubTypes().stream() + .filter(s -> s.getComputationSubType().equals(subType)) + .findFirst() + .orElse(null); + } + + @Transactional(readOnly = true) + public List getComputingResultColumnFilters(UUID computationResultFiltersId, String computationType, String computationSubType) { + FiltersEntity filtersEntity = getFiltersEntity(computationResultFiltersId); + FilterTypeEntity typeEntity = findComputationType(filtersEntity, computationType); + if (typeEntity == null) { + return List.of(); + } + FilterSubTypeEntity subTypeEntity = findComputationSubType(typeEntity, computationSubType); + if (subTypeEntity == null) { + return List.of(); + } + return subTypeEntity.getColumns().stream().map(ComputationResultFiltersMapper::toComputationColumnFilterInfos).toList(); + } + + @Transactional(readOnly = true) + public List getComputingResultGlobalFilters(UUID computationResultFiltersId, String computationType) { + FiltersEntity filtersEntity = getFiltersEntity(computationResultFiltersId); + FilterTypeEntity typeEntity = findComputationType(filtersEntity, computationType); + if (typeEntity == null) { + return List.of(); + } + return typeEntity.getGlobalFilters().stream().map(SpreadsheetConfigMapper::toGlobalFilterDto).toList(); + } + + @Transactional + public void setGlobalFiltersForComputationResult(UUID computationResultFiltersId, String computationType, List globalFilters) { + FiltersEntity filtersEntity = getFiltersEntity(computationResultFiltersId); + FilterTypeEntity typeEntity = filtersEntity.getComputationResultFilter().stream() + .filter(type -> computationType.equals(type.getComputationType())) + .findFirst() + .orElseGet(() -> { + FilterTypeEntity entity = new FilterTypeEntity(); + entity.setComputationType(computationType); + filtersEntity.getComputationResultFilter().add(entity); + return entity; + }); + + List newFilters = globalFilters.stream().map(SpreadsheetConfigMapper::toGlobalFilterEntity).toList(); + if (!typeEntity.getGlobalFilters().equals(newFilters)) { + typeEntity.getGlobalFilters().clear(); + typeEntity.getGlobalFilters().addAll(newFilters); + } + filtersRepository.save(filtersEntity); + } + + @Transactional + public void updateColumn(UUID computationResultFiltersId, String computationType, String computationSubType, ComputationResultColumnFilterInfos columnFilter) { + FiltersEntity filtersEntity = getFiltersEntity(computationResultFiltersId); + FilterTypeEntity typeEntity = findOrCreateComputationType(filtersEntity, computationType); + if (typeEntity.getUuid() == null) { + filterTypeRepository.save(typeEntity); + } + FilterSubTypeEntity subTypeEntity = typeEntity.getComputationSubTypes().stream() + .filter(sub -> sub.getComputationSubType().equals(computationSubType)) + .findFirst() + .orElseGet(() -> createAndAttachSubType(typeEntity, computationSubType)); + + // DELETE case (columnFilter is null) + var filterInfos = columnFilter.columnFilterInfos(); + if (filterInfos == null) { + String columnId = columnFilter.columnId(); + subTypeEntity.getColumns().removeIf(col -> columnId.equals(col.getComputationColumnId())); + filtersRepository.save(filtersEntity); + return; + } + // UPDATE/INSERT case + ColumnEntity updatedColumn = toComputationColumnFilterEntity(columnFilter); + String updatedColumnId = updatedColumn.getComputationColumnId(); + subTypeEntity.getColumns().removeIf(col -> updatedColumnId != null && updatedColumnId.equals(col.getComputationColumnId())); + subTypeEntity.getColumns().add(updatedColumn); + filtersRepository.save(filtersEntity); + } + + private FilterTypeEntity findOrCreateComputationType(FiltersEntity filtersEntity, String computationType) { + return filtersEntity.getComputationResultFilter().stream() + .filter(type -> type.getComputationType().equals(computationType)) + .findFirst() + .orElseGet(() -> { + FilterTypeEntity newType = new FilterTypeEntity(); + newType.setComputationType(computationType); + filtersEntity.getComputationResultFilter().add(newType); + return newType; + }); + } + + private FilterSubTypeEntity createAndAttachSubType(FilterTypeEntity typeEntity, String computationSubType) { + FilterSubTypeEntity newSubType = new FilterSubTypeEntity(); + newSubType.setComputationSubType(computationSubType); + typeEntity.getComputationSubTypes().add(newSubType); + return filterSubTypeRepository.save(newSubType); + } +} diff --git a/src/main/java/org/gridsuite/studyconfig/server/service/SpreadsheetConfigService.java b/src/main/java/org/gridsuite/studyconfig/server/service/SpreadsheetConfigService.java index 8c5e3cfe..05019023 100644 --- a/src/main/java/org/gridsuite/studyconfig/server/service/SpreadsheetConfigService.java +++ b/src/main/java/org/gridsuite/studyconfig/server/service/SpreadsheetConfigService.java @@ -10,10 +10,7 @@ import org.apache.commons.lang3.tuple.Pair; import org.gridsuite.studyconfig.server.constants.SortDirection; import org.gridsuite.studyconfig.server.dto.*; -import org.gridsuite.studyconfig.server.entities.ColumnEntity; -import org.gridsuite.studyconfig.server.entities.GlobalFilterEntity; -import org.gridsuite.studyconfig.server.entities.SpreadsheetConfigCollectionEntity; -import org.gridsuite.studyconfig.server.entities.SpreadsheetConfigEntity; +import org.gridsuite.studyconfig.server.entities.*; import org.gridsuite.studyconfig.server.mapper.SpreadsheetConfigMapper; import org.gridsuite.studyconfig.server.repositories.SpreadsheetConfigCollectionRepository; import org.gridsuite.studyconfig.server.repositories.SpreadsheetConfigRepository; @@ -74,7 +71,7 @@ private SpreadsheetConfigEntity duplicateSpreadsheetConfigEntity(UUID id) { duplicate.setSortDirection(entity.getSortDirection()); } duplicate.setColumns(entity.getColumns().stream() - .map(ColumnEntity::copy) + .map(SpreadsheetColumnEntity::copy) .toList()); // Copy global filters if needed @@ -278,7 +275,7 @@ public UUID duplicateSpreadsheetConfigCollection(UUID id) { configDuplicate.setNodeAliases(new ArrayList<>(config.getNodeAliases())); } configDuplicate.setColumns(config.getColumns().stream() - .map(ColumnEntity::copy) + .map(SpreadsheetColumnEntity::copy) .toList()); configDuplicate.setGlobalFilters(config.getGlobalFilters().stream() .map(GlobalFilterEntity::copy) @@ -291,7 +288,7 @@ public UUID duplicateSpreadsheetConfigCollection(UUID id) { } @Transactional(readOnly = true) - public ColumnInfos getColumn(UUID id, UUID columnId) { + public SpreadsheetColumnInfos getColumn(UUID id, UUID columnId) { SpreadsheetConfigEntity entity = findEntityById(id); return entity.getColumns().stream() .filter(column -> column.getUuid().equals(columnId)) @@ -301,18 +298,18 @@ public ColumnInfos getColumn(UUID id, UUID columnId) { } @Transactional - public UUID createColumn(UUID id, ColumnInfos dto) { + public UUID createColumn(UUID id, SpreadsheetColumnInfos dto) { SpreadsheetConfigEntity entity = findEntityById(id); - ColumnEntity columnEntity = SpreadsheetConfigMapper.toColumnEntity(dto); + SpreadsheetColumnEntity columnEntity = SpreadsheetConfigMapper.toColumnEntity(dto); entity.getColumns().add(columnEntity); spreadsheetConfigRepository.flush(); return columnEntity.getUuid(); } @Transactional - public void updateColumn(UUID id, UUID columnId, ColumnInfos dto) { + public void updateColumn(UUID id, UUID columnId, SpreadsheetColumnInfos dto) { SpreadsheetConfigEntity entity = findEntityById(id); - ColumnEntity columnEntity = entity.getColumns().stream() + SpreadsheetColumnEntity columnEntity = entity.getColumns().stream() .filter(column -> column.getUuid().equals(columnId)) .findFirst() .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, COLUMN_NOT_FOUND + columnId)); @@ -323,10 +320,18 @@ public void updateColumn(UUID id, UUID columnId, ColumnInfos dto) { columnEntity.setFormula(dto.formula()); columnEntity.setDependencies(dto.dependencies()); columnEntity.setId(dto.id()); - columnEntity.setFilterDataType(dto.filterDataType()); - columnEntity.setFilterType(dto.filterType()); - columnEntity.setFilterValue(dto.filterValue()); - columnEntity.setFilterTolerance(dto.filterTolerance()); + var infos = dto.columnFilterInfos(); + if (infos != null) { + ColumnFilterEntity filter = columnEntity.getColumnFilter(); + if (filter == null) { + filter = new ColumnFilterEntity(); + columnEntity.setColumnFilter(filter); + } + filter.setFilterDataType(infos.filterDataType()); + filter.setFilterType(infos.filterType()); + filter.setFilterValue(infos.filterValue()); + filter.setFilterTolerance(infos.filterTolerance()); + } columnEntity.setVisible(dto.visible()); spreadsheetConfigRepository.save(entity); @@ -345,12 +350,12 @@ public void deleteColumn(UUID id, UUID columnId) { @Transactional public void reorderColumns(UUID id, List columnOrder) { SpreadsheetConfigEntity entity = findEntityById(id); - List columns = entity.getColumns(); + List columns = entity.getColumns(); reorderColumns(columnOrder, columns); } - private static void reorderColumns(List columnOrder, List columns) { + private static void reorderColumns(List columnOrder, List columns) { columns.sort(Comparator.comparingInt(column -> columnOrder.indexOf(column.getUuid()))); } @@ -378,8 +383,8 @@ private String getUniqueValue(String originalValue, Set existingValues) } private Pair getDuplicateIdAndNameCandidate(SpreadsheetConfigEntity entity, String columnId, String columnName) { - var existingColumnIds = entity.getColumns().stream().map(ColumnEntity::getId).collect(Collectors.toSet()); - var existingColumnNames = entity.getColumns().stream().map(ColumnEntity::getName).collect(Collectors.toSet()); + var existingColumnIds = entity.getColumns().stream().map(SpreadsheetColumnEntity::getId).collect(Collectors.toSet()); + var existingColumnNames = entity.getColumns().stream().map(SpreadsheetColumnEntity::getName).collect(Collectors.toSet()); String newColumnId = getUniqueValue(columnId, existingColumnIds); String newColumnName = getUniqueValue(columnName, existingColumnNames); @@ -389,14 +394,15 @@ private Pair getDuplicateIdAndNameCandidate(SpreadsheetConfigEnt @Transactional public void duplicateColumn(UUID id, UUID columnId) { SpreadsheetConfigEntity entity = findEntityById(id); - ColumnEntity columnEntity = entity.getColumns().stream().filter(col -> col.getUuid().equals(columnId)) + SpreadsheetColumnEntity columnEntity = entity.getColumns().stream().filter(col -> col.getUuid().equals(columnId)) .findFirst().orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, COLUMN_NOT_FOUND + columnId)); - ColumnEntity columnCopy = columnEntity.toBuilder().build(); + SpreadsheetColumnEntity columnCopy = columnEntity.toBuilder().build(); columnCopy.setUuid(null); + columnCopy.setColumnFilter(columnEntity.getColumnFilter().copy()); Pair idAndName = getDuplicateIdAndNameCandidate(entity, columnCopy.getId(), columnCopy.getName()); columnCopy.setId(idAndName.getLeft()); columnCopy.setName(idAndName.getRight()); - List columns = entity.getColumns(); + List columns = entity.getColumns(); columns.add(columns.indexOf(columnEntity) + 1, columnCopy); entity.setColumns(columns); spreadsheetConfigRepository.save(entity); @@ -405,13 +411,13 @@ public void duplicateColumn(UUID id, UUID columnId) { @Transactional public void updateColumnStates(UUID id, List columnStates) { SpreadsheetConfigEntity entity = findEntityById(id); - List columns = entity.getColumns(); + List columns = entity.getColumns(); - Map columnMap = columns.stream() - .collect(Collectors.toMap(ColumnEntity::getUuid, column -> column)); + Map columnMap = columns.stream() + .collect(Collectors.toMap(SpreadsheetColumnEntity::getUuid, column -> column)); for (ColumnStateUpdateInfos state : columnStates) { - ColumnEntity column = columnMap.get(state.columnId()); + SpreadsheetColumnEntity column = columnMap.get(state.columnId()); if (column == null) { throw new ResponseStatusException(HttpStatus.NOT_FOUND, COLUMN_NOT_FOUND + state.columnId()); } diff --git a/src/main/resources/db/changelog/changesets/changelog_20260128T102437Z.xml b/src/main/resources/db/changelog/changesets/changelog_20260128T102437Z.xml new file mode 100644 index 00000000..b662d0be --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20260128T102437Z.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/changesets/migrationColumnFilter_20260201T111008Z.sql b/src/main/resources/db/changelog/changesets/migrationColumnFilter_20260201T111008Z.sql new file mode 100644 index 00000000..c5e2e7b0 --- /dev/null +++ b/src/main/resources/db/changelog/changesets/migrationColumnFilter_20260201T111008Z.sql @@ -0,0 +1,20 @@ +WITH created_filters AS (SELECT sc.uuid AS column_uuid, + gen_random_uuid() AS filter_uuid, + sc.filter_data_type, + sc.filter_type, + sc.filter_value, + sc.filter_tolerance + FROM spreadsheet_column sc + WHERE sc.filter_data_type IS NOT NULL + OR sc.filter_type IS NOT NULL + OR sc.filter_value IS NOT NULL + OR sc.filter_tolerance IS NOT NULL), + inserted AS ( + INSERT INTO column_filter (uuid, filter_data_type, filter_type, filter_value, filter_tolerance) + SELECT filter_uuid, filter_data_type, filter_type, filter_value, filter_tolerance + FROM created_filters + RETURNING uuid) +UPDATE spreadsheet_column sc +SET column_entity_column_filter_id = cf.filter_uuid +FROM created_filters cf +WHERE sc.uuid = cf.column_uuid; \ No newline at end of file diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 72620d57..141b376e 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -91,4 +91,7 @@ databaseChangeLog: relativeToChangelogFile: true - include: file: changesets/changelog_20260106T155059Z.xml + relativeToChangelogFile: true + - include: + file: changesets/changelog_20260128T102437Z.xml relativeToChangelogFile: true \ No newline at end of file diff --git a/src/test/java/org/gridsuite/studyconfig/server/ComputationResultFiltersTest.java b/src/test/java/org/gridsuite/studyconfig/server/ComputationResultFiltersTest.java new file mode 100644 index 00000000..352422ed --- /dev/null +++ b/src/test/java/org/gridsuite/studyconfig/server/ComputationResultFiltersTest.java @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2025, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.studyconfig.server; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.gridsuite.studyconfig.server.dto.*; +import org.gridsuite.studyconfig.server.dto.ComputationResultColumnFilterInfos; +import org.gridsuite.studyconfig.server.repositories.computationresult.FiltersRepository; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import java.util.List; +import java.util.UUID; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * @author Rehili Ghazwa + */ +@SpringBootTest +@AutoConfigureMockMvc +class ComputationResultFiltersTest { + + private static final String BASE_URI = "/v1/computation-result-filters"; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper mapper; + + @Autowired + private FiltersRepository computationResultFiltersRepository; + + @AfterEach + void tearDown() { + computationResultFiltersRepository.deleteAll(); + } + + private List createGlobalFilters() { + return List.of(GlobalFilterInfos.builder().id(UUID.randomUUID()).filterType("country").label("Filter 1").recent(false).build(), + GlobalFilterInfos.builder().id(UUID.randomUUID()).filterType("country").label("Filter 2").recent(false).build()); + } + + private ComputationResultColumnFilterInfos createColumnFilter() { + return new ComputationResultColumnFilterInfos("subjectId", new ColumnFilterInfos("number", "greaterThan", "10", 0.5)); + } + + @Test + void testCreateDefaultComputationResultFilters() throws Exception { + MvcResult result = mockMvc.perform(post(BASE_URI + "/default")) + .andExpect(status().isCreated()) + .andReturn(); + UUID computationResultFiltersId = mapper.readValue(result.getResponse().getContentAsString(), UUID.class); + assertThat(computationResultFiltersId).isNotNull(); + assertThat(computationResultFiltersRepository.findById(computationResultFiltersId)).isPresent(); + } + + @Test + void testComputationResultFilters() throws Exception { + MvcResult result = mockMvc.perform(post(BASE_URI + "/default")).andReturn(); + UUID computationResultFiltersId = mapper.readValue(result.getResponse().getContentAsString(), UUID.class); + mockMvc.perform(post(BASE_URI + "/" + computationResultFiltersId + "/" + "LoadFlow" + "/global-filters") + .content(mapper.writeValueAsString(createGlobalFilters())) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + mockMvc.perform(put(BASE_URI + "/" + computationResultFiltersId + "/" + "PccMin" + "/" + "pccMinResults" + "/columns") + .content(mapper.writeValueAsString(createColumnFilter())) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + + result = mockMvc.perform(get(BASE_URI + "/" + computationResultFiltersId + "/LoadFlow/loadflowCurrentLimitViolation")).andExpect(status().isOk()).andReturn(); + List infosLoadFlowColumn = mapper.readValue(result.getResponse().getContentAsString(), new TypeReference<>() { }); + assertThat(infosLoadFlowColumn).isEmpty(); + + result = mockMvc.perform(get(BASE_URI + "/" + computationResultFiltersId + "/PccMin/pccMinResults")).andExpect(status().isOk()).andReturn(); + List infosPccMinColumn = mapper.readValue(result.getResponse().getContentAsString(), new TypeReference<>() { }); + assertThat(infosPccMinColumn).hasSize(1); + ComputationResultColumnFilterInfos info = infosPccMinColumn.getFirst(); + assertThat(info.columnId()).isEqualTo("subjectId"); + assertThat(info.columnFilterInfos().filterValue()).isEqualTo("10"); + assertThat(info.columnFilterInfos().filterType()).isEqualTo("greaterThan"); + assertThat(info.columnFilterInfos().filterDataType()).isEqualTo("number"); + + result = mockMvc.perform(get(BASE_URI + "/" + computationResultFiltersId + "/LoadFlow")).andExpect(status().isOk()).andReturn(); + List globalFilterInfos = mapper.readValue(result.getResponse().getContentAsString(), new TypeReference<>() { }); + assertThat(globalFilterInfos).hasSize(2); + GlobalFilterInfos globalFilterInfo = globalFilterInfos.getFirst(); + assertThat(globalFilterInfo.label()).isEqualTo("Filter 1"); + assertThat(globalFilterInfo.filterType()).isEqualTo("country"); + assertThat(globalFilterInfo.recent()).isFalse(); + + } +} diff --git a/src/test/java/org/gridsuite/studyconfig/server/DtoConverterTest.java b/src/test/java/org/gridsuite/studyconfig/server/DtoConverterTest.java index fd1a64bb..ebd9ce13 100644 --- a/src/test/java/org/gridsuite/studyconfig/server/DtoConverterTest.java +++ b/src/test/java/org/gridsuite/studyconfig/server/DtoConverterTest.java @@ -9,10 +9,11 @@ import org.assertj.core.api.WithAssertions; import org.gridsuite.studyconfig.server.constants.ColumnType; import org.gridsuite.studyconfig.server.constants.SheetType; -import org.gridsuite.studyconfig.server.dto.ColumnInfos; +import org.gridsuite.studyconfig.server.dto.SpreadsheetColumnInfos; import org.gridsuite.studyconfig.server.dto.GlobalFilterInfos; import org.gridsuite.studyconfig.server.dto.SpreadsheetConfigInfos; -import org.gridsuite.studyconfig.server.entities.ColumnEntity; +import org.gridsuite.studyconfig.server.entities.SpreadsheetColumnEntity; +import org.gridsuite.studyconfig.server.entities.ColumnFilterEntity; import org.gridsuite.studyconfig.server.entities.GlobalFilterEntity; import org.gridsuite.studyconfig.server.entities.SpreadsheetConfigEntity; import org.gridsuite.studyconfig.server.mapper.SpreadsheetConfigMapper; @@ -38,16 +39,18 @@ void testConversionToDtoOfSpreadsheetConfig() { .id(id) .sheetType(SheetType.BATTERY) .columns(Arrays.asList( - ColumnEntity.builder() + SpreadsheetColumnEntity.builder() .name("Column1") .formula("A+B") .id("id1") - .filterDataType("text") - .filterType("contains") - .filterValue("test") .visible(false) + .columnFilter(ColumnFilterEntity.builder() + .filterDataType("text") + .filterType("contains") + .filterValue("test") + .build()) .build(), - ColumnEntity.builder().name("Column2").formula("C*D").id("id2").build() + SpreadsheetColumnEntity.builder().name("Column2").formula("C*D").id("id2").build() )) .globalFilters(Arrays.asList( GlobalFilterEntity.builder() @@ -73,17 +76,17 @@ void testConversionToDtoOfSpreadsheetConfig() { assertThat(d.columns().get(0).name()).isEqualTo("Column1"); assertThat(d.columns().get(0).formula()).isEqualTo("A+B"); assertThat(d.columns().get(0).id()).isEqualTo("id1"); - assertThat(d.columns().get(0).filterDataType()).isEqualTo("text"); - assertThat(d.columns().get(0).filterType()).isEqualTo("contains"); - assertThat(d.columns().get(0).filterValue()).isEqualTo("test"); + assertThat(d.columns().get(0).columnFilterInfos().filterDataType()).isEqualTo("text"); + assertThat(d.columns().get(0).columnFilterInfos().filterType()).isEqualTo("contains"); + assertThat(d.columns().get(0).columnFilterInfos().filterValue()).isEqualTo("test"); assertThat(d.columns().get(0).visible()).isFalse(); assertThat(d.columns().get(1).name()).isEqualTo("Column2"); assertThat(d.columns().get(1).formula()).isEqualTo("C*D"); assertThat(d.columns().get(1).id()).isEqualTo("id2"); - assertThat(d.columns().get(1).filterDataType()).isNull(); - assertThat(d.columns().get(1).filterType()).isNull(); - assertThat(d.columns().get(1).filterValue()).isNull(); + assertThat(d.columns().get(1).columnFilterInfos().filterDataType()).isNull(); + assertThat(d.columns().get(1).columnFilterInfos().filterType()).isNull(); + assertThat(d.columns().get(1).columnFilterInfos().filterValue()).isNull(); assertThat(d.columns().get(1).visible()).isTrue(); // Global filters assertions @@ -102,10 +105,10 @@ void testConversionToEntityOfSpreadsheetConfig() { "TestSheet", SheetType.BUS, Arrays.asList( - new ColumnInfos(null, "Column1", ColumnType.NUMBER, 1, "X+Y", "[\"col1\", \"col2\"]", "id1", - "number", "greaterThan", "100", 0.5, true), - new ColumnInfos(null, "Column2", ColumnType.NUMBER, 2, "Z*W", "[\"col1\"]", "id2", - null, null, null, null, true) + new SpreadsheetColumnInfos(null, "Column1", ColumnType.NUMBER, 1, "X+Y", "[\"col1\", \"col2\"]", "id1", true, + "number", "greaterThan", "100", 0.5), + new SpreadsheetColumnInfos(null, "Column2", ColumnType.NUMBER, 2, "Z*W", "[\"col1\"]", "id2", true, + null, null, null, null) ), List.of( GlobalFilterInfos.builder().uuid(filterId).filterType("country").label("GlobalFilter1").recent(false).build() @@ -128,20 +131,20 @@ void testConversionToEntityOfSpreadsheetConfig() { assertThat(e.getColumns().get(0).getFormula()).isEqualTo("X+Y"); assertThat(e.getColumns().get(0).getId()).isEqualTo("id1"); assertThat(e.getColumns().get(0).getDependencies()).isEqualTo("[\"col1\", \"col2\"]"); - assertThat(e.getColumns().get(0).getFilterDataType()).isEqualTo("number"); - assertThat(e.getColumns().get(0).getFilterType()).isEqualTo("greaterThan"); - assertThat(e.getColumns().get(0).getFilterValue()).isEqualTo("100"); - assertThat(e.getColumns().get(0).getFilterTolerance()).isEqualTo(0.5); + assertThat(e.getColumns().get(0).getColumnFilter().getFilterDataType()).isEqualTo("number"); + assertThat(e.getColumns().get(0).getColumnFilter().getFilterType()).isEqualTo("greaterThan"); + assertThat(e.getColumns().get(0).getColumnFilter().getFilterValue()).isEqualTo("100"); + assertThat(e.getColumns().get(0).getColumnFilter().getFilterTolerance()).isEqualTo(0.5); assertThat(e.getColumns().get(0).isVisible()).isTrue(); assertThat(e.getColumns().get(1).getName()).isEqualTo("Column2"); assertThat(e.getColumns().get(1).getFormula()).isEqualTo("Z*W"); assertThat(e.getColumns().get(1).getId()).isEqualTo("id2"); assertThat(e.getColumns().get(1).getDependencies()).isEqualTo("[\"col1\"]"); - assertThat(e.getColumns().get(1).getFilterDataType()).isNull(); - assertThat(e.getColumns().get(1).getFilterType()).isNull(); - assertThat(e.getColumns().get(1).getFilterValue()).isNull(); - assertThat(e.getColumns().get(1).getFilterTolerance()).isNull(); + assertThat(e.getColumns().get(1).getColumnFilter().getFilterDataType()).isNull(); + assertThat(e.getColumns().get(1).getColumnFilter().getFilterType()).isNull(); + assertThat(e.getColumns().get(1).getColumnFilter().getFilterValue()).isNull(); + assertThat(e.getColumns().get(1).getColumnFilter().getFilterTolerance()).isNull(); assertThat(e.getColumns().get(1).isVisible()).isTrue(); // Global filter assertions @@ -156,17 +159,18 @@ void testConversionToEntityOfSpreadsheetConfig() { class ColumnConverterTest { @Test void testConversionToDtoOfColumnWithFilter() { - ColumnEntity entity = ColumnEntity.builder() + SpreadsheetColumnEntity entity = SpreadsheetColumnEntity.builder() .name("TestColumn") .formula("A+B+C") .id("idTest") + .columnFilter(ColumnFilterEntity.builder() .filterDataType("text") .filterType("startsWith") .filterValue("prefix") - .filterTolerance(null) + .filterTolerance(null).build()) .build(); - ColumnInfos dto = SpreadsheetConfigMapper.toColumnDto(entity); + SpreadsheetColumnInfos dto = SpreadsheetConfigMapper.toColumnDto(entity); assertThat(dto) .as("DTO conversion result") @@ -174,17 +178,17 @@ void testConversionToDtoOfColumnWithFilter() { assertThat(d.name()).isEqualTo("TestColumn"); assertThat(d.formula()).isEqualTo("A+B+C"); assertThat(d.id()).isEqualTo("idTest"); - assertThat(d.filterDataType()).isEqualTo("text"); - assertThat(d.filterType()).isEqualTo("startsWith"); - assertThat(d.filterValue()).isEqualTo("prefix"); - assertThat(d.filterTolerance()).isNull(); + assertThat(d.columnFilterInfos().filterDataType()).isEqualTo("text"); + assertThat(d.columnFilterInfos().filterType()).isEqualTo("startsWith"); + assertThat(d.columnFilterInfos().filterValue()).isEqualTo("prefix"); + assertThat(d.columnFilterInfos().filterTolerance()).isNull(); assertThat(d.visible()).isTrue(); }); } @Test void testConversionToEntityOfColumnWithFilter() { - ColumnInfos dto = new ColumnInfos( + SpreadsheetColumnInfos dto = new SpreadsheetColumnInfos( null, "TestColumn", ColumnType.NUMBER, @@ -192,13 +196,13 @@ void testConversionToEntityOfColumnWithFilter() { "X*Y*Z", "[\"col1\", \"col2\"]", "idTest", + true, "number", "lessThan", "50.5", - 0.1, - true); + 0.1); - ColumnEntity column = SpreadsheetConfigMapper.toColumnEntity(dto); + SpreadsheetColumnEntity column = SpreadsheetConfigMapper.toColumnEntity(dto); assertThat(column) .as("Entity conversion result") @@ -207,17 +211,17 @@ void testConversionToEntityOfColumnWithFilter() { assertThat(e.getFormula()).isEqualTo("X*Y*Z"); assertThat(e.getDependencies()).isEqualTo("[\"col1\", \"col2\"]"); assertThat(e.getId()).isEqualTo("idTest"); - assertThat(e.getFilterDataType()).isEqualTo("number"); - assertThat(e.getFilterType()).isEqualTo("lessThan"); - assertThat(e.getFilterValue()).isEqualTo("50.5"); - assertThat(e.getFilterTolerance()).isEqualTo(0.1); + assertThat(e.getColumnFilter().getFilterDataType()).isEqualTo("number"); + assertThat(e.getColumnFilter().getFilterType()).isEqualTo("lessThan"); + assertThat(e.getColumnFilter().getFilterValue()).isEqualTo("50.5"); + assertThat(e.getColumnFilter().getFilterTolerance()).isEqualTo(0.1); assertThat(e.isVisible()).isTrue(); }); } @Test void testConversionOfColumnWithoutFilter() { - ColumnInfos dto = new ColumnInfos( + SpreadsheetColumnInfos dto = new SpreadsheetColumnInfos( null, "TestColumn", ColumnType.TEXT, @@ -225,14 +229,14 @@ void testConversionOfColumnWithoutFilter() { "X*Y*Z", "[\"col1\", \"col2\"]", "idTest", + true, null, null, null, - null, - true); + null); - ColumnEntity entity = SpreadsheetConfigMapper.toColumnEntity(dto); - ColumnInfos convertedDto = SpreadsheetConfigMapper.toColumnDto(entity); + SpreadsheetColumnEntity entity = SpreadsheetConfigMapper.toColumnEntity(dto); + SpreadsheetColumnInfos convertedDto = SpreadsheetConfigMapper.toColumnDto(entity); assertThat(convertedDto) .as("Round-trip conversion result") diff --git a/src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigCollectionIntegrationTest.java b/src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigCollectionIntegrationTest.java index bd55762b..257fba4c 100644 --- a/src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigCollectionIntegrationTest.java +++ b/src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigCollectionIntegrationTest.java @@ -276,8 +276,8 @@ void testAddSpreadsheetConfigToCollection() throws Exception { SpreadsheetConfigCollectionInfos initialCollection = new SpreadsheetConfigCollectionInfos(null, createSpreadsheetConfigs(), null); UUID collectionUuid = postSpreadsheetConfigCollection(initialCollection); - List columnInfos = List.of( - new ColumnInfos(null, "new_col", ColumnType.NUMBER, 1, "formula", "[\"dep\"]", "idNew", null, null, null, null, true) + List columnInfos = List.of( + new SpreadsheetColumnInfos(null, "new_col", ColumnType.NUMBER, 1, "formula", "[\"dep\"]", "idNew", true, null, null, null, null) ); SpreadsheetConfigInfos newConfig = new SpreadsheetConfigInfos(null, "NewSheet", SheetType.BATTERY, columnInfos, null, List.of(), new SortConfig("idNew", SortDirection.ASC.name().toLowerCase())); @@ -413,9 +413,9 @@ void testReplaceAllSpreadsheetConfigs() throws Exception { } private List createSpreadsheetConfigsWithAliases() { - List columnInfos = Arrays.asList( - new ColumnInfos(null, "cust_a", ColumnType.NUMBER, 1, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", null, null, null, null, true), - new ColumnInfos(null, "cust_b", ColumnType.TEXT, null, "var_minP + 1", null, "idB", null, null, null, null, true) + List columnInfos = Arrays.asList( + new SpreadsheetColumnInfos(null, "cust_a", ColumnType.NUMBER, 1, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_b", ColumnType.TEXT, null, "var_minP + 1", null, "idB", true, null, null, null, null) ); return List.of( @@ -428,9 +428,9 @@ private List createSpreadsheetConfigsWithAliases() { } private List createSpreadsheetConfigs() { - List columnInfos = Arrays.asList( - new ColumnInfos(null, "cust_a", ColumnType.NUMBER, 1, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", null, null, null, null, true), - new ColumnInfos(null, "cust_b", ColumnType.TEXT, null, "var_minP + 1", null, "idB", null, null, null, null, true) + List columnInfos = Arrays.asList( + new SpreadsheetColumnInfos(null, "cust_a", ColumnType.NUMBER, 1, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_b", ColumnType.TEXT, null, "var_minP + 1", null, "idB", true, null, null, null, null) ); return List.of( @@ -440,15 +440,15 @@ private List createSpreadsheetConfigs() { } private List createSpreadsheetConfigsWithFilters() { - List columnsConfig1 = Arrays.asList( - new ColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", - "text", "equals", "test-value", null, true), - new ColumnInfos(null, "name", ColumnType.TEXT, null, "name", "[\"name\"]", "name", - "text", "contains", "name-value", null, true), - new ColumnInfos(null, "country1", ColumnType.ENUM, null, "country1", "[\"country1\"]", "country1", - null, null, null, null, true), - new ColumnInfos(null, "voltage", ColumnType.NUMBER, 1, "voltage", "[\"voltage\"]", "voltage", - "number", "greaterThan", "100", 0.5, true) + List columnsConfig1 = Arrays.asList( + new SpreadsheetColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", true, + "text", "equals", "test-value", null), + new SpreadsheetColumnInfos(null, "name", ColumnType.TEXT, null, "name", "[\"name\"]", "name", true, + "text", "contains", "name-value", null), + new SpreadsheetColumnInfos(null, "country1", ColumnType.ENUM, null, "country1", "[\"country1\"]", "country1", true, + null, null, null, null), + new SpreadsheetColumnInfos(null, "voltage", ColumnType.NUMBER, 1, "voltage", "[\"voltage\"]", "voltage", true, + "number", "greaterThan", "100", 0.5) ); List globalFiltersConfig1 = Arrays.asList( @@ -456,13 +456,13 @@ private List createSpreadsheetConfigsWithFilters() { GlobalFilterInfos.builder().uuid(UUID.randomUUID()).filterType("country").label("Global Filter 2").recent(false).build() ); - List columnsConfig2 = Arrays.asList( - new ColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", - "text", "contains", "other-value", null, true), - new ColumnInfos(null, "type", ColumnType.ENUM, null, "type", "[\"type\"]", "type", - null, null, null, null, true), - new ColumnInfos(null, "power", ColumnType.NUMBER, 1, "power", "[\"power\"]", "power", - "number", "lessThan", "50", 0.1, true) + List columnsConfig2 = Arrays.asList( + new SpreadsheetColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", true, + "text", "contains", "other-value", null), + new SpreadsheetColumnInfos(null, "type", ColumnType.ENUM, null, "type", "[\"type\"]", "type", true, + null, null, null, null), + new SpreadsheetColumnInfos(null, "power", ColumnType.NUMBER, 1, "power", "[\"power\"]", "power", true, + "number", "lessThan", "50", 0.1) ); List globalFiltersConfig2 = List.of( @@ -476,11 +476,11 @@ private List createSpreadsheetConfigsWithFilters() { } private List createUpdatedSpreadsheetConfigs() { - List columnInfos = Arrays.asList( - new ColumnInfos(null, "cust_a", ColumnType.NUMBER, 1, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", null, null, null, null, true), - new ColumnInfos(null, "cust_b", ColumnType.TEXT, null, "var_minP + 2", null, "idB", null, null, null, null, true), - new ColumnInfos(null, "cust_c", ColumnType.ENUM, null, "cust_b + 2", "[\"cust_b\"]", "idC", null, null, null, null, true), - new ColumnInfos(null, "cust_d", ColumnType.NUMBER, 0, "5 + 1", null, "idD", null, null, null, null, true) + List columnInfos = Arrays.asList( + new SpreadsheetColumnInfos(null, "cust_a", ColumnType.NUMBER, 1, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_b", ColumnType.TEXT, null, "var_minP + 2", null, "idB", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_c", ColumnType.ENUM, null, "cust_b + 2", "[\"cust_b\"]", "idC", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_d", ColumnType.NUMBER, 0, "5 + 1", null, "idD", true, null, null, null, null) ); return List.of( @@ -491,11 +491,11 @@ private List createUpdatedSpreadsheetConfigs() { } private List createUpdatedSpreadsheetConfigsWithFilters() { - List columnsConfig1 = Arrays.asList( - new ColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", - "text", "startsWith", "new-prefix", null, true), - new ColumnInfos(null, "updated", ColumnType.TEXT, null, "updated", "[\"updated\"]", "updated", - null, null, null, null, true) + List columnsConfig1 = Arrays.asList( + new SpreadsheetColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", true, + "text", "startsWith", "new-prefix", null), + new SpreadsheetColumnInfos(null, "updated", ColumnType.TEXT, null, "updated", "[\"updated\"]", "updated", true, + null, null, null, null) ); List globalFiltersConfig1 = Arrays.asList( @@ -504,22 +504,22 @@ private List createUpdatedSpreadsheetConfigsWithFilters( GlobalFilterInfos.builder().uuid(UUID.randomUUID()).filterType("country").label("Updated Filter 3").recent(false).build() ); - List columnsConfig2 = Arrays.asList( - new ColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", - "text", "endsWith", "suffix", null, true), - new ColumnInfos(null, "other", ColumnType.NUMBER, 2, "other", "[\"other\"]", "other", - "number", "between", "10,20", null, true) + List columnsConfig2 = Arrays.asList( + new SpreadsheetColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", true, + "text", "endsWith", "suffix", null), + new SpreadsheetColumnInfos(null, "other", ColumnType.NUMBER, 2, "other", "[\"other\"]", "other", true, + "number", "between", "10,20", null) ); List globalFiltersConfig2 = List.of( GlobalFilterInfos.builder().uuid(UUID.randomUUID()).filterType("country").label("Updated Other Filter").recent(false).build() ); - List columnsConfig3 = Arrays.asList( - new ColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", - "text", "contains", "middle", null, true), - new ColumnInfos(null, "third", ColumnType.BOOLEAN, null, "third", "[\"third\"]", "third", - "boolean", "equals", "true", null, true) + List columnsConfig3 = Arrays.asList( + new SpreadsheetColumnInfos(null, "id", ColumnType.TEXT, null, "id", "[\"id\"]", "id", true, + "text", "contains", "middle", null), + new SpreadsheetColumnInfos(null, "third", ColumnType.BOOLEAN, null, "third", "[\"third\"]", "third", true, + "boolean", "equals", "true", null) ); List globalFiltersConfig3 = List.of( diff --git a/src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigIntegrationTest.java b/src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigIntegrationTest.java index a84f1132..4e372167 100644 --- a/src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigIntegrationTest.java +++ b/src/test/java/org/gridsuite/studyconfig/server/SpreadsheetConfigIntegrationTest.java @@ -238,7 +238,7 @@ void testCreateColumn() throws Exception { SpreadsheetConfigInfos config = new SpreadsheetConfigInfos(null, "Battery", SheetType.BATTERY, List.of(), null, List.of(), null); UUID configId = saveAndReturnId(config); - ColumnInfos columnToCreate = new ColumnInfos(null, "new_column", ColumnType.NUMBER, 2, "x + 1", "[\"x\"]", "newId", null, null, null, null, true); + SpreadsheetColumnInfos columnToCreate = new SpreadsheetColumnInfos(null, "new_column", ColumnType.NUMBER, 2, "x + 1", "[\"x\"]", "newId", true, null, null, null, null); MvcResult result = mockMvc.perform(post(URI_SPREADSHEET_CONFIG_GET_PUT + configId + URI_COLUMN_BASE) .content(mapper.writeValueAsString(columnToCreate)) @@ -248,15 +248,15 @@ void testCreateColumn() throws Exception { UUID columnId = mapper.readValue(result.getResponse().getContentAsString(), UUID.class); - ColumnInfos createdColumn = getColumn(configId, columnId); + SpreadsheetColumnInfos createdColumn = getColumn(configId, columnId); assertThat(createdColumn) .usingRecursiveComparison() .ignoringFields("uuid") .isEqualTo(columnToCreate); // Create a column with a filter - ColumnInfos columnWithFilter = new ColumnInfos(null, "new_column_with_filter", ColumnType.NUMBER, 2, "x + 1", "[\"x\"]", "newId", - "text", "equals", "test-value", null, true); + SpreadsheetColumnInfos columnWithFilter = new SpreadsheetColumnInfos(null, "new_column_with_filter", ColumnType.NUMBER, 2, "x + 1", "[\"x\"]", "newId", true, + "text", "equals", "test-value", null); MvcResult resultWithFilter = mockMvc.perform(post(URI_SPREADSHEET_CONFIG_GET_PUT + configId + URI_COLUMN_BASE) .content(mapper.writeValueAsString(columnWithFilter)) @@ -265,7 +265,7 @@ void testCreateColumn() throws Exception { .andReturn(); UUID columnWithFilterId = mapper.readValue(resultWithFilter.getResponse().getContentAsString(), UUID.class); - ColumnInfos createdColumnWithFilter = getColumn(configId, columnWithFilterId); + SpreadsheetColumnInfos createdColumnWithFilter = getColumn(configId, columnWithFilterId); assertThat(createdColumnWithFilter) .usingRecursiveComparison() .ignoringFields("uuid") @@ -280,15 +280,15 @@ void testUpdateColumn() throws Exception { SpreadsheetConfigInfos savedConfig = getSpreadsheetConfig(configId); UUID columnId = savedConfig.columns().get(0).uuid(); - ColumnInfos columnUpdate = new ColumnInfos(columnId, "updated_column", ColumnType.TEXT, null, "new_formula", "[]", "updatedId", - "text", "equals", "updated-value", null, true); + SpreadsheetColumnInfos columnUpdate = new SpreadsheetColumnInfos(columnId, "updated_column", ColumnType.TEXT, null, "new_formula", "[]", "updatedId", true, + "text", "equals", "updated-value", null); mockMvc.perform(put(URI_SPREADSHEET_CONFIG_GET_PUT + configId + URI_COLUMN_BASE + "/" + columnId) .content(mapper.writeValueAsString(columnUpdate)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isNoContent()); - ColumnInfos updatedColumn = getColumn(configId, columnId); + SpreadsheetColumnInfos updatedColumn = getColumn(configId, columnId); assertThat(updatedColumn).isEqualTo(columnUpdate); } @@ -305,7 +305,7 @@ void testDeleteColumn() throws Exception { SpreadsheetConfigInfos configAfterDelete = getSpreadsheetConfig(configId); assertThat(configAfterDelete.columns()) - .extracting(ColumnInfos::uuid) + .extracting(SpreadsheetColumnInfos::uuid) .isNotEmpty() .doesNotContain(columnId); } @@ -324,8 +324,8 @@ void testDuplicateColumn() throws Exception { SpreadsheetConfigInfos configAfterDuplicate = getSpreadsheetConfig(configId); assertThat(configAfterDuplicate.columns()).hasSize(5); - ColumnInfos columnInfos = configAfterDuplicate.columns().get(0); - ColumnInfos duplicatedColumnInfos = configAfterDuplicate.columns().get(1); + SpreadsheetColumnInfos columnInfos = configAfterDuplicate.columns().get(0); + SpreadsheetColumnInfos duplicatedColumnInfos = configAfterDuplicate.columns().get(1); assertThat(columnInfos.uuid()).isNotEqualTo(duplicatedColumnInfos.uuid()); assertEquals(columnInfos.id() + "_1", duplicatedColumnInfos.id()); @@ -356,7 +356,7 @@ void testGetColumn() throws Exception { SpreadsheetConfigInfos savedConfig = getSpreadsheetConfig(configId); UUID columnId = savedConfig.columns().get(0).uuid(); - ColumnInfos column = getColumn(configId, columnId); + SpreadsheetColumnInfos column = getColumn(configId, columnId); assertThat(column).isNotNull(); assertThat(column.uuid()).isEqualTo(columnId); } @@ -368,12 +368,12 @@ void testReorderColumns() throws Exception { // get the saved config to retrieve column UUIDs SpreadsheetConfigInfos savedConfig = getSpreadsheetConfig(configId); - List originalColumns = savedConfig.columns(); + List originalColumns = savedConfig.columns(); assertThat(originalColumns).hasSize(4); // reverse the original order List reorderedColumnIds = originalColumns.stream() - .map(ColumnInfos::uuid) + .map(SpreadsheetColumnInfos::uuid) .collect(Collectors.toList()); Collections.reverse(reorderedColumnIds); @@ -384,7 +384,7 @@ void testReorderColumns() throws Exception { // verify the new order SpreadsheetConfigInfos updatedConfig = getSpreadsheetConfig(configId); - List reorderedColumns = updatedConfig.columns(); + List reorderedColumns = updatedConfig.columns(); assertThat(reorderedColumns).hasSize(originalColumns.size()); @@ -397,10 +397,10 @@ void testReorderColumns() throws Exception { @Test void testUpdateColumnStates() throws Exception { // Create config with multiple columns - List columns = Arrays.asList( - new ColumnInfos(null, "col1", ColumnType.TEXT, null, "formula1", null, "id1", null, null, null, null, true), - new ColumnInfos(null, "col2", ColumnType.NUMBER, 2, "formula2", null, "id2", null, null, null, null, true), - new ColumnInfos(null, "col3", ColumnType.BOOLEAN, null, "formula3", null, "id3", null, null, null, null, false) + List columns = Arrays.asList( + new SpreadsheetColumnInfos(null, "col1", ColumnType.TEXT, null, "formula1", null, "id1", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "col2", ColumnType.NUMBER, 2, "formula2", null, "id2", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "col3", ColumnType.BOOLEAN, null, "formula3", null, "id3", false, null, null, null, null) ); SpreadsheetConfigInfos config = new SpreadsheetConfigInfos(null, "TestConfig", SheetType.BATTERY, columns, null, List.of(), null); @@ -408,7 +408,7 @@ void testUpdateColumnStates() throws Exception { // Get the saved config to retrieve column UUIDs SpreadsheetConfigInfos savedConfig = getSpreadsheetConfig(configId); - List savedColumns = savedConfig.columns(); + List savedColumns = savedConfig.columns(); assertThat(savedColumns).hasSize(3); // Prepare column state updates: reorder and change visibility @@ -426,15 +426,15 @@ void testUpdateColumnStates() throws Exception { // Verify the updates SpreadsheetConfigInfos updatedConfig = getSpreadsheetConfig(configId); - List updatedColumns = updatedConfig.columns(); + List updatedColumns = updatedConfig.columns(); // Check visibility updates - ColumnInfos firstColumn = updatedColumns.stream() + SpreadsheetColumnInfos firstColumn = updatedColumns.stream() .filter(col -> col.uuid().equals(savedColumns.get(0).uuid())) .findFirst().orElseThrow(); assertThat(firstColumn.visible()).isFalse(); - ColumnInfos thirdColumn = updatedColumns.stream() + SpreadsheetColumnInfos thirdColumn = updatedColumns.stream() .filter(col -> col.uuid().equals(savedColumns.get(2).uuid())) .findFirst().orElseThrow(); assertThat(thirdColumn.visible()).isTrue(); @@ -597,7 +597,7 @@ void testResetFiltersForSpreadsheetConfig() throws Exception { // Initial config should have filters set SpreadsheetConfigInfos initialConfig = getSpreadsheetConfig(configId); assertThat(initialConfig.globalFilters()).hasSize(2); - assertThat(initialConfig.columns().getFirst()).hasFieldOrPropertyWithValue("filterValue", "test-value"); + assertThat(initialConfig.columns().getFirst().columnFilterInfos()).hasFieldOrPropertyWithValue("filterValue", "test-value"); // Call the endpoint to reset the filters mockMvc.perform(put(URI_SPREADSHEET_CONFIG_GET_PUT + configId + "/reset-filters") @@ -607,7 +607,7 @@ void testResetFiltersForSpreadsheetConfig() throws Exception { // Verify the filters (global or column based) were reset SpreadsheetConfigInfos updatedConfig = getSpreadsheetConfig(configId); assertThat(updatedConfig.globalFilters()).isEmpty(); - assertThat(updatedConfig.columns().getFirst()).hasFieldOrPropertyWithValue("filterValue", null); + assertThat(updatedConfig.columns().getFirst().columnFilterInfos()).hasFieldOrPropertyWithValue("filterValue", null); } @Test @@ -623,44 +623,44 @@ void testSetGlobalFiltersToNonExistentConfig() throws Exception { .andExpect(status().isNotFound()); } - private List createColumns() { + private List createColumns() { return Arrays.asList( - new ColumnInfos(null, "cust_a", ColumnType.BOOLEAN, null, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", null, null, null, null, true), - new ColumnInfos(null, "cust_b", ColumnType.NUMBER, 0, "var_minP + 1", null, "idB", null, null, null, null, true), - new ColumnInfos(null, "cust_c", ColumnType.NUMBER, 2, "cust_b + 1", "[\"cust_b\"]", "idC", null, null, null, null, true), - new ColumnInfos(null, "cust_d", ColumnType.TEXT, null, "5 + 2", null, "idD", null, null, null, null, true) + new SpreadsheetColumnInfos(null, "cust_a", ColumnType.BOOLEAN, null, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_b", ColumnType.NUMBER, 0, "var_minP + 1", null, "idB", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_c", ColumnType.NUMBER, 2, "cust_b + 1", "[\"cust_b\"]", "idC", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_d", ColumnType.TEXT, null, "5 + 2", null, "idD", true, null, null, null, null) ); } - private List createColumnsWithFilters() { + private List createColumnsWithFilters() { return Arrays.asList( - new ColumnInfos(null, "cust_a", ColumnType.BOOLEAN, null, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", - "text", "equals", "test-value", null, true), - new ColumnInfos(null, "cust_b", ColumnType.NUMBER, 0, "var_minP + 1", null, "idB", - "number", "greaterThan", "100", 0.5, true), - new ColumnInfos(null, "cust_c", ColumnType.NUMBER, 2, "cust_b + 1", "[\"cust_b\"]", "idC", - "text", "startsWith", "prefix", null, true), - new ColumnInfos(null, "cust_d", ColumnType.TEXT, null, "5 + 2", null, "idD", - null, null, null, null, true) + new SpreadsheetColumnInfos(null, "cust_a", ColumnType.BOOLEAN, null, "cust_b + cust_c", "[\"cust_b\", \"cust_c\"]", "idA", true, + "text", "equals", "test-value", null), + new SpreadsheetColumnInfos(null, "cust_b", ColumnType.NUMBER, 0, "var_minP + 1", null, "idB", true, + "number", "greaterThan", "100", 0.5), + new SpreadsheetColumnInfos(null, "cust_c", ColumnType.NUMBER, 2, "cust_b + 1", "[\"cust_b\"]", "idC", true, + "text", "startsWith", "prefix", null), + new SpreadsheetColumnInfos(null, "cust_d", ColumnType.TEXT, null, "5 + 2", null, "idD", true, + null, null, null, null) ); } - private List createUpdatedColumns() { + private List createUpdatedColumns() { return Arrays.asList( - new ColumnInfos(null, "cust_x", ColumnType.BOOLEAN, null, "cust_y * 2", "[\"cust_y\"]", "idX", null, null, null, null, true), - new ColumnInfos(null, "cust_y", ColumnType.NUMBER, 1, "var_maxP - 1", null, "idY", null, null, null, null, true), - new ColumnInfos(null, "cust_z", ColumnType.NUMBER, 0, "cust_x / 2", "[\"cust_x\"]", "idZ", null, null, null, null, true) + new SpreadsheetColumnInfos(null, "cust_x", ColumnType.BOOLEAN, null, "cust_y * 2", "[\"cust_y\"]", "idX", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_y", ColumnType.NUMBER, 1, "var_maxP - 1", null, "idY", true, null, null, null, null), + new SpreadsheetColumnInfos(null, "cust_z", ColumnType.NUMBER, 0, "cust_x / 2", "[\"cust_x\"]", "idZ", true, null, null, null, null) ); } - private List createUpdatedColumnsWithFilters() { + private List createUpdatedColumnsWithFilters() { return Arrays.asList( - new ColumnInfos(null, "cust_x", ColumnType.BOOLEAN, null, "cust_y * 2", "[\"cust_y\"]", "idX", - "text", "contains", "updated-value", null, true), - new ColumnInfos(null, "cust_y", ColumnType.NUMBER, 1, "var_maxP - 1", null, "idY", - "number", "lessThan", "50", 0.1, true), - new ColumnInfos(null, "cust_z", ColumnType.NUMBER, 0, "cust_x / 2", "[\"cust_x\"]", "idZ", - null, null, null, null, true) // No filter on this column + new SpreadsheetColumnInfos(null, "cust_x", ColumnType.BOOLEAN, null, "cust_y * 2", "[\"cust_y\"]", "idX", true, + "text", "contains", "updated-value", null), + new SpreadsheetColumnInfos(null, "cust_y", ColumnType.NUMBER, 1, "var_maxP - 1", null, "idY", true, + "number", "lessThan", "50", 0.1), + new SpreadsheetColumnInfos(null, "cust_z", ColumnType.NUMBER, 0, "cust_x / 2", "[\"cust_x\"]", "idZ", true, + null, null, null, null) // No filter on this column ); } @@ -722,11 +722,11 @@ private UUID saveAndReturnId(SpreadsheetConfigInfos config) { return spreadsheetConfigService.createSpreadsheetConfig(config); } - private ColumnInfos getColumn(UUID configId, UUID columnId) throws Exception { + private SpreadsheetColumnInfos getColumn(UUID configId, UUID columnId) throws Exception { MvcResult result = mockMvc.perform(get(URI_SPREADSHEET_CONFIG_GET_PUT + configId + URI_COLUMN_BASE + "/" + columnId)) .andExpect(status().isOk()) .andReturn(); - return mapper.readValue(result.getResponse().getContentAsString(), ColumnInfos.class); + return mapper.readValue(result.getResponse().getContentAsString(), SpreadsheetColumnInfos.class); } }