-
Notifications
You must be signed in to change notification settings - Fork 9
[OSDEV-1336] SLC. Implement PATCH api/v1/production-locations/{os_id}/ #457
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
vladsha-dev
merged 14 commits into
main
from
OSDEV-1336-slc-implement-patch-api-v1-production-locations-os-id
Dec 18, 2024
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
907c669
Created api/v1/production-locations/{os_id}/ PATCH endpoint
vladsha-dev 19d0406
Merge branch 'main' into OSDEV-1336-slc-implement-patch-api-v1-produc…
vladsha-dev e19e224
Fix moderation events indexing and tests
vladsha-dev fb18164
Write tests
vladsha-dev ebf421b
Updated release notes
vladsha-dev effca00
Merge branch 'main' into OSDEV-1336-slc-implement-patch-api-v1-produc…
vladsha-dev 0563e3e
Trigger CI
vladsha-dev 8311cf7
Trigger CI
vladsha-dev d0a89e6
Merge branch 'main' into OSDEV-1336-slc-implement-patch-api-v1-produc…
vladsha-dev e0d79c8
Trigger CI
vladsha-dev 6c14f76
Trigger CI
vladsha-dev 635a5e3
Merge branch 'main' into OSDEV-1336-slc-implement-patch-api-v1-produc…
vladsha-dev b523b70
Reverted changes in clear_opensearch.sh.tpl
vladsha-dev d2eeb88
Update release notes
vladsha-dev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,10 +4,16 @@ | |
|
|
||
| from unittest.mock import Mock, patch | ||
| from rest_framework.test import APITestCase | ||
| from allauth.account.models import EmailAddress | ||
| from django.contrib.gis.geos import Point | ||
|
|
||
| from api.models.moderation_event import ModerationEvent | ||
| from api.models.contributor.contributor import Contributor | ||
| from api.models.user import User | ||
| from api.models.facility.facility_list import FacilityList | ||
| from api.models.facility.facility_list_item import FacilityListItem | ||
| from api.models.facility.facility import Facility | ||
| from api.models.source import Source | ||
| from api.tests.test_data import ( | ||
| geocoding_data, | ||
| geocoding_no_results | ||
|
|
@@ -70,7 +76,7 @@ def test_source_set_as_api_regardless_of_whether_passed(self, mock_get): | |
| self.assertNotIn('source', self.common_valid_input_data) | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
roman-stolar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| contributor=self.contributor, | ||
| raw_data=self.common_valid_input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -137,7 +143,7 @@ def test_invalid_source_value_cannot_be_accepted(self, mock_get): | |
|
|
||
| # Check the length validation. | ||
| event_dto_1 = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=invalid_input_data_1, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -150,7 +156,7 @@ def test_invalid_source_value_cannot_be_accepted(self, mock_get): | |
|
|
||
| # Check validation of accepted values. | ||
| event_dto_2 = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=invalid_input_data_2, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -163,7 +169,7 @@ def test_invalid_source_value_cannot_be_accepted(self, mock_get): | |
|
|
||
| # Check the accepted data type validation for the source field. | ||
| event_dto_3 = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=invalid_input_data_3, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -189,7 +195,7 @@ def test_mapping_of_unsupported_fields_by_contricleaner_with_valid_data( | |
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -256,7 +262,7 @@ def test_mapping_of_unsupported_fields_by_contricleaner_with_invalid_data( | |
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -289,7 +295,7 @@ def test_handling_of_cc_list_level_errors(self): | |
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -332,7 +338,7 @@ def test_handling_of_cc_handler_not_set_exception(self, mock_process_data): | |
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -368,7 +374,7 @@ def test_handling_geocoded_no_results_error(self, mock_get): | |
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -397,7 +403,7 @@ def test_handling_geocoding_internal_error(self, mock_geocode_address): | |
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -408,8 +414,7 @@ def test_handling_geocoding_internal_error(self, mock_geocode_address): | |
| self.assertIsNone(result.moderation_event) | ||
| self.assertEqual(result.errors, expected_error_result) | ||
|
|
||
| def test_moderation_event_is_created_with_coordinates_properly(self): | ||
|
|
||
| def test_moderation_event_creation_with_coordinates_for_create(self): | ||
| input_data = { | ||
| 'source': 'SLC', | ||
| 'name': 'Blue Horizon Facility', | ||
|
|
@@ -454,7 +459,7 @@ def test_moderation_event_is_created_with_coordinates_properly(self): | |
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
@@ -499,9 +504,153 @@ def test_moderation_event_is_created_with_coordinates_properly(self): | |
| # was provided during the creation of the moderation event. | ||
| self.assertIsNone(moderation_event.os) | ||
|
|
||
| def test_moderation_event_creation_with_valid_data_for_update(self): | ||
| # Create a new user and contributor for the production location that | ||
| # already exists in the system while processing the location | ||
| # contribution. | ||
| existing_location_user_email = '[email protected]' | ||
| existing_location_user_password = '4567test' | ||
| existing_location_user = User.objects.create( | ||
| email=existing_location_user_email | ||
| ) | ||
| existing_location_user.set_password( | ||
| existing_location_user_password | ||
| ) | ||
| existing_location_user.save() | ||
| EmailAddress.objects.create( | ||
| user=existing_location_user, | ||
| email=existing_location_user_email, | ||
| verified=True, | ||
| primary=True | ||
| ) | ||
|
|
||
| existing_location_contributor = Contributor.objects.create( | ||
| admin=existing_location_user, | ||
| name='test contributor 2', | ||
| contrib_type=Contributor.OTHER_CONTRIB_TYPE, | ||
| ) | ||
|
|
||
| # Create the production location to ensure the existing location is in | ||
| # place before processing the contribution. | ||
| list = FacilityList.objects.create( | ||
| header='header', file_name='one', name='New List Test' | ||
| ) | ||
| source = Source.objects.create( | ||
| source_type=Source.LIST, | ||
| facility_list=list, | ||
| contributor=existing_location_contributor | ||
| ) | ||
| list_item = FacilityListItem.objects.create( | ||
| name='Gamma Tech Manufacturing Plant', | ||
| address='1574 Quantum Avenue, Building 4B, Technopolis', | ||
| country_code='YT', | ||
| sector=['Apparel'], | ||
| row_index=1, | ||
| status=FacilityListItem.CONFIRMED_MATCH, | ||
| source=source | ||
| ) | ||
| production_location = Facility.objects.create( | ||
| name=list_item.name, | ||
| address=list_item.address, | ||
| country_code=list_item.country_code, | ||
| location=Point(0, 0), | ||
| created_from=list_item | ||
| ) | ||
|
|
||
| input_data = { | ||
| 'source': 'SLC', | ||
| 'name': 'Blue Horizon Facility', | ||
| 'address': '990 Spring Garden St., Philadelphia PA 19123', | ||
| 'country': 'US', | ||
| 'sector': ['Apparel', 'Equipment'], | ||
| 'coordinates': { | ||
| 'lat': 51.078389, | ||
| 'lng': 16.978477 | ||
| }, | ||
| 'product_type': ['Random product type'] | ||
| } | ||
|
|
||
| expected_raw_data = deepcopy(input_data) | ||
| expected_cleaned_data = { | ||
| 'raw_json': { | ||
| 'lat': 51.078389, | ||
| 'lng': 16.978477, | ||
| 'name': 'Blue Horizon Facility', | ||
| 'address': '990 Spring Garden St., Philadelphia PA 19123', | ||
| 'country': 'US', | ||
| 'sector': ['Apparel', 'Equipment'], | ||
| 'product_type': ['Random product type'] | ||
| }, | ||
| 'name': 'Blue Horizon Facility', | ||
| 'clean_name': 'blue horizon facility', | ||
| 'address': '990 Spring Garden St., Philadelphia PA 19123', | ||
| 'clean_address': '990 spring garden st. philadelphia pa 19123', | ||
| 'country_code': 'US', | ||
| 'sector': ['Unspecified'], | ||
| 'fields': { | ||
| 'product_type': [ | ||
| 'Apparel', | ||
| 'Equipment', | ||
| 'Random product type' | ||
| ], | ||
| 'lat': 51.078389, | ||
| 'lng': 16.978477, | ||
| 'country': 'US' | ||
| }, | ||
| 'errors': [] | ||
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.UPDATE.value, | ||
| os=production_location | ||
| ) | ||
| result = self.moderation_event_creator.perform_event_creation( | ||
| event_dto | ||
| ) | ||
| self.assertEqual(result.status_code, 202) | ||
|
|
||
| moderation_event = result.moderation_event | ||
|
|
||
| self.assertIsNotNone(moderation_event) | ||
| self.assertTrue(self.is_valid_uuid(moderation_event.uuid)) | ||
|
|
||
| stringified_created_at = moderation_event.created_at.strftime( | ||
| '%Y-%m-%dT%H:%M:%S.%f' | ||
| ) + 'Z' | ||
| self.assertTrue( | ||
| self.is_valid_date_with_microseconds(stringified_created_at) | ||
| ) | ||
|
|
||
| stringified_updated_at = moderation_event.updated_at.strftime( | ||
| '%Y-%m-%dT%H:%M:%S.%f' | ||
| ) + 'Z' | ||
| self.assertTrue( | ||
| self.is_valid_date_with_microseconds(stringified_updated_at) | ||
| ) | ||
|
|
||
| self.assertIsNone(moderation_event.status_change_date) | ||
| self.assertEqual(moderation_event.request_type, 'UPDATE') | ||
| self.assertEqual(moderation_event.raw_data, expected_raw_data) | ||
| self.assertEqual(moderation_event.cleaned_data, expected_cleaned_data) | ||
| # The geocode result should be empty because the coordinates provided | ||
| # did not trigger the Google API geocoding. | ||
| self.assertEqual(moderation_event.geocode_result, {}) | ||
| self.assertEqual(moderation_event.status, 'PENDING') | ||
| self.assertEqual(moderation_event.source, 'SLC') | ||
| # The claim field should be None because no claim relation was | ||
| # provided during the creation of the moderation event. | ||
| self.assertIsNone(moderation_event.claim) | ||
| self.assertEqual(moderation_event.contributor, self.contributor) | ||
| self.assertEqual(moderation_event.os.id, production_location.id) | ||
|
|
||
| @patch('api.geocoding.requests.get') | ||
| def test_moderation_event_is_created_without_coordinates_properly( | ||
| self, mock_get): | ||
| # This test focuses on testing the case when the coordinates were not | ||
| # passed, and geocoding should be performed for the particular | ||
| # contribution. | ||
| mock_get.return_value = Mock(ok=True, status_code=200) | ||
| mock_get.return_value.json.return_value = geocoding_data | ||
|
|
||
|
|
@@ -629,7 +778,7 @@ def test_moderation_event_is_created_without_coordinates_properly( | |
| } | ||
|
|
||
| event_dto = CreateModerationEventDTO( | ||
| contributor_id=self.contributor, | ||
| contributor=self.contributor, | ||
| raw_data=input_data, | ||
| request_type=ModerationEvent.RequestType.CREATE.value | ||
| ) | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.