Skip to content

Commit

Permalink
(PC-31475)[ADAGE] feat: Add an attribut in brevo for Marseille en Grand
Browse files Browse the repository at this point in the history
  • Loading branch information
rprasquier-pass committed Sep 4, 2024
1 parent 04a96b7 commit f792131
Show file tree
Hide file tree
Showing 11 changed files with 54 additions and 6 deletions.
9 changes: 8 additions & 1 deletion api/src/pcapi/core/educational/api/offer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
3 changes: 3 additions & 0 deletions api/src/pcapi/core/educational/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,9 @@ class EducationalInstitution(PcObject, Base, Model):
def full_name(self) -> str:
return f"{self.institutionType} {self.name}".strip()

def with_program(self, program_name: str) -> bool:
return any(program.name == program_name for program in self.programs)


class EducationalYear(PcObject, Base, Model):
__tablename__ = "educational_year"
Expand Down
14 changes: 14 additions & 0 deletions api/src/pcapi/core/external/attributes/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,29 @@ def get_pro_attributes(email: str) -> models.ProAttributes:
.load_only(offerers_models.OffererTag.label),
joinedload(offerers_models.Venue.bankInformation).load_only(finance_models.BankInformation.status),
joinedload(offerers_models.Venue.venueLabel).load_only(offerers_models.VenueLabel.label),
joinedload(offerers_models.Venue.collectiveOffers)
.subqueryload(educational_models.CollectiveOffer.institution)
.subqueryload(educational_models.EducationalInstitution.programs)
.load_only(educational_models.EducationalInstitutionProgram.name),
)
.all()
)

if venues:
has_collective_offers_marseille_en_grand = False

all_venues += venues
for venue in venues:
offerers_names.add(venue.managingOfferer.name)
offerers_tags.update(tag.label for tag in venue.managingOfferer.tags)

for collective_offer in venue.collectiveOffers:
institution = collective_offer.institution
if institution and institution.with_program("marseille_en_grand"):
has_collective_offers_marseille_en_grand = True

has_individual_offers = offerers_repository.venues_have_offers(*venues)

attributes.update(
{
"dms_application_submitted": any(venue.hasPendingBankInformationApplication for venue in venues),
Expand All @@ -303,6 +316,7 @@ def get_pro_attributes(email: str) -> models.ProAttributes:
"has_individual_offers": has_individual_offers,
"has_bookings": bookings_repository.venues_have_bookings(*venues),
"has_banner_url": all(venue._bannerUrl for venue in venues if venue.isPermanent),
"eac_meg": has_collective_offers_marseille_en_grand,
}
)

Expand Down
1 change: 1 addition & 0 deletions api/src/pcapi/core/external/attributes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
eac_meg: bool | None = None # At least one collective offer with 'Marseille en Grand'


@dataclass
Expand Down
2 changes: 2 additions & 0 deletions api/src/pcapi/core/external/sendinblue.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class SendinblueAttributes(Enum):
VENUE_NAME = "VENUE_NAME"
VENUE_TYPE = "VENUE_TYPE"
IS_EAC = "IS_EAC"
EAC_MEG = "EAC_MEG"

@classmethod
def list(cls) -> list[str]:
Expand Down Expand Up @@ -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.EAC_MEG.value: _get_attr(attributes, "eac_meg"),
}


Expand Down
9 changes: 9 additions & 0 deletions api/tests/core/educational/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,15 @@ def test_unique_program_for_an_educational_institution(self):
institution.programs = [program1, program2]
db.session.commit()

def test_with_program(self):
program1 = factories.EducationalInstitutionProgramFactory(name="under_test")
_program2 = factories.EducationalInstitutionProgramFactory(name="not_to_be_found")

institution = factories.EducationalInstitutionFactory(programs=[program1])

assert institution.with_program("under_test")
assert not institution.with_program("not_to_be_found")


class CollectiveOfferDisplayedStatusTest:
@pytest.mark.parametrize("status", set(CollectiveOfferDisplayedStatus))
Expand Down
1 change: 1 addition & 0 deletions api/tests/core/external/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,5 @@
has_bookings=True,
is_eac=False,
has_banner_url=True,
eac_meg=False,
)
7 changes: 6 additions & 1 deletion api/tests/core/external/external_pro_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
# 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
# 1 query on educational_institution for program (meg) table with joinedload
EXPECTED_PRO_ATTR_NUM_QUERIES = 5


Expand Down Expand Up @@ -222,7 +223,11 @@ 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
if create_permanent:
num_queries += 1

with assert_num_queries(num_queries):
attributes = get_pro_attributes(email)

assert attributes.is_pro is True
Expand Down
10 changes: 6 additions & 4 deletions api/tests/core/external/sendinblue_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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,
}


Expand Down Expand Up @@ -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;;;;;;;[email protected]"
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;;;;;;;[email protected]"
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;;;;;;;[email protected]"
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;;;;;;;[email protected]"
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;;;;;;;[email protected]"
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;;;;;;;[email protected]"

def test_build_file_body(self):
expected = (
Expand Down
3 changes: 3 additions & 0 deletions api/tests/routes/pro/post_collective_offers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -107,6 +108,8 @@ def test_create_collective_offer(self, client):

assert_offer_values(offer, data, user, offerer)

assert len(sendinblue_testing.sendinblue_requests) == 3

def test_create_collective_offer_college_6(self, client):
# Given
venue = offerers_factories.VenueFactory()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit f792131

Please sign in to comment.