From dafa1324c4f1e2a8a152dfce9bdf2ff76b9d7ba4 Mon Sep 17 00:00:00 2001 From: Raphael Prasquier <171559546+rprasquier-pass@users.noreply.github.com> Date: Fri, 18 Oct 2024 14:31:39 +0200 Subject: [PATCH] (PC-32511)[PRO] feat: Add data in sandbox to ease testing of displayedStatus --- api/src/pcapi/core/educational/factories.py | 1 + .../create_offers.py | 204 ++++++++++++++++++ .../create_users_and_offerers.py | 8 + .../create_venues.py | 15 ++ 4 files changed, 228 insertions(+) diff --git a/api/src/pcapi/core/educational/factories.py b/api/src/pcapi/core/educational/factories.py index c3b610614e1..eaf4d903208 100644 --- a/api/src/pcapi/core/educational/factories.py +++ b/api/src/pcapi/core/educational/factories.py @@ -260,6 +260,7 @@ class Meta: ) ) confirmationLimitDate = factory.LazyFunction(lambda: datetime.datetime.utcnow() - datetime.timedelta(days=1)) + cancellationReason = None educationalInstitution = factory.SubFactory(EducationalInstitutionFactory) educationalYear = factory.SubFactory(EducationalYearFactory) educationalRedactor = factory.SubFactory(EducationalRedactorFactory) diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_offers.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_offers.py index daa6b022e94..18658f27f2c 100644 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_offers.py +++ b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_offers.py @@ -4,6 +4,8 @@ from itertools import count from itertools import cycle import typing +from typing import Optional +from typing import TypedDict from pcapi import settings from pcapi.core import search @@ -95,6 +97,17 @@ def create_offers( reimbursed_booking=False, ) + # eac_with_displayed_status_cases + offerer = next(o for o in offerers if o.name == "eac_with_displayed_status_cases") + provider = create_collective_api_provider(offerer.managedVenues) + create_offers_booking_with_different_displayed_status( + provider=provider, + offerer=offerer, + institutions=institutions, + domains=domains, + national_programs=national_programs, + ) + search.index_all_collective_offers_and_templates() @@ -352,6 +365,197 @@ def add_image_to_offer(offer: educational_models.HasImageMixin, image_name: str) offer.set_image(image=file.read(), credit="CC-BY-SA WIKIPEDIA", crop_params=DO_NOT_CROP) +def create_offers_booking_with_different_displayed_status( + *, + provider: providers_models.Provider, + offerer: offerers_models.Offerer, + institutions: list[educational_models.EducationalInstitution], + domains: list[educational_models.EducationalDomain], + national_programs: list[educational_models.NationalProgram], +) -> tuple[list[educational_models.CollectiveOffer], list[educational_models.CollectiveBooking]]: + offers = [] + bookings: list[educational_models.CollectiveBooking] = [] + + current_ansco = educational_models.EducationalYear.query.filter( + educational_models.EducationalYear.beginningDate <= datetime.utcnow(), + educational_models.EducationalYear.expirationDate >= datetime.utcnow(), + ).one() + domains_iterator = cycle(domains) + venue_iterator = cycle(offerer.managedVenues) + institution_iterator = cycle(institutions) + + today = datetime.utcnow() + in_two_weeks = today + timedelta(days=14) + in_four_weeks = today + timedelta(days=28) + + two_weeks_ago = today - timedelta(days=14) + four_weeks_ago = today - timedelta(days=28) + + yesterday = today - timedelta(days=1) + + class OfferAttributes(TypedDict, total=False): + bookingLimitDatetime: datetime + beginningDatetime: datetime + endDatetime: datetime + lastBookingStatus: Optional[educational_models.CollectiveBookingStatus] + cancellationReason: Optional[educational_models.CollectiveBookingCancellationReasons] + + options: dict[str, OfferAttributes] = { + # no bookings + "Amsterdam": { + "bookingLimitDatetime": in_two_weeks, + "beginningDatetime": in_four_weeks, + "endDatetime": in_four_weeks, + "lastBookingStatus": None, + }, + "Athènes": { + "bookingLimitDatetime": two_weeks_ago, + "beginningDatetime": in_two_weeks, + "endDatetime": in_two_weeks, + "lastBookingStatus": None, + }, + "Berlin": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": two_weeks_ago, + "endDatetime": in_two_weeks, + "lastBookingStatus": None, + }, + "Bratislava": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": four_weeks_ago, + "endDatetime": four_weeks_ago, + "lastBookingStatus": None, + }, + # with a pending booking + "Bruxelles": { + "bookingLimitDatetime": in_two_weeks, + "beginningDatetime": in_four_weeks, + "endDatetime": in_four_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.PENDING, + }, + "Bucarest": { + "bookingLimitDatetime": two_weeks_ago, + "beginningDatetime": in_two_weeks, + "endDatetime": in_two_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.PENDING, + }, + # with a cancelled booking due to expiration + "Budapest": { + "bookingLimitDatetime": two_weeks_ago, + "beginningDatetime": in_two_weeks, + "endDatetime": in_two_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CANCELLED, + "cancellationReason": educational_models.CollectiveBookingCancellationReasons.EXPIRED, + }, + "Copenhague": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": two_weeks_ago, + "endDatetime": in_two_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CANCELLED, + "cancellationReason": educational_models.CollectiveBookingCancellationReasons.EXPIRED, + }, + # with a confirmed booking + "Dublin": { + "bookingLimitDatetime": in_two_weeks, + "beginningDatetime": in_four_weeks, + "endDatetime": in_four_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CONFIRMED, + }, + "Helsinki": { + "bookingLimitDatetime": two_weeks_ago, + "beginningDatetime": in_two_weeks, + "endDatetime": in_two_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CONFIRMED, + }, + "La Valette": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": two_weeks_ago, + "endDatetime": in_two_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CONFIRMED, + }, + "Lisbonne": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": yesterday, + "endDatetime": yesterday, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CONFIRMED, + }, + # with a used booking + "Ljubljana": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": four_weeks_ago, + "endDatetime": four_weeks_ago, + "lastBookingStatus": educational_models.CollectiveBookingStatus.USED, + }, + "Luxembourg": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": four_weeks_ago, + "endDatetime": four_weeks_ago, + "lastBookingStatus": educational_models.CollectiveBookingStatus.REIMBURSED, + }, + # with a cancelled booking + "Madrid": { + "bookingLimitDatetime": in_two_weeks, + "beginningDatetime": in_four_weeks, + "endDatetime": in_four_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CANCELLED, + "cancellationReason": educational_models.CollectiveBookingCancellationReasons.OFFERER, + }, + "Nicosie": { + "bookingLimitDatetime": two_weeks_ago, + "beginningDatetime": in_two_weeks, + "endDatetime": in_two_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CANCELLED, + "cancellationReason": educational_models.CollectiveBookingCancellationReasons.OFFERER, + }, + "Paris": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": two_weeks_ago, + "endDatetime": in_two_weeks, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CANCELLED, + "cancellationReason": educational_models.CollectiveBookingCancellationReasons.OFFERER, + }, + "Prague": { + "bookingLimitDatetime": four_weeks_ago, + "beginningDatetime": four_weeks_ago, + "endDatetime": four_weeks_ago, + "lastBookingStatus": educational_models.CollectiveBookingStatus.CANCELLED, + "cancellationReason": educational_models.CollectiveBookingCancellationReasons.OFFERER, + }, + } + + for city, attributes in options.items(): + last_booking_status: educational_models.CollectiveBookingStatus | None = attributes["lastBookingStatus"] + beginning_datetime: datetime = attributes["beginningDatetime"] + end_datetime: datetime = attributes["endDatetime"] + booking_limit_datetime: datetime = attributes["bookingLimitDatetime"] + + stock = educational_factories.CollectiveStockFactory( + collectiveOffer__name=f"La culture à {city}", + collectiveOffer__educational_domains=[next(domains_iterator)], + collectiveOffer__venue=next(venue_iterator), + collectiveOffer__validation=OfferValidationStatus.APPROVED, + collectiveOffer__bookingEmails=["toto@totoland.com"], + beginningDatetime=beginning_datetime, + endDatetime=end_datetime, + bookingLimitDatetime=booking_limit_datetime, + ) + offers.append(stock.collectiveOffer) + + if last_booking_status: + cancellation_reason = attributes.get("cancellationReason", None) + educational_factories.CollectiveBookingFactory( + collectiveStock=stock, + educationalYear=current_ansco, + educationalInstitution=next(institution_iterator), + status=last_booking_status, + confirmationLimitDate=booking_limit_datetime, + cancellationReason=cancellation_reason, + dateCreated=min(datetime.utcnow(), booking_limit_datetime - timedelta(days=1)), + ) + + return offers, bookings + + def create_booking_base_list( *, offerer: offerers_models.Offerer, diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_users_and_offerers.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_users_and_offerers.py index 044a5e2d8bd..06ba790633e 100644 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_users_and_offerers.py +++ b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_users_and_offerers.py @@ -126,4 +126,12 @@ def create_users_offerers() -> list[offerers_models.Offerer]: ) offerers.append(user_offerer.offerer) + user_offerer = offerers_factories.UserOffererFactory( + user__email="eac_with_displayed_status_cases@example.com", + offerer__name="eac_with_displayed_status_cases", + offerer__siren="662042449", + offerer__allowedOnAdage=True, + ) + offerers.append(user_offerer.offerer) + return offerers diff --git a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_venues.py b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_venues.py index e658f75f84c..7fbc32fb7f2 100644 --- a/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_venues.py +++ b/api/src/pcapi/sandboxes/scripts/creators/industrial/create_industrial_eac_data/create_venues.py @@ -359,6 +359,21 @@ def create_venues(offerer_list: list[offerers_models.Offerer]) -> None: processingDate=datetime.fromisoformat("2025-03-24T16:08:33+01:00"), state="refuse", ) + # eac_with_displayed_status_cases + offerer = next(offerer_iterator) + create_venue( + managingOfferer=offerer, + name=f"reimbursementPoint {offerer.name} 57", + reimbursement=True, + adageId="123547", + adageInscriptionDate=datetime.utcnow() - timedelta(days=3), + venueEducationalStatusId=next(educational_status_iterator), + collectiveInterventionArea=ALL_INTERVENTION_AREA, + departementCode="57", + postalCode="57000", + city="Lorient", + siret="55208131766523", + ) def create_venue(*, reimbursement: bool = False, **kwargs: typing.Any) -> offerers_models.Venue: