Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<sonar.organization>gridsuite</sonar.organization>
<sonar.projectKey>org.gridsuite:network-modification-server</sonar.projectKey>
<!-- TODO network-modification.version remove when upgrading gridsuite dependencies -->
<network-modification.version>0.45.0</network-modification.version>
<network-modification.version>0.46.0-SNAPSHOT</network-modification.version>
<!-- FIXME: powsybl-network-store modules'version is overloaded in the dependencies section.The overloads and this property below have to be removed at next powsybl-ws-dependencies.version upgrade -->
<powsybl-network-store.version>1.31.0</powsybl-network-store.version>
<powsybl-balances-adjustment.version>2.14.1</powsybl-balances-adjustment.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
import com.powsybl.network.store.client.PreloadingStrategy;
import lombok.NonNull;
import org.apache.commons.lang3.StringUtils;
import org.gridsuite.filter.AbstractFilter;
import org.gridsuite.modification.ModificationType;
import org.gridsuite.modification.NetworkModificationException;
import org.gridsuite.modification.dto.GenerationDispatchInfos;
import org.gridsuite.modification.dto.ModificationInfos;
import org.gridsuite.modification.server.NetworkModificationServerException;
import org.gridsuite.modification.server.dto.*;
Expand Down Expand Up @@ -69,16 +71,25 @@ public class NetworkModificationService {

private final ModificationApplicationInfosService applicationInfosService;

private final FilterService filterService;

static final String NETWORK_UUID = "networkUuid.keyword";
static final String CREATED_EQUIPMENT_IDS = "createdEquipmentIds.fullascii";
static final String MODIFIED_EQUIPMENT_IDS = "modifiedEquipmentIds.fullascii";
static final String DELETED_EQUIPMENT_IDS = "deletedEquipmentIds.fullascii";
private final ModificationRepository modificationRepository;
private static final int PAGE_MAX_SIZE = 500;

public NetworkModificationService(NetworkStoreService networkStoreService, NetworkModificationRepository networkModificationRepository,
EquipmentInfosService equipmentInfosService, NotificationService notificationService,
NetworkModificationApplicator applicationService, ObjectMapper objectMapper, ModificationApplicationInfosService applicationInfosService, ElasticsearchOperations elasticsearchOperations, ModificationRepository modificationRepository) {
public NetworkModificationService(NetworkStoreService networkStoreService,
NetworkModificationRepository networkModificationRepository,
EquipmentInfosService equipmentInfosService,
NotificationService notificationService,
NetworkModificationApplicator applicationService,
ObjectMapper objectMapper,
ModificationApplicationInfosService applicationInfosService,
ElasticsearchOperations elasticsearchOperations,
ModificationRepository modificationRepository,
FilterService filterService) {
this.networkStoreService = networkStoreService;
this.networkModificationRepository = networkModificationRepository;
this.equipmentInfosService = equipmentInfosService;
Expand All @@ -88,6 +99,7 @@ public NetworkModificationService(NetworkStoreService networkStoreService, Netwo
this.applicationInfosService = applicationInfosService;
this.elasticsearchOperations = elasticsearchOperations;
this.modificationRepository = modificationRepository;
this.filterService = filterService;
}

public List<UUID> getModificationGroups() {
Expand Down Expand Up @@ -123,9 +135,44 @@ public List<ModificationInfos> getNetworkModificationsFromComposite(UUID composi
}
}

private void checkGenerationDispatchFilters(GenerationDispatchInfos generationDispatchInfos) {
// set filter name to null for non existing filters
Map<UUID, String> filterNamesByUuid = new LinkedHashMap<>();
generationDispatchInfos.getGeneratorsWithoutOutage().forEach(filterInfos -> filterNamesByUuid.put(filterInfos.getId(), filterInfos.getName()));
generationDispatchInfos.getGeneratorsWithFixedSupply().forEach(filterInfos -> filterNamesByUuid.put(filterInfos.getId(), filterInfos.getName()));
generationDispatchInfos.getGeneratorsFrequencyReserve().forEach(frequencyReserveInfos ->
frequencyReserveInfos.getGeneratorsFilters().forEach(filterInfos -> filterNamesByUuid.put(filterInfos.getId(), filterInfos.getName()))
);
if (!filterNamesByUuid.isEmpty()) {
List<AbstractFilter> filters = filterService.getFilters(new ArrayList<>(filterNamesByUuid.keySet()));
Set<UUID> validFilters = filters.stream().map(AbstractFilter::getId).collect(Collectors.toSet());
Set<UUID> missingFilters = filterNamesByUuid.keySet().stream().filter(filterId -> !validFilters.contains(filterId)).collect(Collectors.toSet());
generationDispatchInfos.getGeneratorsWithoutOutage().forEach(filterInfos -> {
if (missingFilters.contains(filterInfos.getId())) {
filterInfos.setName(null);
}
});
generationDispatchInfos.getGeneratorsWithFixedSupply().forEach(filterInfos -> {
if (missingFilters.contains(filterInfos.getId())) {
filterInfos.setName(null);
}
});
generationDispatchInfos.getGeneratorsFrequencyReserve().forEach(frequencyReserveInfos ->
frequencyReserveInfos.getGeneratorsFilters().forEach(filterInfos -> {
if (missingFilters.contains(filterInfos.getId())) {
filterInfos.setName(null);
}
}));
}
}

@Transactional(readOnly = true)
public ModificationInfos getNetworkModification(UUID networkModificationUuid) {
return networkModificationRepository.getModificationInfo(networkModificationUuid);
ModificationInfos modificationInfos = networkModificationRepository.getModificationInfo(networkModificationUuid);
if (modificationInfos instanceof GenerationDispatchInfos) {
checkGenerationDispatchFilters((GenerationDispatchInfos) modificationInfos);
}
return modificationInfos;
}

public Integer getNetworkModificationsCount(UUID groupUuid, boolean stashed) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ void testGenerationDispatchWithMaxPReduction() throws Exception {
assertLogMessageWithoutRank("Marginal cost: 150.0", "network.modification.MaxUsedMarginalCost", reportService);
assertLogMessageWithoutRank("The supply-demand balance could be met", "network.modification.SupplyDemandBalanceCouldBeMet", reportService);
assertLogMessageWithoutRank("Sum of generator active power setpoints in WEST region: 330.0 MW (NUCLEAR: 0.0 MW, THERMAL: 0.0 MW, HYDRO: 330.0 MW, WIND AND SOLAR: 0.0 MW, OTHER: 0.0 MW).", "network.modification.SumGeneratorActivePower", reportService);
wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(filters.stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubId, PATH, handleQueryParams(filters.stream().map(AbstractFilter::getId).collect(Collectors.toList())), false, 2);
}

@Test
Expand Down Expand Up @@ -341,6 +341,11 @@ void testGenerationDispatchGeneratorsWithFixedSupply() throws Exception {
.withBody(mapper.writeValueAsString(filtersForFixedSupply))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();

UUID stubIdForGetFilters = wireMockServer.stubFor(WireMock.get(getPath(false) + FILTER_ID_1 + "," + FILTER_ID_2 + "," + FILTER_ID_3 + "," + FILTER_ID_4)
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(getFilters1234()))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();

String modificationJson = getJsonBody(modification, null);
mockMvc.perform(post(getNetworkModificationUri()).content(modificationJson).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk());
Expand Down Expand Up @@ -380,6 +385,7 @@ void testGenerationDispatchGeneratorsWithFixedSupply() throws Exception {
assertLogMessageWithoutRank("The supply-demand balance could be met", "network.modification.SupplyDemandBalanceCouldBeMet", reportService);
assertLogMessageWithoutRank("Sum of generator active power setpoints in EAST region: 330.0 MW (NUCLEAR: 0.0 MW, THERMAL: 0.0 MW, HYDRO: 330.0 MW, WIND AND SOLAR: 0.0 MW, OTHER: 0.0 MW).", "network.modification.SumGeneratorActivePower", reportService);

wireMockUtils.verifyGetRequest(stubIdForGetFilters, PATH, handleQueryParams(getFilters1234().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubIdForPmaxReduction, PATH, handleQueryParams(filtersForPmaxReduction.stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubIdForFixedSupply, PATH, handleQueryParams(filtersForFixedSupply.stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
}
Expand Down Expand Up @@ -413,6 +419,16 @@ private static List<AbstractFilter> getGeneratorsFrequencyReserveFilter6() {
return List.of(getFilter(FILTER_ID_6, List.of(getIdentifiableAttributes(TEST1_ID))));
}

private static List<AbstractFilter> getFilters1234() {
return List.of(getFilter(FILTER_ID_1, List.of()), getFilter(FILTER_ID_2, List.of()), getFilter(FILTER_ID_3, List.of()),
getFilter(FILTER_ID_4, List.of()));
}

private static List<AbstractFilter> getFilters123456() {
return List.of(getFilter(FILTER_ID_1, List.of()), getFilter(FILTER_ID_2, List.of()), getFilter(FILTER_ID_3, List.of()),
getFilter(FILTER_ID_4, List.of()), getFilter(FILTER_ID_5, List.of()), getFilter(FILTER_ID_6, List.of()));
}

@Test
void testGenerationDispatchWithFrequencyReserve() throws Exception {
ModificationInfos modification = buildModification();
Expand All @@ -437,6 +453,10 @@ void testGenerationDispatchWithFrequencyReserve() throws Exception {
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(getGeneratorsFrequencyReserveFilter6()))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();
UUID stubIdForGetFilters = wireMockServer.stubFor(WireMock.get(getPath(false) + FILTER_ID_1 + "," + FILTER_ID_2 + "," + FILTER_ID_3 + "," + FILTER_ID_4 + "," + FILTER_ID_5 + "," + FILTER_ID_6)
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(getFilters123456()))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();

String modificationJson = getJsonBody(modification, null);
mockMvc.perform(post(getNetworkModificationUri()).content(modificationJson).contentType(MediaType.APPLICATION_JSON))
Expand Down Expand Up @@ -472,6 +492,7 @@ void testGenerationDispatchWithFrequencyReserve() throws Exception {
assertLogMessageWithoutRank("The supply-demand balance could be met", "network.modification.SupplyDemandBalanceCouldBeMet", reportService);
assertLogMessageWithoutRank("Sum of generator active power setpoints in WEST region: 330.0 MW (NUCLEAR: 0.0 MW, THERMAL: 0.0 MW, HYDRO: 330.0 MW, WIND AND SOLAR: 0.0 MW, OTHER: 0.0 MW).", "network.modification.SumGeneratorActivePower", reportService);

wireMockUtils.verifyGetRequest(stubIdForGetFilters, PATH, handleQueryParams(getFilters123456().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubIdForPmaxReduction, PATH, handleQueryParams(getGeneratorsWithoutOutageFilters123().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubIdForFrequencyReserve1, PATH, handleQueryParams(getGeneratorsFrequencyReserveFilters45().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubIdForFrequencyReserve2, PATH, handleQueryParams(getGeneratorsFrequencyReserveFilter6().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
Expand Down Expand Up @@ -597,6 +618,10 @@ void testGenerationDispatchWithMaxValueLessThanMinP() throws Exception {
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(getGeneratorsFrequencyReserveFilter6()))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();
UUID stubIdForGetFilters = wireMockServer.stubFor(WireMock.get(getPath(false) + FILTER_ID_1 + "," + FILTER_ID_2 + "," + FILTER_ID_3 + "," + FILTER_ID_4 + "," + FILTER_ID_5 + "," + FILTER_ID_6)
.willReturn(WireMock.ok()
.withBody(mapper.writeValueAsString(getFilters123456()))
.withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))).getId();

String modificationJson = getJsonBody(modification, null);
MvcResult mvcResult = mockMvc.perform(post(getNetworkModificationUri()).content(modificationJson).contentType(MediaType.APPLICATION_JSON))
Expand Down Expand Up @@ -628,6 +653,7 @@ void testGenerationDispatchWithMaxValueLessThanMinP() throws Exception {
assertLogMessageWithoutRank("The supply-demand balance could be met", "network.modification.SupplyDemandBalanceCouldBeMet", reportService);
assertLogMessageWithoutRank("Sum of generator active power setpoints in NORTH region: 330.0 MW (NUCLEAR: 0.0 MW, THERMAL: 0.0 MW, HYDRO: 330.0 MW, WIND AND SOLAR: 0.0 MW, OTHER: 0.0 MW).", "network.modification.SumGeneratorActivePower", reportService);

wireMockUtils.verifyGetRequest(stubIdForGetFilters, PATH, handleQueryParams(getFilters123456().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubIdForPmaxReduction, PATH, handleQueryParams(getGeneratorsWithoutOutageFilters123().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubIdForFrequencyReserve1, PATH, handleQueryParams(getGeneratorsFrequencyReserveFilters45().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
wireMockUtils.verifyGetRequest(stubIdForFrequencyReserve2, PATH, handleQueryParams(getGeneratorsFrequencyReserveFilter6().stream().map(AbstractFilter::getId).collect(Collectors.toList())), false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ public WireMockUtils(WireMockServer wireMockServer) {
}

public void verifyGetRequest(UUID stubId, String urlPath, Map<String, StringValuePattern> queryParams, boolean regexMatching) {
verifyGetRequest(stubId, urlPath, queryParams, regexMatching, 1);
}

public void verifyGetRequest(UUID stubId, String urlPath, Map<String, StringValuePattern> queryParams, boolean regexMatching, int nbRequests) {
RequestPatternBuilder requestBuilder = regexMatching ? WireMock.getRequestedFor(WireMock.urlPathMatching(urlPath)) : WireMock.getRequestedFor(WireMock.urlPathEqualTo(urlPath));
queryParams.forEach(requestBuilder::withQueryParam);
wireMockServer.verify(1, requestBuilder);
removeRequestForStub(stubId, 1);
wireMockServer.verify(nbRequests, requestBuilder);
removeRequestForStub(stubId, nbRequests);
}

private void removeRequestForStub(UUID stubId, int nbRequests) {
Expand Down
Loading