Skip to content

Commit

Permalink
(PC-32797)[PRO] feat: resync acceslibre when venue address change
Browse files Browse the repository at this point in the history
  • Loading branch information
rchaffal-pass authored and pcharlet-pass committed Jan 30, 2025
1 parent 496bf21 commit 8685ef6
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 52 deletions.
7 changes: 6 additions & 1 deletion api/src/pcapi/core/offerers/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ def update_venue(
# TODO: (pcharlet 2024-11-28) Remove new_permanent when regularisation is done. Used only to sync venues with acceslibre when update permanent from BO
new_open_to_public = not venue.isOpenToPublic and modifications.get("isOpenToPublic")
new_permanent = not venue.isPermanent and modifications.get("isPermanent")
has_address_changed = (
modifications.get("banId", offerers_constants.UNCHANGED) is not offerers_constants.UNCHANGED
or modifications.get("postalCode", offerers_constants.UNCHANGED) is not offerers_constants.UNCHANGED
or modifications.get("street", offerers_constants.UNCHANGED) is not offerers_constants.UNCHANGED
)
venue_snapshot = history_api.ObjectUpdateSnapshot(venue, author)
if not venue.isVirtual:
assert venue.offererAddress is not None # helps mypy
Expand Down Expand Up @@ -246,7 +251,7 @@ def update_venue(
if contact_data and contact_data.website:
virustotal.request_url_scan(contact_data.website, skip_if_recent_scan=True)

if (new_open_to_public or new_permanent) and not external_accessibility_url:
if ((new_open_to_public or new_permanent) and not external_accessibility_url) or has_address_changed:
match_acceslibre_job.delay(venue.id)

return venue
Expand Down
35 changes: 19 additions & 16 deletions api/src/pcapi/scripts/acceslibre/match_acceslibre.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,31 @@
def match_acceslibre(venue: offerers_models.Venue) -> None:
old_slug = venue.external_accessibility_id
old_url = venue.external_accessibility_url
offerers_api.delete_venue_accessibility_provider(venue)
# TODO(xordoquy): see why delete_venue_accessibility_provider doesn't synchronize session
db.session.refresh(venue)
offerers_api.set_accessibility_provider_id(venue)

if not venue.accessibilityProvider:
logger.info("No match found at acceslibre for Venue %s ", venue.id)
return

history_api.add_action(
history_models.ActionType.INFO_MODIFIED,
author=None,
venue=venue,
comment="Recherche automatisée du lieu permanent avec Acceslibre",
modified_info={
"accessibilityProvider.externalAccessibilityId": {
"old_info": old_slug,
"new_info": venue.accessibilityProvider.externalAccessibilityId,
},
"accessibilityProvider.externalAccessibilityUrl": {
"old_info": old_url,
"new_info": venue.accessibilityProvider.externalAccessibilityUrl,
if old_slug != venue.accessibilityProvider.externalAccessibilityId:
history_api.add_action(
history_models.ActionType.INFO_MODIFIED,
author=None,
venue=venue,
comment="Recherche automatisée du lieu permanent avec Acceslibre",
modified_info={
"accessibilityProvider.externalAccessibilityId": {
"old_info": old_slug,
"new_info": venue.accessibilityProvider.externalAccessibilityId,
},
"accessibilityProvider.externalAccessibilityUrl": {
"old_info": old_url,
"new_info": venue.accessibilityProvider.externalAccessibilityUrl,
},
},
},
)
)

offerers_api.set_accessibility_infos_from_provider_id(venue)
db.session.add(venue)
Expand Down
7 changes: 2 additions & 5 deletions api/tests/core/offerers/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2568,13 +2568,10 @@ def test_add_opening_hours_timespan_is_sorted_chronogicaly(self):
class AccessibilityProviderTest:
def test_set_accessibility_provider_id(self):
venue = offerers_factories.VenueFactory(
name="Une librairie de test",
postalCode="75001",
city="Paris",
name="Une librairie de test", postalCode="75001", city="Paris", accessibilityProvider=None
)
venue_accessibility = offerers_factories.AccessibilityProviderFactory(venue=venue)
offerers_api.set_accessibility_provider_id(venue)
assert venue.accessibilityProvider.externalAccessibilityId == venue_accessibility.externalAccessibilityId
assert venue.accessibilityProvider.externalAccessibilityId == "mon-lieu-chez-acceslibre"

def test_set_accessibility_last_update_at_provider_id(self):
venue = offerers_factories.VenueFactory(
Expand Down
39 changes: 32 additions & 7 deletions api/tests/routes/backoffice/venues_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,7 @@ def test_update_venue(self, mock_get_address, authenticated_client, siren, old_s
"latitude": "48.869311",
"longitude": "2.325463",
"venue_type_code": offerers_models.VenueTypeCode.CREATIVE_ARTS_STORE.name,
"acceslibre_url": "https://acceslibre.beta.gouv.fr/app/slug/",
"acceslibre_url": None,
}

response = self.post_to_endpoint(authenticated_client, venue_id=venue.id, form=data)
Expand Down Expand Up @@ -954,10 +954,11 @@ def test_update_venue(self, mock_get_address, authenticated_client, siren, old_s
assert venue.contact.website == website
assert venue.contact.social_medias == social_medias

assert len(venue.action_history) == 1

update_snapshot = venue.action_history[0].extraData["modified_info"]
assert len(venue.action_history) == 2

# Check the venue update action
update_action = [action for action in venue.action_history if action.extraData["modified_info"].get("name")][0]
update_snapshot = update_action.extraData["modified_info"]
assert update_snapshot["street"]["new_info"] == data["street"]
assert update_snapshot["bookingEmail"]["new_info"] == data["booking_email"]
assert update_snapshot["latitude"]["new_info"] == str(round(float(data["latitude"]), 5))
Expand All @@ -969,6 +970,29 @@ def test_update_venue(self, mock_get_address, authenticated_client, siren, old_s
)
assert update_snapshot["old_oa_label"]["new_info"] == "Venue Name"

# Check the acces libre update action
# The folloing assert is a reminder that acceslibre_url must be None to get the updated acceslibre_url
# from the associated backend. It is updated in a async task which is executed during the tests though
# probably not asynchronously but ends up with unpredictable results.
# Slug could be either mon-lieu-chez-acceslibre or whatever the original slug was.
assert data["acceslibre_url"] is None
acceslibre_action = [
action
for action in venue.action_history
if action.extraData["modified_info"].get("accessibilityProvider.externalAccessibilityId")
][0]
acceslibre_snapshot = acceslibre_action.extraData["modified_info"]
assert (
acceslibre_snapshot["accessibilityProvider.externalAccessibilityId"]["new_info"]
== "mon-lieu-chez-acceslibre"
)
assert acceslibre_snapshot["accessibilityProvider.externalAccessibilityId"]["old_info"] is None
assert (
acceslibre_snapshot["accessibilityProvider.externalAccessibilityUrl"]["new_info"]
== "https://acceslibre.beta.gouv.fr/app/activite/mon-lieu-chez-acceslibre/"
)
assert acceslibre_snapshot["accessibilityProvider.externalAccessibilityUrl"]["old_info"] is None

assert len(mails_testing.outbox) == 1
# check that email is sent when venue is set to permanent and has no image
assert mails_testing.outbox[0]["To"] == venue.bookingEmail
Expand Down Expand Up @@ -1016,8 +1040,9 @@ def test_update_venue_location_with_offerer_address_not_manual(self, authenticat
offerer_address = offerer_addresses[0]
assert (len(offerer_addresses)) == 2
assert venue.offererAddressId == offerer_address.id
assert len(venue.action_history) == 1
update_snapshot = venue.action_history[0].extraData["modified_info"]
assert len(venue.action_history) == 2
update_action = [action for action in venue.action_history if action.extraData["modified_info"].get("name")][0]
update_snapshot = update_action.extraData["modified_info"]

assert update_snapshot["offererAddress.addressId"]["new_info"] == offerer_address.addressId

Expand Down Expand Up @@ -1115,7 +1140,7 @@ def test_updating_venue_manual_address(
assert venue.contact.website == website
assert venue.contact.social_medias == social_medias

assert len(venue.action_history) == 1
assert len(venue.action_history) == 2

assert len(mails_testing.outbox) == 1
# check that email is sent when venue is set to permanent and has no image
Expand Down
100 changes: 77 additions & 23 deletions api/tests/routes/pro/patch_venue_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import pytest

from pcapi.connectors import acceslibre as acceslibre_connector
from pcapi.connectors.api_adresse import AddressInfo
import pcapi.connectors.entreprise.exceptions as entreprise_exceptions
from pcapi.core import search
Expand All @@ -15,6 +16,7 @@
import pcapi.core.offerers.models as offerers_models
from pcapi.core.users import factories as users_factories
from pcapi.core.users import testing as external_testing
from pcapi.models import db
from pcapi.utils.date import timespan_str_to_numrange


Expand Down Expand Up @@ -104,11 +106,15 @@ def test_should_update_venue(self, client) -> None:
}
]

assert len(venue.action_history) == 1
assert venue.action_history[0].actionType == history_models.ActionType.INFO_MODIFIED
assert venue.action_history[0].venueId == venue_id
assert venue.action_history[0].authorUser.id == user_offerer.user.id
assert venue.action_history[0].extraData == {
assert len(venue.action_history) == 2

update_action = [action for action in venue.action_history if action.extraData["modified_info"].get("street")][
0
]
assert update_action.actionType == history_models.ActionType.INFO_MODIFIED
assert update_action.venueId == venue_id
assert update_action.authorUser.id == user_offerer.user.id
assert update_action.extraData == {
"modified_info": {
"publicName": {"new_info": "Ma librairie", "old_info": "old name"},
"venueTypeCode": {
Expand Down Expand Up @@ -179,6 +185,23 @@ def test_should_update_venue(self, client) -> None:
},
}
}

acceslibre_action = [
action
for action in venue.action_history
if action.extraData["modified_info"].get("accessibilityProvider.externalAccessibilityId")
][0]
assert acceslibre_action.extraData["modified_info"] == {
"accessibilityProvider.externalAccessibilityId": {
"new_info": "mon-lieu-chez-acceslibre",
"old_info": None,
},
"accessibilityProvider.externalAccessibilityUrl": {
"new_info": "https://acceslibre.beta.gouv.fr/app/activite/mon-lieu-chez-acceslibre/",
"old_info": None,
},
}

assert (len(offerers_models.OffererAddress.query.all())) == 2
offerer_address = offerers_models.OffererAddress.query.order_by(
offerers_models.OffererAddress.id.desc()
Expand Down Expand Up @@ -335,27 +358,32 @@ def test_update_venue_location_with_manual_edition(self, client) -> None:
assert response.json["city"] == venue.city
assert response.json["siret"] == venue.siret
assert response.json["postalCode"] == venue.postalCode
assert len(venue.action_history) == 1
assert venue.action_history[0].actionType == history_models.ActionType.INFO_MODIFIED
assert venue.action_history[0].venueId == venue_id
assert venue.action_history[0].authorUser.id == user_offerer.user.id
assert venue.action_history[0].extraData["modified_info"]["street"] == {
assert len(venue.action_history) == 2

update_action = [action for action in venue.action_history if action.extraData["modified_info"].get("street")][
0
]
update_snapshot = update_action.extraData["modified_info"]
assert update_action.actionType == history_models.ActionType.INFO_MODIFIED
assert update_action.venueId == venue_id
assert update_action.authorUser.id == user_offerer.user.id
assert update_snapshot["street"] == {
"new_info": "3 Rue de Valois",
"old_info": "1 boulevard Poissonnière",
}
assert venue.action_history[0].extraData["modified_info"]["banId"] == {
assert update_snapshot["banId"] == {
"new_info": "75101_9575_00003",
"old_info": "75102_7560_00001",
}
assert venue.action_history[0].extraData["modified_info"]["latitude"] == {
assert update_snapshot["latitude"] == {
"new_info": "48.87171",
"old_info": "48.87004",
}
assert venue.action_history[0].extraData["modified_info"]["longitude"] == {
assert update_snapshot["longitude"] == {
"new_info": "2.30829",
"old_info": "2.3785",
}
assert venue.action_history[0].extraData["modified_info"]["postalCode"] == {
assert update_snapshot["postalCode"] == {
"new_info": "75001",
"old_info": "75000",
}
Expand Down Expand Up @@ -575,27 +603,32 @@ def test_update_should_be_able_to_update_venue_even_if_only_centroid_found(
assert response.json["city"] == venue.city
assert response.json["siret"] == venue.siret
assert response.json["postalCode"] == venue.postalCode
assert len(venue.action_history) == 1
assert venue.action_history[0].actionType == history_models.ActionType.INFO_MODIFIED
assert venue.action_history[0].venueId == venue_without_siret.id
assert venue.action_history[0].authorUser.id == user_offerer.user.id
assert venue.action_history[0].extraData["modified_info"]["street"] == {
assert len(venue.action_history) == 2

update_action = [action for action in venue.action_history if action.extraData["modified_info"].get("street")][
0
]
update_snapshot = update_action.extraData["modified_info"]
assert update_action.actionType == history_models.ActionType.INFO_MODIFIED
assert update_action.venueId == venue_without_siret.id
assert update_action.authorUser.id == user_offerer.user.id
assert update_snapshot["street"] == {
"new_info": None,
"old_info": "1 boulevard Poissonnière",
}
assert venue.action_history[0].extraData["modified_info"]["banId"] == {
assert update_snapshot["banId"] == {
"new_info": "58062",
"old_info": "75102_7560_00001",
}
assert venue.action_history[0].extraData["modified_info"]["latitude"] == {
assert update_snapshot["latitude"] == {
"new_info": "47.06664",
"old_info": "48.87004",
}
assert venue.action_history[0].extraData["modified_info"]["longitude"] == {
assert update_snapshot["longitude"] == {
"new_info": "3.93336",
"old_info": "2.3785",
}
assert venue.action_history[0].extraData["modified_info"]["postalCode"] == {
assert update_snapshot["postalCode"] == {
"new_info": "58120",
"old_info": "75002",
}
Expand Down Expand Up @@ -1078,6 +1111,27 @@ def test_no_venue_contact_add_contact(self, mock_request_url_scan, client) -> No
}
mock_request_url_scan.assert_called_once_with(venue_data["contact"]["website"], skip_if_recent_scan=True)

def test_resync_acceslibre_when_address_changes(self, client):
user = users_factories.UserFactory()
venue = offerers_factories.VenueFactory()
offerers_factories.UserOffererFactory(user=user, offerer=venue.managingOfferer)

venue_data = {
"street": "3 rue de Valois",
}

http_client = client.with_session_auth(email=user.email)
http_client.patch(f"/venues/{venue.id}", json=venue_data)

db.session.refresh(venue)
assert venue.accessibilityProvider.externalAccessibilityId == "mon-lieu-chez-acceslibre"
assert set(venue.accessibilityProvider.externalAccessibilityData["access_modality"]) == set(
[
acceslibre_connector.ExpectedFieldsEnum.EXTERIOR_ONE_LEVEL.value,
acceslibre_connector.ExpectedFieldsEnum.ENTRANCE_ONE_LEVEL.value,
]
)


class Returns400Test:
@pytest.mark.parametrize("data, key", venue_malformed_test_data)
Expand Down

0 comments on commit 8685ef6

Please sign in to comment.