Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/release/RELEASE-NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
* *Describe scheme changes here.*

### Code/API changes
* [OSDEV-1453](https://opensupplyhub.atlassian.net/browse/OSDEV-1453) - The `detail` keyword instead of `message` has been applied in error response objects for V1 endpoints.
* [OSDEV-1346](https://opensupplyhub.atlassian.net/browse/OSDEV-1346) - Disabled null values from the response of the OpenSearch. Disabled possible null `os_id`, `claim_id` and `source` from `PATCH api/v1/moderation-events/{moderation_id}` response.
* [OSDEV-1449](https://opensupplyhub.atlassian.net/browse/OSDEV-1449) - **Breaking changes** to the following endpoints:
- GET `v1/moderation-events`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def to_internal_value(self, data):
if status is None:
raise ValidationError({
"field": "status",
"message": "This field is required."
"detail": "This field is required."
})

self.__validate_status(status)
Expand All @@ -54,7 +54,7 @@ def __validate_status(self, value):
]:
raise ValidationError({
"field": "status",
"message": (
"detail": (
"Moderation status must be one of "
"PENDING, APPROVED or REJECTED."
)
Expand Down
4 changes: 2 additions & 2 deletions src/django/api/serializers/v1/moderation_events_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
countries_validator import CountryValidator
from api.serializers.v1.opensearch_common_validators. \
date_range_validator import DateRangeValidator
from api.views.v1.utils import COMMON_ERROR_MESSAGE
from api.views.v1.utils import COMMON_ERROR_DETAIL


class ModerationEventsSerializer(Serializer):
Expand Down Expand Up @@ -86,7 +86,7 @@ def validate(self, data):
if errors:
# [OSDEV-1441] Pass error msg to the Rollbar here
raise ValidationError({
"message": COMMON_ERROR_MESSAGE,
"detail": COMMON_ERROR_DETAIL,
"errors": errors
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ def validate_opensearch_params(self, data) -> List[dict]:
(lat is None and lng is not None)):
errors.append({
"field": "coordinates",
"message": "Both latitude and longitude must be provided."
"detail": "Both latitude and longitude must be provided."
})

if lat is not None:
if not (-90 <= lat <= 90):
errors.append({
"field": "coordinates",
"message": "Latitude must be between -90 and 90 degrees."
"detail": "Latitude must be between -90 and 90 degrees."
})

if lng is not None:
if not (-180 <= lng <= 180):
errors.append({
"field": "coordinates",
"message":
"detail":
"Longitude must be between -180 and 180 degrees."
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def validate_opensearch_params(self, data) -> List[dict]:
if not re.match(valid_country_value_regexp, country):
errors.append({
"field": "country",
"message":
"detail":
f"'{country}' is not a valid alpha-2 country code."
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def validate_opensearch_params(self, data) -> List[dict]:
if date_gte and date_lt and date_gte > date_lt:
errors.append({
"field": "date_gte",
"message": (
"detail": (
"The 'date_gte' must be "
"less than or equal to 'date_lt'."
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ def validate_opensearch_params(self, data) -> List[dict]:
if invalid_ids:
errors.append({
"field": "moderation_id",
"message": f"Invalid UUID(s): {', '.join(invalid_ids)}.",
"detail": f"Invalid UUID(s): {', '.join(invalid_ids)}.",
})
elif isinstance(moderation_id, str):
if not self.is_valid_uuid(moderation_id):
errors.append({
"field": "moderation_id",
"message": f"Invalid UUID: {moderation_id}.",
"detail": f"Invalid UUID: {moderation_id}.",
})
else:
errors.append({
"field": "moderation_id",
"message": (
"detail": (
"moderation_id must be a valid UUID or a list of UUIDs."
)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def validate_opensearch_params(self, data) -> List[dict]:
(min_value is None and max_value is not None)):
errors.append({
"field": "number_of_workers",
"message": (
"detail": (
"The value must be a valid object with `min` and `max` "
"properties."
)
Expand All @@ -24,7 +24,7 @@ def validate_opensearch_params(self, data) -> List[dict]:
min_value > max_value):
errors.append({
"field": "number_of_workers",
"message": (
"detail": (
"Minimum value must be less than or equal "
"to maximum value."
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def validate_opensearch_params(self, data) -> List[dict]:
percent_female_workers_max is not None):
errors.append({
"field": "percent_female_workers",
"message": "Both min and max percentages must be provided."
"detail": "Both min and max percentages must be provided."
})

if percent_female_workers_min is not None and \
Expand All @@ -25,12 +25,12 @@ def validate_opensearch_params(self, data) -> List[dict]:
0 < percent_female_workers_max <= 100):
errors.append({
"field": "percent_female_workers",
"message": "Percentages must be between 0 and 100."
"detail": "Percentages must be between 0 and 100."
})
if percent_female_workers_min > percent_female_workers_max:
errors.append({
"field": "percent_female_workers",
"message": (
"detail": (
"Minimum percentage must be less than or equal to "
"maximum percentage."
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def validate_opensearch_params(self, data) -> List[dict]:
if request_type not in valid_request_types:
errors.append({
"field": "request_type",
"message": f"'{request_type}' is not a valid request_type. \
"detail": f"'{request_type}' is not a valid request_type. \
Allowed values are 'CREATE', 'UPDATE' or 'CLAIM'."
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ def validate_opensearch_params(self, data) -> List[dict]:
if size <= 0 or size > size_limit:
errors.append({
"field": "size",
"message": (
"detail": (
f"Size must be a positive integer less than or equal "
f"to {size_limit}."
)
})
except ValueError:
errors.append({
"field": "size",
"message": "Size must be a valid integer."
"detail": "Size must be a valid integer."
})

return errors
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ def validate_opensearch_params(self, data) -> List[dict]:
if not isinstance(source, list):
errors.append({
"field": "source",
"message": "Source must be a list of values."
"detail": "Source must be a list of values."
})
elif not all(item in self.VALID_SOURCES for item in source):
invalid_sources = [item for item in source if
item not in self.VALID_SOURCES]
errors.append({
"field": "source",
"message": (
"detail": (
f"Invalid source(s) {invalid_sources}. "
"Allowed values are 'SLC' or 'API'."
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ def validate_opensearch_params(self, data) -> List[dict]:
if not isinstance(status, list):
errors.append({
"field": "status",
"message": "Status must be a list of values."
"detail": "Status must be a list of values."
})
elif not all(item in self.VALID_STATUSES for item in status):
invalid_statuses = [item for item in status if
item not in self.VALID_STATUSES]
errors.append({
"field": "status",
"message": (
f"Invalid source(s) {invalid_statuses}. "
"detail": (
f"Invalid status(es) {invalid_statuses}. "
"Allowed values are 'PENDING','APPROVED' or 'REJECTED'."
)
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
percent_of_female_workers_validator import PercentOfFemaleWorkersValidator
from api.serializers.v1.opensearch_common_validators. \
coordinates_validator import CoordinatesValidator
from api.views.v1.utils import COMMON_ERROR_MESSAGE
from api.views.v1.utils import COMMON_ERROR_DETAIL


class ProductionLocationsSerializer(Serializer):
Expand Down Expand Up @@ -61,7 +61,7 @@ def validate(self, data):
if errors:
# [OSDEV-1441] Pass error msg to the Rollbar here
raise ValidationError({
"message": COMMON_ERROR_MESSAGE,
"detail": COMMON_ERROR_DETAIL,
"errors": errors
})

Expand Down
6 changes: 3 additions & 3 deletions src/django/api/services/opensearch/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
class OpenSearchServiceException(Exception):
def __init__(
self,
message="An unexpected error occurred while processing the request."
detail="An unexpected error occurred while processing the request."
):
self.message = message
super().__init__(self.message)
self.detail = detail
super().__init__(self.detail)


class OpenSearchService(SearchInterface):
Expand Down
4 changes: 2 additions & 2 deletions src/django/api/tests/test_production_locations_view_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ def test_get_single_production_location_not_found(self):
self.search_index_mock.return_value = {}
url = f"/api/v1/production-locations/{self.os_id}/"
api_res = self.client.get(url)
message = {"detail": "The location with the given id was not found."}
self.assertEqual(api_res.data, message)
detail = {"detail": "The location with the given id was not found."}
self.assertEqual(api_res.data, detail)
self.assertEqual(api_res.status_code, status.HTTP_404_NOT_FOUND)
12 changes: 6 additions & 6 deletions src/django/api/tests/test_v1_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,20 +115,20 @@ def test_serialize_params_invalid(self):
serialize_params(TestProductionLocationsSerializer, query_dict)
self.assertIsNotNone(error_response)
self.assertEqual(
error_response['message'],
error_response['detail'],
"The request query is invalid."
)
self.assertIn(
{
'field': 'number_of_workers_min',
'message': 'A Valid Integer Is Required.'
'detail': 'A Valid Integer Is Required.'
},
error_response['errors']
)
self.assertIn(
{
'field': 'size',
'message': 'A Valid Integer Is Required.'
'detail': 'A Valid Integer Is Required.'
},
error_response['errors']
)
Expand All @@ -139,18 +139,18 @@ def test_handle_value_error(self):
self.assertIsInstance(response, Response)
self.assertEqual(response.status_code, 400)
self.assertEqual(
response.data['message'],
response.data['detail'],
"The request query is invalid."
)
self.assertEqual(response.data['errors'][0]['field'], "general")
self.assertIn(
"There was a problem processing your request.",
response.data['errors'][0]['message']
response.data['errors'][0]['detail']
)

def test_handle_opensearch_exception(self):
exception = OpenSearchServiceException("OpenSearch error")
response = handle_opensearch_exception(exception)
self.assertIsInstance(response, Response)
self.assertEqual(response.status_code, 500)
self.assertEqual(response.data['message'], "OpenSearch error")
self.assertEqual(response.data['detail'], "OpenSearch error")
8 changes: 4 additions & 4 deletions src/django/api/views/v1/moderation_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def retrieve(self, _, pk=None):
if not ModerationIdValidator.is_valid_uuid(pk):
return handle_path_error(
field="moderation_id",
message="Invalid UUID format.",
detail="Invalid UUID format.",
status_code=status.HTTP_400_BAD_REQUEST
)

Expand All @@ -89,7 +89,7 @@ def patch(self, request, pk=None):
if not ModerationIdValidator.is_valid_uuid(pk):
return handle_path_error(
field="moderation_id",
message="Invalid UUID format.",
detail="Invalid UUID format.",
status_code=status.HTTP_400_BAD_REQUEST
)

Expand All @@ -98,7 +98,7 @@ def patch(self, request, pk=None):
except ModerationEvent.DoesNotExist:
return handle_path_error(
field="moderation_id",
message="Moderation event not found.",
detail="Moderation event not found.",
status_code=status.HTTP_404_NOT_FOUND
)

Expand All @@ -114,7 +114,7 @@ def patch(self, request, pk=None):

return Response(
{
"message": 'The request body contains '
"detail": 'The request body contains '
'invalid or missing fields.',
"error": [serializer.errors]
},
Expand Down
Loading