diff --git a/deployment/docker/Dockerfile b/deployment/docker/Dockerfile index 42ff0bb9..70164d5b 100644 --- a/deployment/docker/Dockerfile +++ b/deployment/docker/Dockerfile @@ -1,7 +1,7 @@ FROM python:3.10.4-buster AS prod # Enable postgresql-client-14 -RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ buster-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list +RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main" | tee /etc/apt/sources.list.d/pgdg.list RUN echo "deb http://deb.debian.org/debian/ stable main contrib non-free" | tee /etc/apt/sources.list.d/debian.list RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - diff --git a/django_project/georepo/tasks/geocoding.py b/django_project/georepo/tasks/geocoding.py index 8de7a97a..170f9caf 100644 --- a/django_project/georepo/tasks/geocoding.py +++ b/django_project/georepo/tasks/geocoding.py @@ -30,6 +30,7 @@ get_column_id, get_return_type_key ) +from georepo.utils.uuid_helper import UUIDEncoder logger = logging.getLogger(__name__) @@ -257,7 +258,8 @@ def do_containment_check(geocoding_request: GeocodingRequest, "properties": properties, "geometry": geom } - geojson_file.write(json.dumps(feature_data)) + geojson_file.write( + json.dumps(feature_data, cls=UUIDEncoder)) geojson_file.write(',\n') idx += 1 feature_idx = row[1] @@ -287,7 +289,7 @@ def do_containment_check(geocoding_request: GeocodingRequest, "properties": properties, "geometry": geom } - geojson_file.write(json.dumps(feature_data)) + geojson_file.write(json.dumps(feature_data, cls=UUIDEncoder)) geojson_file.write('\n') geojson_file.write(']\n') geojson_file.write('}\n') diff --git a/django_project/georepo/tests/test_geocoding.py b/django_project/georepo/tests/test_geocoding.py index 8adebfe6..7679f2c6 100644 --- a/django_project/georepo/tests/test_geocoding.py +++ b/django_project/georepo/tests/test_geocoding.py @@ -215,3 +215,77 @@ def test_submit_batch_geocoding_nearest(self, mocked_task): self.assertEqual(len(feat_3['properties']['ucode']), 1) self.assertEqual(feat_3['properties']['ucode'][0], self.pak0_2.ucode) + + @mock.patch('georepo.api_views.entity_view.' + 'process_geocoding_request.delay') + def test_submit_batch_geocoding_nearest_concept_uuid(self, mocked_task): + mocked_task.side_effect = mocked_process + kwargs = { + 'uuid': str(self.dataset_view.uuid), + 'spatial_query': 'ST_Intersects', + 'distance': 0, + 'admin_level': 0, + 'id_type': 'concept_uuid' + } + test_file_path = absolute_path( + 'georepo', 'tests', + 'geojson_dataset', 'level_0_test_points.geojson') + data = open(test_file_path, 'rb') + file = SimpleUploadedFile( + content=data.read(), + name=data.name, + content_type='multipart/form-data' + ) + request = self.factory.post( + reverse( + 'v1:batch-geocoding', + kwargs=kwargs + ) + '?find_nearest=true', + data={ + 'file': file + } + ) + request.user = self.superuser + view = ViewEntityBatchGeocoding.as_view() + response = view(request, **kwargs) + self.assertEqual(response.status_code, 200) + mocked_task.assert_called_once() + self.assertIn('request_id', response.data) + self.assertIn('status_url', response.data) + geocoding_request = GeocodingRequest.objects.filter( + uuid=response.data['request_id'] + ).first() + self.assertTrue(geocoding_request) + self.assertEqual(geocoding_request.status, PENDING) + self.assertEqual(geocoding_request.file_type, GEOJSON) + self.assertTrue(geocoding_request.file) + params = ( + f'({str(self.dataset_view.id)},\'ST_Intersects\',' + f'0,\'concept_uuid\',0,True)' + ) + self.assertEqual(geocoding_request.parameters, params) + self.assertTrue(geocoding_request.task_id) + process_geocoding_request(geocoding_request.id) + geocoding_request.refresh_from_db() + self.assertEqual(geocoding_request.status, DONE) + self.assertTrue(geocoding_request.output_file) + self.assertEqual(geocoding_request.feature_count, 3) + # check for output result + with geocoding_request.output_file.open('rb') as json_data: + features = json.load(json_data) + self.assertEqual(len(features['features']), 3) + feat_1 = features['features'][0] + self.assertIn('concept_uuid', feat_1['properties']) + self.assertEqual(len(feat_1['properties']['concept_uuid']), 1) + self.assertEqual(feat_1['properties']['concept_uuid'][0], + str(self.pak0_2.uuid)) + feat_2 = features['features'][1] + self.assertIn('concept_uuid', feat_2['properties']) + self.assertEqual(len(feat_2['properties']['concept_uuid']), 1) + self.assertEqual(feat_2['properties']['concept_uuid'][0], + str(self.pak0_2.uuid)) + feat_3 = features['features'][2] + self.assertIn('concept_uuid', feat_3['properties']) + self.assertEqual(len(feat_3['properties']['concept_uuid']), 1) + self.assertEqual(feat_3['properties']['concept_uuid'][0], + str(self.pak0_2.uuid)) diff --git a/django_project/georepo/tests/test_search_id.py b/django_project/georepo/tests/test_search_id.py index 2b60c2e8..1a2e7411 100644 --- a/django_project/georepo/tests/test_search_id.py +++ b/django_project/georepo/tests/test_search_id.py @@ -1,4 +1,5 @@ import mock +import json from django.urls import reverse from django.utils import timezone @@ -62,6 +63,14 @@ def test_process_search_id_request(self): id_request.output_file.storage.exists( id_request.output_file.name) ) + f = id_request.output_file.open() + data = json.load(f) + # match the uuid and concept_uuid from PAK_V2 + self.assertEqual( + str(self.pak0_2.uuid), data['PAK'][0]['concept_uuid']) + self.assertEqual( + str(self.pak0_2.uuid_revision), data['PAK'][0]['uuid']) + f.close() id_request.delete() @mock.patch('georepo.api_views.entity_view.' diff --git a/django_project/georepo/utils/uuid_helper.py b/django_project/georepo/utils/uuid_helper.py index 94063657..03efca19 100644 --- a/django_project/georepo/utils/uuid_helper.py +++ b/django_project/georepo/utils/uuid_helper.py @@ -44,5 +44,5 @@ class UUIDEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, UUID): # if the obj is uuid, we simply return the value of uuid - return obj.hex + return str(obj) return json.JSONEncoder.default(self, obj)