diff --git a/api/src/pcapi/core/educational/api/offer.py b/api/src/pcapi/core/educational/api/offer.py index 9e290854c9c..e42859d89b7 100644 --- a/api/src/pcapi/core/educational/api/offer.py +++ b/api/src/pcapi/core/educational/api/offer.py @@ -22,6 +22,7 @@ from pcapi.core.educational.models import CollectiveOffer from pcapi.core.educational.models import HasImageMixin from pcapi.core.educational.utils import get_image_from_url +from pcapi.core.external.attributes.api import update_external_pro from pcapi.core.mails import transactional as transactional_mails from pcapi.core.object_storage import store_public_object from pcapi.core.offerers import api as offerers_api @@ -268,7 +269,13 @@ def create_collective_offer( formats=offer_data.formats, # type: ignore[arg-type] author=user, ) - collective_offer.bookingEmails = offer_data.booking_emails + + emails = offer_data.booking_emails + collective_offer.bookingEmails = emails + + # we update pro email data in sendinblue + for email in emails: + update_external_pro(email) db.session.add(collective_offer) db.session.commit() diff --git a/api/src/pcapi/core/educational/models.py b/api/src/pcapi/core/educational/models.py index 8872568cbd6..c22f21ed486 100644 --- a/api/src/pcapi/core/educational/models.py +++ b/api/src/pcapi/core/educational/models.py @@ -1873,6 +1873,9 @@ class CollectiveOfferTemplateEducationalRedactor(PcObject, Base, Model): ) +PROGRAM_MARSEILLE_EN_GRAND = "marseille_en_grand" + + class EducationalInstitutionProgramAssociation(Base, Model): """Association model between EducationalInstitution and EducationalInstitutionProgram (many-to-many) diff --git a/api/src/pcapi/core/educational/repository.py b/api/src/pcapi/core/educational/repository.py index bb8e1d9a0bc..21e3eb460b0 100644 --- a/api/src/pcapi/core/educational/repository.py +++ b/api/src/pcapi/core/educational/repository.py @@ -1346,3 +1346,20 @@ def fetch_venue_for_new_offer(venue_id: int, requested_provider_id: int) -> offe if not venue: raise offerers_exceptions.VenueNotFoundException() return typing.cast(offerers_models.Venue, venue) + + +def has_collective_offers_for_program_and_venue_ids(program_name: str, venue_ids: typing.Iterable[str]) -> bool: + query = ( + educational_models.CollectiveOffer.query.join( + educational_models.EducationalInstitution, educational_models.CollectiveOffer.institution + ) + .join(educational_models.EducationalInstitutionProgram, educational_models.EducationalInstitution.programs) + .filter( + educational_models.CollectiveOffer.venueId.in_(venue_ids), + educational_models.CollectiveOffer.validation == offer_mixin.OfferValidationStatus.APPROVED, + educational_models.EducationalInstitutionProgram.name == program_name, + ) + .exists() + ) + + return db.session.query(query).scalar() diff --git a/api/src/pcapi/core/external/attributes/api.py b/api/src/pcapi/core/external/attributes/api.py index a9efd1934b6..5123382fa0a 100644 --- a/api/src/pcapi/core/external/attributes/api.py +++ b/api/src/pcapi/core/external/attributes/api.py @@ -12,6 +12,7 @@ from pcapi.core.bookings import repository as bookings_repository from pcapi.core.categories import categories from pcapi.core.educational import models as educational_models +from pcapi.core.educational.repository import has_collective_offers_for_program_and_venue_ids from pcapi.core.external.attributes import models from pcapi.core.external.batch import update_user_attributes as update_batch_user from pcapi.core.external.sendinblue import update_contact_attributes as update_sendinblue_user @@ -276,6 +277,7 @@ def get_pro_attributes(email: str) -> models.ProAttributes: offerers_models.Venue.isVirtual, offerers_models.Venue.isPermanent, offerers_models.Venue._bannerUrl, + offerers_models.Venue.adageId, ), contains_eager(offerers_models.Venue.managingOfferer) .load_only(offerers_models.Offerer.name) @@ -287,12 +289,20 @@ def get_pro_attributes(email: str) -> models.ProAttributes: .all() ) + venue_ids = {venue.id for venue in venues} + is_eac_meg = has_collective_offers_for_program_and_venue_ids( + educational_models.PROGRAM_MARSEILLE_EN_GRAND, venue_ids + ) + if venues: + all_venues += venues for venue in venues: offerers_names.add(venue.managingOfferer.name) offerers_tags.update(tag.label for tag in venue.managingOfferer.tags) + has_individual_offers = offerers_repository.venues_have_offers(*venues) + attributes.update( { "dms_application_submitted": any(venue.hasPendingBankInformationApplication for venue in venues), @@ -329,6 +339,7 @@ def get_pro_attributes(email: str) -> models.ProAttributes: departement_code={venue.departementCode for venue in all_venues if venue.departementCode}, postal_code={venue.postalCode for venue in all_venues if venue.postalCode}, has_collective_offers=has_collective_offers, + is_eac_meg=is_eac_meg, **attributes, ) diff --git a/api/src/pcapi/core/external/attributes/models.py b/api/src/pcapi/core/external/attributes/models.py index 5f25e7fbcc3..945ec63ef22 100644 --- a/api/src/pcapi/core/external/attributes/models.py +++ b/api/src/pcapi/core/external/attributes/models.py @@ -91,6 +91,7 @@ class ProAttributes: has_banner_url: bool | None = ( None # Set to False when at least one permanent venue doesn't have a banner URL, True otherwise ) + is_eac_meg: bool | None = None # At least one collective offer with 'Marseille en Grand' @dataclass diff --git a/api/src/pcapi/core/external/sendinblue.py b/api/src/pcapi/core/external/sendinblue.py index d39a65085ff..a1a3e64aac2 100644 --- a/api/src/pcapi/core/external/sendinblue.py +++ b/api/src/pcapi/core/external/sendinblue.py @@ -89,6 +89,7 @@ class SendinblueAttributes(Enum): VENUE_NAME = "VENUE_NAME" VENUE_TYPE = "VENUE_TYPE" IS_EAC = "IS_EAC" + IS_EAC_MEG = "EAC_MEG" @classmethod def list(cls) -> list[str]: @@ -244,6 +245,7 @@ def format_user_attributes(attributes: attributes_models.UserAttributes | attrib SendinblueAttributes.VENUE_NAME.value: _get_attr(attributes, "venues_names", format_list), SendinblueAttributes.VENUE_TYPE.value: _get_attr(attributes, "venues_types", format_list), SendinblueAttributes.IS_EAC.value: _get_attr(attributes, "is_eac"), + SendinblueAttributes.IS_EAC_MEG.value: _get_attr(attributes, "is_eac_meg"), } diff --git a/api/tests/core/bookings/test_api.py b/api/tests/core/bookings/test_api.py index 0aa7bfe2937..73b17357f19 100644 --- a/api/tests/core/bookings/test_api.py +++ b/api/tests/core/bookings/test_api.py @@ -182,7 +182,7 @@ def test_create_booking(self, mocked_async_index_offer_ids, app): # 1 - SELECT from offer that I don't get # 1 - SELECT bookings for the venue ??? # 1 - SELECT feature - with assert_num_queries(35): + with assert_num_queries(36): booking = api.book_offer(beneficiary=beneficiary, stock_id=stock_id, quantity=1) # One request should have been sent to Batch to trigger the event diff --git a/api/tests/core/educational/test_repository.py b/api/tests/core/educational/test_repository.py index 6d9f3564d8d..f0313f91024 100644 --- a/api/tests/core/educational/test_repository.py +++ b/api/tests/core/educational/test_repository.py @@ -12,6 +12,7 @@ from pcapi.core.educational.models import CollectiveOfferDisplayedStatus from pcapi.core.offerers import factories as offerers_factories from pcapi.core.offers.repository import _filter_collective_offers_by_statuses +from pcapi.core.testing import assert_num_queries from pcapi.core.users import factories as users_factories from pcapi.models import offer_mixin @@ -621,3 +622,37 @@ def test_filter_with_statuses_has_none(self, app): # Then assert filtered_nostatus_query.count() == 2 assert set(filtered_nostatus_query.all()) == {pending_offer, booked_offer} + + +class HasCollectiveOffersForProgramAndVenueIdsTest: + + def test_has_collective_offers_for_program_and_venueids_test(self, app): + program = educational_factories.EducationalInstitutionProgramFactory(name="program") + other_program = educational_factories.EducationalInstitutionProgramFactory(name="other_program") + + venue = offerers_factories.VenueFactory() + other_venue = offerers_factories.VenueFactory() + + institution = educational_factories.EducationalInstitutionFactory(programs=[program]) + other_institution = educational_factories.EducationalInstitutionFactory(programs=[other_program]) + + _collective_offer_with_program = educational_factories.CollectiveOfferFactory( + venue=venue, institution=institution + ) + _collective_offer_without_program = educational_factories.CollectiveOfferFactory(venue=venue) + _collective_offer_with_other_program = educational_factories.CollectiveOfferFactory( + venue=other_venue, institution=other_institution + ) + + venue_id = venue.id + + with assert_num_queries(1): + assert educational_repository.has_collective_offers_for_program_and_venue_ids("program", [venue_id]) == True + + assert ( + educational_repository.has_collective_offers_for_program_and_venue_ids("other_program", [venue.id]) == False + ) + + assert ( + educational_repository.has_collective_offers_for_program_and_venue_ids("program", [other_venue.id]) == False + ) diff --git a/api/tests/core/external/__init__.py b/api/tests/core/external/__init__.py index ce97c109fd1..e123fee3d11 100644 --- a/api/tests/core/external/__init__.py +++ b/api/tests/core/external/__init__.py @@ -83,4 +83,5 @@ has_bookings=True, is_eac=False, has_banner_url=True, + is_eac_meg=False, ) diff --git a/api/tests/core/external/external_pro_test.py b/api/tests/core/external/external_pro_test.py index 697258210cc..4299e9e3dba 100644 --- a/api/tests/core/external/external_pro_test.py +++ b/api/tests/core/external/external_pro_test.py @@ -23,10 +23,12 @@ # 1 query on user table with joinedload # 1 query on venue table with joinedload # 2 extra SQL queries: select exists on offer and booking tables -EXPECTED_PRO_ATTR_NUM_QUERIES = 5 +# 1 extra query to check if the venue has any related collective offer with 'marseille en grand' +# 1 check if the venue is concerned with marseille_en_grand +EXPECTED_PRO_ATTR_NUM_QUERIES = 6 -def _build_params(subs, virt, perman, draft, accep, offer, book, attach, colloff, tploff): +def _build_params(subs, virt, perman, draft, accep, offer, book, attach, colloff, tploff, megoff): return pytest.param( subs, virt, @@ -38,25 +40,27 @@ def _build_params(subs, virt, perman, draft, accep, offer, book, attach, colloff attach, colloff, tploff, + megoff, id=( f"sub:{subs}, vir:{virt}, per:{perman}, dra:{draft}, " f"acc:{accep}, off:{offer}, boo:{book}, " - f"att:{attach}, colloff:{colloff}, tploff:{tploff}" + f"att:{attach}, colloff:{colloff}, tploff:{tploff}, megoff:{megoff}" ), ) @pytest.mark.parametrize( "enable_subscription,create_virtual,create_permanent,create_dms_draft,create_dms_accepted," - "create_individual_offer,create_booking,attached,create_collective_offer,create_template_offer", + "create_individual_offer,create_booking,attached,create_collective_offer,create_template_offer,create_collective_offer_meg", [ - # subs, virt, perman, draft, accep, offer, book, attach, colloff, tploff - _build_params(False, False, False, False, False, False, False, "none", False, False), - _build_params(True, False, True, True, False, True, False, "one", True, False), - _build_params(False, True, False, False, True, True, False, "all", False, True), - _build_params(True, True, True, True, True, True, True, "none", True, True), - _build_params(False, True, True, False, True, False, False, "one", True, False), - _build_params(True, True, True, True, True, True, True, "all", True, True), + # subs, virt, perman, draft, accep, offer, book, attach, colloff, tploff, megoff + _build_params(False, False, False, False, False, False, False, "none", False, False, False), + _build_params(True, False, True, True, False, True, False, "one", True, False, False), + _build_params(False, True, False, False, True, True, False, "all", False, True, False), + _build_params(True, True, True, True, True, True, True, "none", True, True, False), + _build_params(False, True, True, False, True, False, False, "one", True, False, False), + _build_params(True, True, True, True, True, True, True, "all", True, True, False), + _build_params(False, False, False, False, False, False, False, "none", True, False, True), ], ) def test_update_external_pro_user_attributes( @@ -70,6 +74,7 @@ def test_update_external_pro_user_attributes( attached, create_collective_offer, create_template_offer, + create_collective_offer_meg, ): email = "juste.leblanc@example.net" @@ -89,6 +94,19 @@ def test_update_external_pro_user_attributes( if attached in ("one", "all"): offerers_factories.UserOffererFactory(user=ProFactory(), offerer=offerer1) offerers_factories.UserOffererFactory(user=pro_user, offerer=offerer1) + + collective_offers = [] + if create_collective_offer: + if create_collective_offer_meg: + program = educational_factories.EducationalInstitutionProgramFactory(name="marseille_en_grand") + institution = educational_factories.EducationalInstitutionFactory(programs=[program]) + + collective_offer = educational_factories.CollectiveOfferFactory(isActive=True, institution=institution) + else: + collective_offer = educational_factories.CollectiveOfferFactory(isActive=True) + + collective_offers.append(collective_offer) + venue1 = offerers_factories.VenueFactory( managingOfferer=offerer1, name="Cinéma de la plage", @@ -100,9 +118,8 @@ def test_update_external_pro_user_attributes( isPermanent=create_permanent, venueTypeCode=VenueTypeCode.MOVIE, venueLabelId=venue_label_a.id, - collectiveOffers=( - [educational_factories.CollectiveOfferFactory(isActive=True)] if create_collective_offer else [] - ), + adageId="12345" if create_collective_offer else None, + collectiveOffers=collective_offers, collectiveOfferTemplates=( [educational_factories.CollectiveOfferTemplateFactory(isActive=True)] if create_template_offer else [] ), @@ -222,7 +239,9 @@ def test_update_external_pro_user_attributes( venueTypeCode=VenueTypeCode.CONCERT_HALL, # different from others ) - with assert_num_queries(EXPECTED_PRO_ATTR_NUM_QUERIES): + num_queries = EXPECTED_PRO_ATTR_NUM_QUERIES + + with assert_num_queries(num_queries): attributes = get_pro_attributes(email) assert attributes.is_pro is True @@ -272,6 +291,7 @@ def test_update_external_pro_user_attributes( assert attributes.has_bookings is create_booking assert attributes.has_collective_offers == (create_collective_offer or create_template_offer) assert attributes.has_offers == (create_individual_offer or create_collective_offer or create_template_offer) + assert attributes.is_eac_meg == create_collective_offer_meg def test_update_external_pro_user_attributes_no_offerer_no_venue(): @@ -336,7 +356,7 @@ def test_update_external_pro_booking_email_attributes(): venueTypeCode=VenueTypeCode.MUSEUM, ) - with assert_num_queries(4): + with assert_num_queries(5): attributes = get_pro_attributes(email) assert attributes.is_pro is True @@ -382,7 +402,7 @@ def test_update_external_pro_booking_email_attributes_for_permanent_venue_with_b _bannerUrl="https://example.net/banner.jpg", ) - with assert_num_queries(4): + with assert_num_queries(5): attributes = get_pro_attributes(email) assert attributes.isPermanent is True assert attributes.has_banner_url is True @@ -403,7 +423,7 @@ def test_update_external_pro_booking_email_attributes_for_non_permanent_venue_wi _bannerUrl="https://example.net/banner.jpg", ) - with assert_num_queries(4): + with assert_num_queries(5): attributes = get_pro_attributes(email) assert attributes.isPermanent is False assert attributes.has_banner_url is True @@ -423,7 +443,7 @@ def test_update_external_pro_booking_email_attributes_for_non_permanent_venue_wi venueTypeCode=VenueTypeCode.MUSEUM, ) - with assert_num_queries(4): + with assert_num_queries(5): attributes = get_pro_attributes(email) assert attributes.isPermanent is False assert attributes.has_banner_url is True @@ -431,7 +451,8 @@ def test_update_external_pro_booking_email_attributes_for_non_permanent_venue_wi def test_update_external_pro_removed_email_attributes(): # only 2 queries: user and venue - nothing found - with assert_num_queries(2): + # one query for marseille_en_grand + with assert_num_queries(3): attributes = get_pro_attributes("removed@example.net") assert attributes.is_pro is True diff --git a/api/tests/core/external/sendinblue_test.py b/api/tests/core/external/sendinblue_test.py index 3faa90fa196..5c5130419d5 100644 --- a/api/tests/core/external/sendinblue_test.py +++ b/api/tests/core/external/sendinblue_test.py @@ -93,6 +93,7 @@ def test_format_attributes(self): "VENUE_NAME": None, "VENUE_TYPE": None, "IS_EAC": None, + "EAC_MEG": None, } def test_format_pro_attributes(self): @@ -156,6 +157,7 @@ def test_format_pro_attributes(self): "VENUE_NAME": "Venue Name 1,Venue Name 2", "VENUE_TYPE": "BOOKSTORE,MOVIE", "IS_EAC": False, + "EAC_MEG": False, } @@ -216,10 +218,10 @@ def setup_method(self): ), ] - self.expected_header = "BOOKED_OFFER_CATEGORIES;BOOKED_OFFER_CATEGORIES_COUNT;BOOKED_OFFER_SUBCATEGORIES;BOOKING_COUNT;BOOKING_VENUES_COUNT;CREDIT;DATE_CREATED;DATE_OF_BIRTH;DEPARTMENT_CODE;DEPOSITS_COUNT;DEPOSIT_ACTIVATION_DATE;DEPOSIT_EXPIRATION_DATE;DMS_APPLICATION_APPROVED;DMS_APPLICATION_SUBMITTED;ELIGIBILITY;FIRSTNAME;HAS_BANNER_URL;HAS_BOOKINGS;HAS_COLLECTIVE_OFFERS;HAS_COMPLETED_ID_CHECK;HAS_OFFERS;INITIAL_CREDIT;IS_ACTIVE_PRO;IS_BENEFICIARY;IS_BENEFICIARY_18;IS_BOOKING_EMAIL;IS_CURRENT_BENEFICIARY;IS_EAC;IS_ELIGIBLE;IS_EMAIL_VALIDATED;IS_FORMER_BENEFICIARY;IS_PERMANENT;IS_PRO;IS_TAGGED_COLLECTIVITE;IS_UNDERAGE_BENEFICIARY;IS_USER_EMAIL;IS_VIRTUAL;LASTNAME;LAST_BOOKING_DATE;LAST_FAVORITE_CREATION_DATE;LAST_VISIT_DATE;MARKETING_EMAIL_SUBSCRIPTION;MOST_BOOKED_MOVIE_GENRE;MOST_BOOKED_MUSIC_TYPE;MOST_BOOKED_OFFER_SUBCATEGORY;MOST_FAVORITE_OFFER_SUBCATEGORIES;OFFERER_NAME;PERMANENT_THEME_PREFERENCE;POSTAL_CODE;PRODUCT_BRUT_X_USE_DATE;USER_ID;USER_IS_ATTACHED;USER_IS_CREATOR;VENUE_COUNT;VENUE_LABEL;VENUE_NAME;VENUE_TYPE;EMAIL" - self.eren_expected_file_body = "CINEMA,LIVRE;2;ABO_LIVRE_NUMERIQUE,CARTE_CINE_ILLIMITE,CINE_PLEIN_AIR;4;3;480.00;06-02-2021;06-05-2003;12;1;;;;;age-18;First name;;;;Yes;;500;;Yes;Yes;;Yes;;Yes;Yes;No;;No;;No;;;Last name;06-05-2021;;;Yes;COMEDY;900;CINE_PLEIN_AIR;CINE_PLEIN_AIR,SUPPORT_PHYSIQUE_FILM;;cinema;;06-05-2021;1;;;;;;;eren.yeager@shinganshina.paradis" - self.mikasa_expected_file_body = "CINEMA,LIVRE;2;ABO_LIVRE_NUMERIQUE,CARTE_CINE_ILLIMITE,CINE_PLEIN_AIR;4;3;480.00;06-02-2021;06-05-2003;12;1;;;;;age-18;First name;;;Yes;Yes;;500;;Yes;Yes;;Yes;;Yes;Yes;No;;Yes;;No;;;Last name;06-05-2021;;;Yes;COMEDY;900;CINE_PLEIN_AIR;CINE_PLEIN_AIR,SUPPORT_PHYSIQUE_FILM;;cinema;;06-05-2021;2;;;;;;;mikasa.ackerman@shinganshina.paradis" - self.armin_expected_file_body = "CINEMA,LIVRE;2;ABO_LIVRE_NUMERIQUE,CARTE_CINE_ILLIMITE,CINE_PLEIN_AIR;4;3;480.00;06-02-2021;06-05-2003;12;1;;;;;age-18;First name;;;;Yes;;500;;Yes;Yes;;Yes;;Yes;Yes;No;;No;;No;;;Last name;06-05-2021;;;Yes;COMEDY;900;CINE_PLEIN_AIR;CINE_PLEIN_AIR,SUPPORT_PHYSIQUE_FILM;;cinema;;06-05-2021;3;;;;;;;armin.arlert@shinganshina.paradis" + self.expected_header = "BOOKED_OFFER_CATEGORIES;BOOKED_OFFER_CATEGORIES_COUNT;BOOKED_OFFER_SUBCATEGORIES;BOOKING_COUNT;BOOKING_VENUES_COUNT;CREDIT;DATE_CREATED;DATE_OF_BIRTH;DEPARTMENT_CODE;DEPOSITS_COUNT;DEPOSIT_ACTIVATION_DATE;DEPOSIT_EXPIRATION_DATE;DMS_APPLICATION_APPROVED;DMS_APPLICATION_SUBMITTED;EAC_MEG;ELIGIBILITY;FIRSTNAME;HAS_BANNER_URL;HAS_BOOKINGS;HAS_COLLECTIVE_OFFERS;HAS_COMPLETED_ID_CHECK;HAS_OFFERS;INITIAL_CREDIT;IS_ACTIVE_PRO;IS_BENEFICIARY;IS_BENEFICIARY_18;IS_BOOKING_EMAIL;IS_CURRENT_BENEFICIARY;IS_EAC;IS_ELIGIBLE;IS_EMAIL_VALIDATED;IS_FORMER_BENEFICIARY;IS_PERMANENT;IS_PRO;IS_TAGGED_COLLECTIVITE;IS_UNDERAGE_BENEFICIARY;IS_USER_EMAIL;IS_VIRTUAL;LASTNAME;LAST_BOOKING_DATE;LAST_FAVORITE_CREATION_DATE;LAST_VISIT_DATE;MARKETING_EMAIL_SUBSCRIPTION;MOST_BOOKED_MOVIE_GENRE;MOST_BOOKED_MUSIC_TYPE;MOST_BOOKED_OFFER_SUBCATEGORY;MOST_FAVORITE_OFFER_SUBCATEGORIES;OFFERER_NAME;PERMANENT_THEME_PREFERENCE;POSTAL_CODE;PRODUCT_BRUT_X_USE_DATE;USER_ID;USER_IS_ATTACHED;USER_IS_CREATOR;VENUE_COUNT;VENUE_LABEL;VENUE_NAME;VENUE_TYPE;EMAIL" + self.eren_expected_file_body = "CINEMA,LIVRE;2;ABO_LIVRE_NUMERIQUE,CARTE_CINE_ILLIMITE,CINE_PLEIN_AIR;4;3;480.00;06-02-2021;06-05-2003;12;1;;;;;;age-18;First name;;;;Yes;;500;;Yes;Yes;;Yes;;Yes;Yes;No;;No;;No;;;Last name;06-05-2021;;;Yes;COMEDY;900;CINE_PLEIN_AIR;CINE_PLEIN_AIR,SUPPORT_PHYSIQUE_FILM;;cinema;;06-05-2021;1;;;;;;;eren.yeager@shinganshina.paradis" + self.mikasa_expected_file_body = "CINEMA,LIVRE;2;ABO_LIVRE_NUMERIQUE,CARTE_CINE_ILLIMITE,CINE_PLEIN_AIR;4;3;480.00;06-02-2021;06-05-2003;12;1;;;;;;age-18;First name;;;Yes;Yes;;500;;Yes;Yes;;Yes;;Yes;Yes;No;;Yes;;No;;;Last name;06-05-2021;;;Yes;COMEDY;900;CINE_PLEIN_AIR;CINE_PLEIN_AIR,SUPPORT_PHYSIQUE_FILM;;cinema;;06-05-2021;2;;;;;;;mikasa.ackerman@shinganshina.paradis" + self.armin_expected_file_body = "CINEMA,LIVRE;2;ABO_LIVRE_NUMERIQUE,CARTE_CINE_ILLIMITE,CINE_PLEIN_AIR;4;3;480.00;06-02-2021;06-05-2003;12;1;;;;;;age-18;First name;;;;Yes;;500;;Yes;Yes;;Yes;;Yes;Yes;No;;No;;No;;;Last name;06-05-2021;;;Yes;COMEDY;900;CINE_PLEIN_AIR;CINE_PLEIN_AIR,SUPPORT_PHYSIQUE_FILM;;cinema;;06-05-2021;3;;;;;;;armin.arlert@shinganshina.paradis" def test_build_file_body(self): expected = ( diff --git a/api/tests/routes/native/v1/bookings_test.py b/api/tests/routes/native/v1/bookings_test.py index 095a7ba0238..9c9799b803f 100644 --- a/api/tests/routes/native/v1/bookings_test.py +++ b/api/tests/routes/native/v1/bookings_test.py @@ -988,7 +988,7 @@ def test_cancel_booking(self, client): booking = booking_factories.BookingFactory(user=user) client = client.with_token(self.identifier) - with assert_num_queries(24): + with assert_num_queries(25): response = client.post(f"/native/v1/bookings/{booking.id}/cancel") assert response.status_code == 204 @@ -1003,7 +1003,7 @@ def test_cancel_booking_trigger_recredit_event(self, client): booking = booking_factories.BookingFactory(user=user) client = client.with_token(self.identifier) - with assert_num_queries(24): + with assert_num_queries(25): response = client.post(f"/native/v1/bookings/{booking.id}/cancel") assert response.status_code == 204 diff --git a/api/tests/routes/pro/post_collective_offers_test.py b/api/tests/routes/pro/post_collective_offers_test.py index 5fea0cd9e0f..e6ef83f4b04 100644 --- a/api/tests/routes/pro/post_collective_offers_test.py +++ b/api/tests/routes/pro/post_collective_offers_test.py @@ -9,6 +9,7 @@ from pcapi.core.educational.models import CollectiveOffer import pcapi.core.offerers.factories as offerers_factories from pcapi.core.testing import override_features +from pcapi.core.users import testing as sendinblue_testing import pcapi.core.users.factories as users_factories @@ -107,6 +108,9 @@ def test_create_collective_offer(self, client): assert_offer_values(offer, data, user, offerer) + # 2 requests (for 2 bookingEmail) for sendinblue + assert len(sendinblue_testing.sendinblue_requests) == 3 + def test_create_collective_offer_college_6(self, client): # Given venue = offerers_factories.VenueFactory() diff --git a/api/tests/scripts/external_users/batch_update_users_attributes_test.py b/api/tests/scripts/external_users/batch_update_users_attributes_test.py index c1e7b869f45..da9765059e4 100644 --- a/api/tests/scripts/external_users/batch_update_users_attributes_test.py +++ b/api/tests/scripts/external_users/batch_update_users_attributes_test.py @@ -138,6 +138,7 @@ def test_format_sendinblue_user(): "DMS_APPLICATION_APPROVED": None, "DMS_APPLICATION_SUBMITTED": None, "ELIGIBILITY": user.eligibility, + "EAC_MEG": None, "FIRSTNAME": "Jeanne", "HAS_BANNER_URL": None, "HAS_BOOKINGS": None,