diff --git a/.sanitizerconfig b/.sanitizerconfig index 5d086244..8cef9de6 100644 --- a/.sanitizerconfig +++ b/.sanitizerconfig @@ -145,7 +145,7 @@ strategy: normalized_reg_num: parkkihubi.registration_number operator_id: null event_area_id: null - registration_number: parkkihubi.registration_number + registration_number: parkkihubi.registration_number time_end: null time_start: null location_gk25fin: null @@ -168,6 +168,7 @@ strategy: time_period_time_end: null time_period_days_of_week: null description: null + is_test: null parkings_eventareastatistics: id: null created_at: null @@ -175,7 +176,7 @@ strategy: event_area_id: null total_parking_charges: null total_parking_income: null - total_parking_count: null + total_parking_count: null parkings_parkingcheck: allowed: null created_at: null @@ -187,7 +188,7 @@ strategy: registration_number: parkkihubi.registration_number result: null time: null - time_overridden: null + time_overridden: null parkings_parkingterminal: created_at: null domain_id: null diff --git a/parkings/admin.py b/parkings/admin.py index 87f7ed12..8380eeb2 100644 --- a/parkings/admin.py +++ b/parkings/admin.py @@ -86,8 +86,8 @@ def __init__(self, *args, **kwargs): class EventAreaAdmin(WithAreaField, OSMGeoAdmin): form = EventAreaForm area_scale = 1 - list_display = ['id', 'is_active', 'origin_id', 'domain', 'time_start', 'time_end', 'time_period_time_start', - 'time_period_time_end', 'days_of_week', 'price', 'price_unit_length', + list_display = ['id', 'is_active', 'is_test', 'origin_id', 'domain', 'time_start', 'time_end', + 'time_period_time_start', 'time_period_time_end', 'days_of_week', 'price', 'price_unit_length', 'capacity_estimate', 'estimated_capacity', 'area', 'overlapping_parking_areas'] list_filter = ['domain'] ordering = ('origin_id',) @@ -106,7 +106,10 @@ def save_related(self, request, form, formsets, change): form.instance.parking_areas.add(parking_area) def has_delete_permission(self, request, obj=None): - return False + if obj is None: # + return super().has_delete_permission(request, obj) + # Allow deletion only if is_test is True + return obj.is_test @admin.register(EventParking) diff --git a/parkings/api/public/event_area_total_statistics.py b/parkings/api/public/event_area_total_statistics.py index faef26ff..ca05dfbb 100644 --- a/parkings/api/public/event_area_total_statistics.py +++ b/parkings/api/public/event_area_total_statistics.py @@ -25,4 +25,4 @@ class PublicAPIEventAreaTotalStatisticsViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [permissions.AllowAny] serializer_class = EventAreaTotalStatisticsSerializer pagination_class = Pagination - queryset = EventAreaStatistics.objects.all().order_by('-created_at') + queryset = EventAreaStatistics.objects.filter(event_area__is_test=False).order_by('-created_at') diff --git a/parkings/migrations/0065_eventarea_is_test.py b/parkings/migrations/0065_eventarea_is_test.py new file mode 100644 index 00000000..a699900c --- /dev/null +++ b/parkings/migrations/0065_eventarea_is_test.py @@ -0,0 +1,19 @@ +# Generated by Django 4.2.8 on 2024-06-05 13:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('parkings', '0064_alter_archivedparking_domain_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='eventarea', + name='is_test', + field=models.BooleanField( + default=False, help_text='if set to True the event area is ment only for testing purposes, can be deleted and is not serialized.', verbose_name='is test'), + ), + ] diff --git a/parkings/models/event_area.py b/parkings/models/event_area.py index f8156fc1..36c45331 100644 --- a/parkings/models/event_area.py +++ b/parkings/models/event_area.py @@ -26,7 +26,7 @@ def get_active_queryset(self): Q(time_period_time_end__gte=now) & Q(time_period_time_start__lte=now) & Q( time_period_days_of_week__contains=[iso_weekday]) ) - return qs.order_by('origin_id') + return qs.filter(is_test=False).order_by('origin_id') class EventArea(AbstractParkingArea): @@ -68,7 +68,9 @@ class EventArea(AbstractParkingArea): null=True, blank=True, default=list) description = models.TextField(null=True, blank=True, verbose_name=_('description')) - + is_test = models.BooleanField(default=False, verbose_name=_('is test'), help_text=_( + 'if set to True the event area is ment only for testing purposes, can be deleted and' + ' is not visible in the public API.')) objects = EventAreaQuerySet.as_manager() @property diff --git a/parkings/signals.py b/parkings/signals.py index f99e275c..8ebd7036 100644 --- a/parkings/signals.py +++ b/parkings/signals.py @@ -2,11 +2,11 @@ from math import ceil from django.db import transaction -from django.db.models.signals import post_delete, post_save +from django.db.models.signals import post_delete, post_save, pre_delete from django.dispatch import receiver from django.utils import timezone -from parkings.models import EventParking +from parkings.models import EventArea, EventAreaStatistics, EventParking @transaction.atomic @@ -42,3 +42,11 @@ def event_parking_on_save(sender, **kwargs): def event_parking_on_delete(sender, **kwargs): obj = kwargs["instance"] update_statistics(obj.event_area) + + +@receiver(pre_delete, sender=EventArea) +def event_area_on_delete(sender, **kwargs): + obj = kwargs["instance"] + # Only test event areas can be deleted. + if obj.is_test: + EventAreaStatistics.objects.filter(event_area=obj).delete() diff --git a/parkings/tests/api/public/test_event_area.py b/parkings/tests/api/public/test_event_area.py index 6c7b4041..ffaf667c 100644 --- a/parkings/tests/api/public/test_event_area.py +++ b/parkings/tests/api/public/test_event_area.py @@ -46,6 +46,16 @@ def test_get_list_check_data(api_client, event_area): assert properties_data['capacity_estimate'] == event_area.capacity_estimate +def test_get_list_test_event_area(api_client, event_area_factory): + event_area = event_area_factory.create() + stats_data = get(api_client, list_url) + assert stats_data["count"] == 1 + event_area.is_test = True + event_area.save() + stats_data = get(api_client, list_url) + assert stats_data["count"] == 0 + + def test_event_area_with_price_and_price_unit_lenght(api_client, event_area): event_area.price = Decimal(str('1.23')) event_area.price_unit_length = 8 diff --git a/parkings/tests/api/public/test_event_area_statistics.py b/parkings/tests/api/public/test_event_area_statistics.py index 82ac284a..9db211d4 100644 --- a/parkings/tests/api/public/test_event_area_statistics.py +++ b/parkings/tests/api/public/test_event_area_statistics.py @@ -150,6 +150,16 @@ def test_get_list_check_data(api_client, event_parking_factory, event_area_facto assert stats_data_3['current_parking_count'] == 0 # not valid parkings currently +def test_get_list_test_event_area(api_client, event_area_factory): + event_area = event_area_factory.create() + stats_data = get(api_client, list_url) + assert stats_data["count"] == 1 + event_area.is_test = True + event_area.save() + stats_data = get(api_client, list_url) + assert stats_data["count"] == 0 + + def test_get_detail_check_data(api_client, event_parking_factory, event_area): event_parking_factory.create_batch(3, event_area=event_area) stats_data = get(api_client, get_detail_url(event_area)) diff --git a/parkings/tests/api/public/test_event_area_total_statistics.py b/parkings/tests/api/public/test_event_area_total_statistics.py index 4c34220f..995c339b 100644 --- a/parkings/tests/api/public/test_event_area_total_statistics.py +++ b/parkings/tests/api/public/test_event_area_total_statistics.py @@ -38,6 +38,16 @@ def test_get_list_check_data(api_client, event_parking_factory, event_area_facto assert results[4]['total_parking_count'] == 0 +def test_get_list_test_event_area(api_client, event_area_factory): + event_area = event_area_factory.create() + stats_data = get(api_client, list_url) + assert stats_data["count"] == 1 + event_area.is_test = True + event_area.save() + stats_data = get(api_client, list_url) + assert stats_data["count"] == 0 + + @pytest.mark.django_db def test_get_detail_check_data(api_client, event_parking_factory, event_area_factory): event_area = event_area_factory.create() diff --git a/parkings/tests/test_event_area_statistics_model.py b/parkings/tests/test_event_area_statistics_model.py index 780eb7b1..23fd3108 100644 --- a/parkings/tests/test_event_area_statistics_model.py +++ b/parkings/tests/test_event_area_statistics_model.py @@ -31,6 +31,15 @@ def test_event_area_statistics_is_created(event_area_data): assert statistics.total_parking_count == 0 +@pytest.mark.django_db +def test_event_area_statistics_is_deleted(event_area_data): + event_area_data["is_test"] = True + event_area = EventArea.objects.create(**event_area_data) + assert EventAreaStatistics.objects.count() == 1 + event_area.delete() + assert EventAreaStatistics.objects.count() == 0 + + @pytest.mark.django_db def test_event_area_statistics_is_not_deleted(event_area_data): event_area = EventArea.objects.create(**event_area_data)