Skip to content

Commit

Permalink
Merge pull request #317 from City-of-Turku/sync/merge-prod-into-dev
Browse files Browse the repository at this point in the history
Merge production to develop
  • Loading branch information
ezkat authored Jan 9, 2024
2 parents 93ba519 + f755c0f commit cce7ef3
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 18 deletions.
14 changes: 10 additions & 4 deletions resources/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ def validate_translation(self, data):
fields = [(key, data[key]) for key in data if key in self.translated_fields]
for field, value in fields:
for lang in [x[0] for x in settings.LANGUAGES]:
if value is None and self.fields[field].allow_null:
data.update({
'%s_%s' % (field, lang): None
})
continue

if (not lang in value or not value[lang]) and '%s_%s' % (field, lang) in self.Meta.required_translations:
raise ValidationError({
field: [
Expand All @@ -119,10 +125,10 @@ def validate_translation(self, data):
return data

def validate(self, attrs):
attrs = super().validate(attrs)
if getattr(self.Meta, 'required_translations', None):
self.validate_translation(attrs)
return attrs
attrs = super().validate(attrs)
if getattr(self.Meta, 'required_translations', None):
self.validate_translation(attrs)
return attrs


class NullableTimeField(serializers.TimeField):
Expand Down
12 changes: 7 additions & 5 deletions resources/api/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -1583,11 +1583,13 @@ class ResourceCreateSerializer(TranslatedModelSerializer):
description = serializers.DictField(required=True)
responsible_contact_info = serializers.DictField(
required=False,
help_text=get_translated_field_help_text('responsible_contact_info')
help_text=get_translated_field_help_text('responsible_contact_info'),
allow_null=True
)
specific_terms = serializers.DictField(
required=False,
help_text=get_translated_field_help_text('specific_terms')
help_text=get_translated_field_help_text('specific_terms'),
allow_null=True
)
need_manual_confirmation = serializers.BooleanField(required=True)
authentication = serializers.ChoiceField(choices=Resource.AUTHENTICATION_TYPES, required=True)
Expand All @@ -1597,9 +1599,9 @@ class ResourceCreateSerializer(TranslatedModelSerializer):
slot_size = serializers.DurationField(required=True)
reservation_info = serializers.DictField(required=True)

reservation_confirmed_notification_extra = serializers.DictField(required=False)
reservation_requested_notification_extra = serializers.DictField(required=False)
reservation_additional_information = serializers.DictField(required=False)
reservation_confirmed_notification_extra = serializers.DictField(required=False, allow_null=True)
reservation_requested_notification_extra = serializers.DictField(required=False, allow_null=True)
reservation_additional_information = serializers.DictField(required=False, allow_null=True)

resource_staff_emails = ResourceStaffEmailsField(required=False, allow_empty=True)

Expand Down
2 changes: 1 addition & 1 deletion resources/models/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ def _process_image(self):
save_kwargs = {}
with Image.open(self.image) as img:
if img.size > (1920, 1080):
img.thumbnail((1920, 1080), Image.ANTIALIAS)
img.thumbnail((1920, 1080), Image.LANCZOS)
self.cropping = None
setattr(self, '_processing_required', True)
elif img.size < (128, 128):
Expand Down
42 changes: 41 additions & 1 deletion resources/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import pytest
import datetime
import base64
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.utils import timezone
Expand All @@ -14,6 +15,7 @@
from resources.models import ReservationMetadataSet, ReservationMetadataField
from munigeo.models import Municipality
from maintenance.models import MaintenanceMessage, MaintenanceMode
from .utils import get_test_image_data, get_test_image_payload

@pytest.fixture
def api_client():
Expand Down Expand Up @@ -668,4 +670,42 @@ def resource_with_active_reservations(resource_in_unit):
end=datetime.datetime(year=2115, month=4, day=4, hour=i+1, minute=0, second=0)) \
for i in range(1,11)
])
return resource_in_unit
return resource_in_unit


@pytest.fixture
def resource_create_data(
purpose, test_unit,
space_resource_type):
image = get_test_image_data()
return {
"public": True,
"purposes": [
purpose.id
],
"name": {
"fi": "Test Resource API",
"en": "Test Resource API",
"sv": "Test Resource API",
},
"description": {
"fi": "Test Resource created through API",
"en": "Test Resource created through API",
"sv": "Test Resource created through API"
},
"reservation_info": {
"fi": "Test Resource reservation information",
"en": "Test Resource reservation information",
"sv": "Test Resource reservation information"
},
"need_manual_confirmation": False,
"min_period": "00:30:00",
"max_period": "01:00:00",
"slot_size": "00:15:00",
"authentication": "strong",
"people_capacity": "10",
"terms_of_use": [],
"unit": test_unit.pk,
"type": space_resource_type.pk,
"images": [get_test_image_payload(image=image)]
}
85 changes: 79 additions & 6 deletions resources/tests/test_resource_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import pytest
import base64
from copy import deepcopy
from django.urls import reverse
from django.contrib.auth import get_user_model
Expand All @@ -10,13 +11,21 @@
from freezegun import freeze_time
from guardian.shortcuts import assign_perm, remove_perm

