diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index d2390fdf..4683169 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: set up Docker buildx uses: docker/setup-buildx-action@v3 diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 98b6b07..18b1183 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -15,7 +15,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: pip install run: pip install -r requirements.txt -r requirements-dev.txt @@ -33,7 +33,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: pip install run: pip install -r requirements.txt -r requirements-dev.txt @@ -65,7 +65,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: pip install run: pip install -r requirements.txt -r requirements-dev.txt diff --git a/requirements.txt b/requirements.txt index 0ecc0ed..5fc5be3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,7 +19,7 @@ openpyxl~=3.1.5 opening-hours-py~=1.1.5 kombu~=5.5.4 lxml~=6.0.2 -parkapi-sources~=0.31.0 +parkapi-sources~=0.32.0 isodate~=0.7.2 shapely~=2.1.2 urllib3~=2.5.0 diff --git a/webapp/admin_rest_api/parking_spots/parking_spot_schema.py b/webapp/admin_rest_api/parking_spots/parking_spot_schema.py index 60b62bd..bbe1588 100644 --- a/webapp/admin_rest_api/parking_spots/parking_spot_schema.py +++ b/webapp/admin_rest_api/parking_spots/parking_spot_schema.py @@ -23,6 +23,7 @@ properties={ 'uid': StringField(minLength=1, maxLength=256), 'name': StringField(minLength=1, maxLength=256, required=False, nullable=True), + 'parking_site_uid': StringField(minLength=1, maxLength=256, required=False), 'address': StringField(maxLength=256, required=False, nullable=True), 'purpose': EnumField(enum=PurposeType, default=PurposeType.CAR, required=False), 'type': EnumField(enum=ParkingSpotType, required=False, nullable=True), diff --git a/webapp/dependencies.py b/webapp/dependencies.py index 5b5ad74..69563d7 100644 --- a/webapp/dependencies.py +++ b/webapp/dependencies.py @@ -171,6 +171,7 @@ def get_generic_parking_site_import_service(self) -> GenericParkingSiteImportSer def get_generic_parking_spot_import_service(self) -> GenericParkingSpotImportService: return GenericParkingSpotImportService( source_repository=self.get_source_repository(), + parking_site_repository=self.get_parking_site_repository(), parking_spot_repository=self.get_parking_spot_repository(), **self.get_base_service_dependencies(), ) diff --git a/webapp/models/parking_site.py b/webapp/models/parking_site.py index d54fb36..d777a7b 100644 --- a/webapp/models/parking_site.py +++ b/webapp/models/parking_site.py @@ -80,7 +80,7 @@ class ParkingSite(BaseModel): parking_spots: Mapped[list['ParkingSpot']] = relationship( 'ParkingSpot', back_populates='parking_site', - cascade='all, delete-orphan', + cascade='all', ) restrictions: Mapped[list['ParkingRestriction']] = relationship( 'ParkingRestriction', diff --git a/webapp/services/import_service/generic/generic_import_runner.py b/webapp/services/import_service/generic/generic_import_runner.py index ad78b10..692a2d5 100644 --- a/webapp/services/import_service/generic/generic_import_runner.py +++ b/webapp/services/import_service/generic/generic_import_runner.py @@ -30,6 +30,8 @@ def __init__( self.generic_import_service = generic_import_service def start(self): + if self.config_helper.get('PREVENT_AUTO_IMPORT'): + return for source_uid in self.generic_import_service.park_api_sources.converter_by_uid.keys(): # Don't try to pull push-endpoints if not isinstance( diff --git a/webapp/services/import_service/generic/generic_parking_site_import_service.py b/webapp/services/import_service/generic/generic_parking_site_import_service.py index ba9b983..942dd38 100644 --- a/webapp/services/import_service/generic/generic_parking_site_import_service.py +++ b/webapp/services/import_service/generic/generic_parking_site_import_service.py @@ -124,23 +124,24 @@ def save_static_or_combined_parking_site_input( self.set_related_objects(parking_site_input, parking_site) # Legacy mapping - for restriction_input in parking_site_input.restrictions: - if restriction_input.type not in RESTRICTION_MAPPING: - continue - setattr(parking_site, RESTRICTION_MAPPING[restriction_input.type], restriction_input.capacity) - - # Don't overwrite realtime data in case of static data - if isinstance(parking_site_input, CombinedParkingSiteInput): - setattr( - parking_site, - f'realtime_{RESTRICTION_MAPPING[restriction_input.type]}', - restriction_input.realtime_capacity, - ) - setattr( - parking_site, - f'realtime_free_{RESTRICTION_MAPPING[restriction_input.type]}', - restriction_input.realtime_free_capacity, - ) + if parking_site_input.restrictions: + for restriction_input in parking_site_input.restrictions: + if restriction_input.type not in RESTRICTION_MAPPING: + continue + setattr(parking_site, RESTRICTION_MAPPING[restriction_input.type], restriction_input.capacity) + + # Don't overwrite realtime data in case of static data + if isinstance(parking_site_input, CombinedParkingSiteInput): + setattr( + parking_site, + f'realtime_{RESTRICTION_MAPPING[restriction_input.type]}', + restriction_input.realtime_capacity, + ) + setattr( + parking_site, + f'realtime_free_{RESTRICTION_MAPPING[restriction_input.type]}', + restriction_input.realtime_free_capacity, + ) if parking_site_input.group_uid: try: diff --git a/webapp/services/import_service/generic/generic_parking_spot_import_service.py b/webapp/services/import_service/generic/generic_parking_spot_import_service.py index 70ee254..08c76c7 100644 --- a/webapp/services/import_service/generic/generic_parking_spot_import_service.py +++ b/webapp/services/import_service/generic/generic_parking_spot_import_service.py @@ -15,6 +15,7 @@ from webapp.models import ParkingSpot, Source from webapp.models.source import SourceStatus from webapp.repositories import ( + ParkingSiteRepository, ParkingSpotRepository, SourceRepository, ) @@ -27,12 +28,19 @@ class GenericParkingSpotImportService(GenericBaseImportService): source_repository: SourceRepository + parking_site_repository: ParkingSiteRepository parking_spot_repository: ParkingSpotRepository park_api_sources: ParkAPISources - def __init__(self, *args, parking_spot_repository: ParkingSpotRepository, **kwargs): + def __init__( + self, + *args, + parking_site_repository: ParkingSiteRepository, + parking_spot_repository: ParkingSpotRepository, + **kwargs, + ): super().__init__(*args, **kwargs) - + self.parking_site_repository = parking_site_repository self.parking_spot_repository = parking_spot_repository def handle_static_import_results( @@ -103,11 +111,24 @@ def save_static_or_combined_parking_spot_input( 'external_identifiers', 'restrictions', 'tags', + 'parking_site_uid', ]: continue setattr(parking_spot, key, value) - self.set_related_objects(parking_spot_input, parking_spot) + self.set_related_objects(parking_spot_input, parking_spot) + + if parking_spot_input.parking_site_uid: + try: + parking_site = self.parking_site_repository.fetch_parking_site_by_source_id_and_external_uid( + source_id=source.id, + original_uid=parking_spot_input.parking_site_uid, + ) + parking_spot.parking_site = parking_site + except ObjectNotFoundException: + parking_spot.parking_site_id = None + else: + parking_spot.parking_site_id = None self.parking_spot_repository.save_parking_spot(parking_spot) diff --git a/webapp/shared/parking_spot/parking_spot_schema.py b/webapp/shared/parking_spot/parking_spot_schema.py index cea17d0..7410ef3 100644 --- a/webapp/shared/parking_spot/parking_spot_schema.py +++ b/webapp/shared/parking_spot/parking_spot_schema.py @@ -89,6 +89,8 @@ }, ) + parking_spot_example = {} + parking_spot_component = Schema('ParkingSpot', parking_spot_schema, parking_spot_example)