From 4201e88a316b8c678e2a3004dfd703eeef10c01d Mon Sep 17 00:00:00 2001 From: mabw-rte <41002227+mabw-rte@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:59:20 +0100 Subject: [PATCH] fix(api-study): check area duplicates on creation (#1964) --- antarest/core/exceptions.py | 8 ++++++++ antarest/study/business/area_management.py | 12 ++++++++++-- tests/integration/test_integration.py | 19 +++++++++++-------- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/antarest/core/exceptions.py b/antarest/core/exceptions.py index 9a2230c1d1..cada3a5f5d 100644 --- a/antarest/core/exceptions.py +++ b/antarest/core/exceptions.py @@ -253,6 +253,14 @@ def __init__(self, *area_ids: str) -> None: super().__init__(HTTPStatus.NOT_FOUND, msg) +class DuplicateAreaName(HTTPException): + """Exception raised when trying to create an area with an already existing name.""" + + def __init__(self, area_name: str) -> None: + msg = f"Area '{area_name}' already exists and could not be created" + super().__init__(HTTPStatus.CONFLICT, msg) + + class DistrictNotFound(HTTPException): def __init__(self, *district_ids: str) -> None: count = len(district_ids) diff --git a/antarest/study/business/area_management.py b/antarest/study/business/area_management.py index 369b5a96ad..544f18d8cf 100644 --- a/antarest/study/business/area_management.py +++ b/antarest/study/business/area_management.py @@ -5,7 +5,7 @@ from pydantic import BaseModel -from antarest.core.exceptions import LayerNotAllowedToBeDeleted, LayerNotFound +from antarest.core.exceptions import DuplicateAreaName, LayerNotAllowedToBeDeleted, LayerNotFound from antarest.study.business.utils import execute_or_add_commands from antarest.study.model import Patch, PatchArea, PatchCluster, RawStudy, Study from antarest.study.repository import StudyMetadataRepository @@ -318,12 +318,20 @@ def remove_layer(self, study: RawStudy, layer_id: str) -> None: def create_area(self, study: Study, area_creation_info: AreaCreationDTO) -> AreaInfoDTO: file_study = self.storage_service.get_storage(study).get_raw(study) + + # check if area already exists + area_id = transform_name_to_id(area_creation_info.name) + if area_id in set(file_study.config.areas): + raise DuplicateAreaName(area_creation_info.name) + + # Create area and apply changes in the study command = CreateArea( area_name=area_creation_info.name, command_context=self.storage_service.variant_study_service.command_factory.command_context, ) execute_or_add_commands(study, file_study, [command], self.storage_service) - area_id = transform_name_to_id(area_creation_info.name) + + # Update metadata patch = self.patch_service.get(study) patch.areas = patch.areas or {} patch.areas[area_id] = area_creation_info.metadata or PatchArea() diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index 1dc1b385ae..c927e576af 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -9,7 +9,7 @@ from antarest.core.model import PublicMode from antarest.launcher.model import LauncherLoadDTO from antarest.study.business.adequacy_patch_management import PriceTakingOrder -from antarest.study.business.area_management import AreaType, LayerInfoDTO +from antarest.study.business.area_management import LayerInfoDTO from antarest.study.business.areas.properties_management import AdequacyPatchMode from antarest.study.business.areas.renewable_management import TimeSeriesInterpretation from antarest.study.business.general_management import Mode @@ -420,23 +420,26 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: headers=admin_headers, json={ "name": "area 1", - "type": AreaType.AREA.value, + "type": "AREA", "metadata": {"country": "FR", "tags": ["a"]}, }, ) + assert res.status_code == 200, res.json() + + # Test area creation with duplicate name res = client.post( f"/v1/studies/{study_id}/areas", headers=admin_headers, json={ - "name": "area 1", - "type": AreaType.AREA.value, + "name": "Area 1", # Same name but with different case + "type": "AREA", "metadata": {"country": "FR"}, }, ) - assert res.status_code == 500 + assert res.status_code == 409, res.json() assert res.json() == { - "description": "Area 'area 1' already exists and could not be created", - "exception": "CommandApplicationError", + "description": "Area 'Area 1' already exists and could not be created", + "exception": "DuplicateAreaName", } client.post( @@ -444,7 +447,7 @@ def test_area_management(client: TestClient, admin_access_token: str, study_id: headers=admin_headers, json={ "name": "area 2", - "type": AreaType.AREA.value, + "type": "AREA", "metadata": {"country": "DE"}, }, )