from resources.models.resource import Resource
from resources.models.resource import (
Resource, ResourceImage, InvalidImage
)
from ..enums import UnitAuthorizationLevel, UnitGroupAuthorizationLevel

from resources.models import (Day, Equipment, Period, Reservation, ReservationMetadataSet, ResourceEquipment,
ResourceType, Unit, UnitAuthorization, UnitGroup)
from .utils import assert_response_objects, check_only_safe_methods_allowed, is_partial_dict_in_list, MAX_QUERIES

from resources.models import (
Day, Equipment, Period, Reservation,
ReservationMetadataSet, ResourceEquipment,
ResourceType, Unit, UnitGroup
)
from .utils import (
assert_response_objects, check_only_safe_methods_allowed,
is_partial_dict_in_list, MAX_QUERIES,
get_test_image_data, get_test_image_payload
)

@pytest.fixture
def list_url():
Expand Down Expand Up @@ -1332,4 +1341,68 @@ def test_resource_mass_cancel_reservation_permitted_for_admin_user(

response = staff_api_client.delete(url, data=payload, HTTP_ACCEPT_LANGUAGE='en')
assert response.status_code == 204
assert resource_with_active_reservations.reservations.current().count() == 0
assert resource_with_active_reservations.reservations.current().count() == 0


@pytest.mark.django_db
@pytest.mark.parametrize('image_size, gets_processed', (
((128, 128), False),
((1980, 1200), True),
))
def test_resource_create_through_api(
staff_api_client, staff_user,
resource_create_data, list_url,
image_size, gets_processed
):
url = f'{list_url[:-1]}/new/'
assign_perm('resources.add_resource', staff_user)
staff_api_client.force_authenticate(user=staff_user)
image = get_test_image_data(image_size)
resource_create_data['images'] = [get_test_image_payload(image)]
response = staff_api_client.post(url, data=resource_create_data)
assert response.status_code == 201
resource = Resource.objects.get(pk=response.data['id'])

resource_image = resource.images.first().image

if gets_processed:
assert (resource_image.width, resource_image.height) < (1921, 1081)
else:
assert (resource_image.width, resource_image.height) == image_size


@pytest.mark.django_db
def test_resource_create_through_api_invalid_image(
staff_api_client, staff_user,
resource_create_data, list_url
):
image = get_test_image_data((64, 64))

url = f'{list_url[:-1]}/new/'
assign_perm('resources.add_resource', staff_user)
staff_api_client.force_authenticate(user=staff_user)
resource_create_data['images'] = [get_test_image_payload(image)]
with pytest.raises(InvalidImage):
staff_api_client.post(url, data=resource_create_data)


@pytest.mark.django_db
def test_resource_update_optional_fields_to_null(
staff_api_client, staff_user,
detail_url
):
assign_perm('resources.change_resource', staff_user)
url = f'{detail_url[:-1]}/update/'
staff_api_client.force_authenticate(user=staff_user)

optional_fields = {
'responsible_contact_info': None,
'specific_terms': None,
'reservation_confirmed_notification_extra': None,
'reservation_requested_notification_extra': None,
'reservation_additional_information': None
}

response = staff_api_client.patch(url, data=optional_fields)

assert response.status_code == 200
20 changes: 20 additions & 0 deletions resources/tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
import datetime
import base64

from django.core.exceptions import ValidationError
from django.core.files.base import ContentFile
Expand Down Expand Up @@ -197,3 +198,22 @@ def check_keys(data, expected_keys):
def is_partial_dict_in_list(partial, dicts):
partial_items = partial.items()
return any([partial_items <= d.items() for d in dicts])


def get_test_image_payload(
image, *,
type = "main",
caption = "test caption",
name = "test_image.jpg"):
return {
"type": type,
"caption": {
"fi": caption,
"sv": caption,
"en": caption
},
"image": {
"name": name,
"data": base64.b64encode(image).decode()
}
}
2 changes: 1 addition & 1 deletion respa/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = 'tku-v1.9.1'
__version__ = 'tku-v1.9.2'

VERSION = __version__

0 comments on commit cce7ef3

Please sign in to comment.