diff --git a/api/src/pcapi/core/offerers/api.py b/api/src/pcapi/core/offerers/api.py index 9efdf313cda..e26f5788fbc 100644 --- a/api/src/pcapi/core/offerers/api.py +++ b/api/src/pcapi/core/offerers/api.py @@ -2727,9 +2727,31 @@ def create_offerer_address_from_address_api( city: str, latitude: float, longitude: float, + is_manual_edition: bool, ) -> geography_models.Address: - is_manual_edition: bool = False - try: + if is_manual_edition: + try: + address_info = api_adresse.get_municipality_centroid(city=city, postcode=postal_code) + location_data = LocationData( + city=city, + postal_code=postal_code, + latitude=latitude, + longitude=longitude, + street=street, + insee_code=address_info.citycode, + ban_id=None, + ) + except api_adresse.NoResultException: + location_data = LocationData( + city=city, + postal_code=postal_code, + latitude=latitude, + longitude=longitude, + street=street, + insee_code=None, + ban_id=None, + ) + else: address_info = api_adresse.get_address(street, postal_code, city) location_data = LocationData( city=address_info.city, @@ -2740,23 +2762,6 @@ def create_offerer_address_from_address_api( insee_code=address_info.citycode, ban_id=address_info.id, ) - except api_adresse.NoResultException: - insee_code = None - if city and postal_code: - try: - insee_code = api_adresse.get_municipality_centroid(city, postal_code).citycode - except api_adresse.AdresseException: - pass - location_data = LocationData( - city=city, - postal_code=postal_code, - latitude=latitude, - longitude=longitude, - street=street, - insee_code=insee_code, - ban_id=None, - ) - is_manual_edition = True return get_or_create_address(location_data, is_manual_edition=is_manual_edition) diff --git a/api/src/pcapi/core/offerers/schemas.py b/api/src/pcapi/core/offerers/schemas.py index 6815f5853d1..3877cac8681 100644 --- a/api/src/pcapi/core/offerers/schemas.py +++ b/api/src/pcapi/core/offerers/schemas.py @@ -117,3 +117,4 @@ class AddressBodyModel(BaseModel): longitude: float | str postalCode: VenuePostalCode street: VenueAddress + isManualEdition: bool = False diff --git a/api/src/pcapi/core/offers/api.py b/api/src/pcapi/core/offers/api.py index 026cd427b0f..4032dd2f3c5 100644 --- a/api/src/pcapi/core/offers/api.py +++ b/api/src/pcapi/core/offers/api.py @@ -331,6 +331,7 @@ def get_offerer_address_from_address( city=address.city, latitude=float(address.latitude), longitude=float(address.longitude), + is_manual_edition=address.isManualEdition, ) return offerers_api.get_or_create_offerer_address( venue.managingOffererId, diff --git a/api/tests/routes/pro/patch_offer_test.py b/api/tests/routes/pro/patch_offer_test.py index 046fc27e70c..e065a059e6e 100644 --- a/api/tests/routes/pro/patch_offer_test.py +++ b/api/tests/routes/pro/patch_offer_test.py @@ -4,7 +4,7 @@ import pytest -from pcapi.connectors.api_adresse import AddressInfo +from pcapi.connectors import api_adresse import pcapi.core.bookings.factories as bookings_factories from pcapi.core.categories import subcategories_v2 as subcategories import pcapi.core.mails.testing as mails_testing @@ -107,7 +107,7 @@ def test_patch_offer_with_address(self, get_address_mock, label, offer_has_oa, a "label": label, }, } - get_address_mock.return_value = AddressInfo( + get_address_mock.return_value = api_adresse.AddressInfo( street="1 rue de la paix", city="Paris", citycode="75102", @@ -132,6 +132,104 @@ def test_patch_offer_with_address(self, get_address_mock, label, offer_has_oa, a assert address.postalCode == "75102" assert address.latitude == Decimal("48.85660") assert address.longitude == Decimal("2.3522") + assert address.isManualEdition is False + + @patch("pcapi.connectors.api_adresse.get_municipality_centroid") + def test_patch_offer_with_manual_address_edition(self, mocked_get_centroid, client): + # Given + user_offerer = offerers_factories.UserOffererFactory(user__email="user@example.com") + venue = offerers_factories.VenueFactory(managingOfferer=user_offerer.offerer) + offer = offers_factories.OfferFactory( + subcategoryId=subcategories.RENCONTRE.id, + venue=venue, + name="New name", + description="description", + ) + mocked_get_centroid.return_value = api_adresse.AddressInfo( + id="98826", + label="Poum", + postcode="98826", + citycode="98826", + latitude=-20.203, + longitude=164.073, + score=0.9371472727272726, + city="Poum", + street=None, + ) + + # When + data = { + "name": "Visite des Marais Salins de Kô", + "externalTicketOfficeUrl": "http://example.net", + "mentalDisabilityCompliant": True, + "address": { + "street": "3, Chemin de la Plage", + "city": "Poum, Tiabet", + "postalCode": "98826", + "latitude": -20.08521415490879, + "longitude": 164.03239215718415, + "label": "Marais Salins de Kô", + "isManualEdition": True, + }, + } + + response = client.with_session_auth("user@example.com").patch(f"/offers/{offer.id}", json=data) + + assert response.status_code == 200 + assert response.json["id"] == offer.id + updated_offer = Offer.query.get(offer.id) + address = updated_offer.offererAddress.address + assert updated_offer.offererAddress.label == "Marais Salins de Kô" + assert address.street == data["address"]["street"] + assert address.city == data["address"]["city"] + assert address.postalCode == data["address"]["postalCode"] + assert address.inseeCode == "98826" + assert address.latitude == Decimal("-20.08521") + assert address.longitude == Decimal("164.03239") + assert address.isManualEdition is True + + @patch("pcapi.connectors.api_adresse.get_municipality_centroid") + def test_unknown_result_from_api_adresse_doesnt_block_offer_creation(self, mocked_get_centroid, client): + # Given + user_offerer = offerers_factories.UserOffererFactory(user__email="user@example.com") + venue = offerers_factories.VenueFactory(managingOfferer=user_offerer.offerer) + offer = offers_factories.OfferFactory( + subcategoryId=subcategories.RENCONTRE.id, + venue=venue, + name="New name", + description="description", + ) + mocked_get_centroid.side_effect = api_adresse.NoResultException + # When + data = { + "name": "Visite des Marais Salins de Kô", + "externalTicketOfficeUrl": "http://example.net", + "mentalDisabilityCompliant": True, + "address": { + "street": "3, Chemin de la Plage", + "city": "Poum, Tiabet", + "postalCode": "98826", + "latitude": -20.08521415490879, + "longitude": 164.03239215718415, + "label": "Marais Salins de Kô", + "isManualEdition": True, + }, + } + + response = client.with_session_auth("user@example.com").patch(f"/offers/{offer.id}", json=data) + + assert response.status_code == 200 + assert response.json["id"] == offer.id + updated_offer = Offer.query.get(offer.id) + address = updated_offer.offererAddress.address + assert updated_offer.offererAddress.label == "Marais Salins de Kô" + assert address.street == data["address"]["street"] + assert address.city == data["address"]["city"] + assert address.postalCode == data["address"]["postalCode"] + assert address.inseeCode == None + assert address.latitude == Decimal("-20.08521") + assert address.longitude == Decimal("164.03239") + assert address.isManualEdition is True @pytest.mark.parametrize("label", ["", None, True]) @patch("pcapi.connectors.api_adresse.get_address") @@ -170,7 +268,7 @@ def test_patch_offer_with_address_twice(self, get_address_mock, label, client): "label": label, }, } - get_address_mock.return_value = AddressInfo( + get_address_mock.return_value = api_adresse.AddressInfo( street="1 rue de la paix", city="Paris", citycode="75102", @@ -193,6 +291,7 @@ def test_patch_offer_with_address_twice(self, get_address_mock, label, client): assert address.postalCode == "75102" assert address.latitude == Decimal("48.85660") assert address.longitude == Decimal("2.3522") + assert address.isManualEdition is False def test_withdrawal_can_be_updated(self, client): offer = offers_factories.OfferFactory( diff --git a/api/tests/routes/pro/post_offer_test.py b/api/tests/routes/pro/post_offer_test.py index 1a8e830d884..d58ef914e57 100644 --- a/api/tests/routes/pro/post_offer_test.py +++ b/api/tests/routes/pro/post_offer_test.py @@ -1,9 +1,7 @@ from decimal import Decimal -from unittest.mock import patch import pytest -from pcapi.connectors import api_adresse from pcapi.core.categories import subcategories_v2 as subcategories import pcapi.core.offerers.factories as offerers_factories from pcapi.core.offers.models import Offer @@ -210,11 +208,10 @@ def test_create_event_offer_with_manual_offerer_address(self, oa_label, client): "longitude": "2.308289", "postalCode": "75001", "street": "3 Rue de Valois", + "isManualEdition": True, }, } - with patch("pcapi.connectors.api_adresse.get_address") as mocked_get_address: - mocked_get_address.side_effect = api_adresse.NoResultException - response = client.with_session_auth("user@example.com").post("/offers", json=data) + response = client.with_session_auth("user@example.com").post("/offers", json=data) # Then assert response.status_code == 201 @@ -222,8 +219,8 @@ def test_create_event_offer_with_manual_offerer_address(self, oa_label, client): offer = Offer.query.get(offer_id) assert offer.offererAddress.address.isManualEdition assert offer.offererAddress.label == oa_label - assert offer.offererAddress.address.inseeCode == "06029" assert not offer.offererAddress.address.banId + assert offer.offererAddress.address.isManualEdition is True def when_creating_new_thing_offer(self, client): # Given diff --git a/pro/src/apiClient/v1/models/AddressBodyModel.ts b/pro/src/apiClient/v1/models/AddressBodyModel.ts index b191229fa60..2e7bc4f1abe 100644 --- a/pro/src/apiClient/v1/models/AddressBodyModel.ts +++ b/pro/src/apiClient/v1/models/AddressBodyModel.ts @@ -4,6 +4,7 @@ /* eslint-disable */ export type AddressBodyModel = { city: string; + isManualEdition?: boolean; label?: string | null; latitude: (number | string); longitude: (number | string); diff --git a/pro/src/screens/IndividualOffer/InformationsScreen/__specs__/serializers.spec.ts b/pro/src/screens/IndividualOffer/InformationsScreen/__specs__/serializers.spec.ts index 2516f91cab3..784da6c5279 100644 --- a/pro/src/screens/IndividualOffer/InformationsScreen/__specs__/serializers.spec.ts +++ b/pro/src/screens/IndividualOffer/InformationsScreen/__specs__/serializers.spec.ts @@ -146,6 +146,7 @@ describe('test updateIndividualOffer::serializers', () => { postalCode: '75001', street: '3 Rue de Valois', locationLabel: 'Bureau', + manuallySetAddress: true, } patchBody = { ...patchBody, @@ -156,6 +157,7 @@ describe('test updateIndividualOffer::serializers', () => { postalCode: '75001', street: '3 Rue de Valois', label: 'Bureau', + isManualEdition: true, }, } expect( @@ -164,6 +166,37 @@ describe('test updateIndividualOffer::serializers', () => { formValues, }) ).toEqual(patchBody) + + // Test with empty label and manual edition false + formValues = { + ...formValues, + city: 'Paris', + latitude: '48.853320', + longitude: '2.348979', + postalCode: '75001', + street: '3 Rue de Valois', + locationLabel: '', + manuallySetAddress: false, + } + patchBody = { + ...patchBody, + address: { + city: 'Paris', + latitude: '48.853320', + longitude: '2.348979', + postalCode: '75001', + street: '3 Rue de Valois', + label: '', + isManualEdition: false, + }, + } + + expect( + serializePatchOffer({ + offer: getIndividualOfferFactory(), + formValues, + }) + ).toEqual(patchBody) }) }) }) diff --git a/pro/src/screens/IndividualOffer/InformationsScreen/serializePatchOffer.ts b/pro/src/screens/IndividualOffer/InformationsScreen/serializePatchOffer.ts index 5e1cace1bf6..eb375048628 100644 --- a/pro/src/screens/IndividualOffer/InformationsScreen/serializePatchOffer.ts +++ b/pro/src/screens/IndividualOffer/InformationsScreen/serializePatchOffer.ts @@ -83,8 +83,7 @@ export const serializePatchOffer = ({ sentValues.latitude && sentValues.longitude && sentValues.postalCode && - sentValues.street && - sentValues.locationLabel + sentValues.street ) { addressValues = { address: { @@ -94,6 +93,7 @@ export const serializePatchOffer = ({ postalCode: sentValues.postalCode, street: sentValues.street, label: sentValues.locationLabel, + isManualEdition: sentValues.manuallySetAddress, }, } }