def test_import_educational_institutions_and_deposits_with_existing_data_on_future_year(
            self, db_session):
        # Given
        educational_year = factories.EducationalYearFactory(
            beginningDate=datetime(2020, 9, 1),
            expirationDate=datetime(2021, 8, 30),
        )
        future_educational_year = factories.EducationalYearFactory(
            beginningDate=datetime(2021, 9, 1),
            expirationDate=datetime(2022, 8, 30),
        )

        educational_institution2 = factories.EducationalInstitutionFactory(
            institutionId="4790032L")
        factories.EducationalDepositFactory(
            educationalInstitution=educational_institution2,
            educationalYear=future_educational_year,
        )

        # When
        _process_educational_csv([{
            "UAICode": "4790032L",
            "depositAmount": 5000
        }])

        # Then it creates educational deposit for current year even if it exists for another year
        educational_deposit = models.EducationalDeposit.query.filter(
            models.EducationalDeposit.educationalInstitutionId ==
            educational_institution2.id,
            models.EducationalDeposit.educationalYearId ==
            educational_year.adageId,
        ).one()
        assert educational_deposit.amount == Decimal(5000)
    def test_should_send_email_on_educational_booking_creation(self):
        # Given
        stock = offers_factories.EducationalEventStockFactory(
            beginningDatetime=datetime.datetime(2021, 5, 15),
            offer__bookingEmail="*****@*****.**",
        )
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_factories.EducationalYearFactory(
            beginningDate=datetime.datetime(2020, 9, 1),
            expirationDate=datetime.datetime(2021, 8, 31))
        educational_factories.EducationalYearFactory(
            beginningDate=datetime.datetime(2021, 9, 1),
            expirationDate=datetime.datetime(2022, 8, 31))
        educational_redactor = educational_factories.EducationalRedactorFactory(
            email="*****@*****.**",
            firstName="Georges",
            lastName="Moustaki",
        )
        redactor_informations = AuthenticatedInformation(
            email=educational_redactor.email,
            civility=educational_redactor.civility,
            firstname=educational_redactor.firstName,
            lastname=educational_redactor.lastName,
            uai=educational_institution.institutionId,
        )

        # When
        educational_api.book_educational_offer(
            redactor_informations=redactor_informations,
            stock_id=stock.id,
        )

        # Then
        assert len(mails_testing.outbox) == 1
        sent_data = mails_testing.outbox[0].sent_data
        offer = stock.offer
        assert sent_data == {
            "FromEmail": "*****@*****.**",
            "MJ-TemplateID": 3174424,
            "MJ-TemplateLanguage": True,
            "To": "*****@*****.**",
            "Vars": {
                "departement": "75",
                "lien_offre_pcpro":
                f"http://*****:*****@example.com",
                "is_event": 1,
            },
        }
    def test_should_not_create_educational_booking_when_educational_institution_unknown(
            self):
        # Given
        stock = offers_factories.EducationalEventStockFactory(
            beginningDatetime=datetime.datetime(2021, 5, 15))
        educational_factories.EducationalInstitutionFactory()
        educational_factories.EducationalYearFactory()
        educational_redactor = educational_factories.EducationalRedactorFactory(
            email="*****@*****.**")
        provided_institution_id = "AU3568Unknown"
        redactor_informations = AuthenticatedInformation(
            email=educational_redactor.email,
            civility=educational_redactor.civility,
            firstname=educational_redactor.firstName,
            lastname=educational_redactor.lastName,
            uai=provided_institution_id,
        )

        # When
        with pytest.raises(exceptions.EducationalInstitutionUnknown) as error:
            educational_api.book_educational_offer(
                redactor_informations=redactor_informations,
                stock_id=stock.id,
            )

        # Then
        assert error.value.errors == {
            "educationalInstitution": ["Cette institution est inconnue"]
        }

        saved_bookings = EducationalBooking.query.join(Booking).filter(
            Booking.stockId == stock.id).all()
        assert len(saved_bookings) == 0
    def test_should_not_create_educational_booking_when_stock_does_not_exist(
            self):
        # Given
        offers_factories.EducationalEventStockFactory(
            beginningDatetime=datetime.datetime(2021, 5, 15))
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_factories.EducationalYearFactory()
        educational_redactor = educational_factories.EducationalRedactorFactory(
            email="*****@*****.**")
        requested_stock_id = 4875
        redactor_informations = AuthenticatedInformation(
            email=educational_redactor.email,
            civility=educational_redactor.civility,
            firstname=educational_redactor.firstName,
            lastname=educational_redactor.lastName,
            uai=educational_institution.institutionId,
        )

        # When
        with pytest.raises(offers_exceptions.StockDoesNotExist):
            educational_api.book_educational_offer(
                redactor_informations=redactor_informations,
                stock_id=requested_stock_id,
            )

        # Then
        saved_bookings = EducationalBooking.query.all()
        assert len(saved_bookings) == 0
    def test_should_not_create_educational_booking_when_offer_is_not_an_event(
            self):
        # Given
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_factories.EducationalYearFactory()
        educational_redactor = educational_factories.EducationalRedactorFactory(
            email="*****@*****.**")
        stock = offers_factories.ThingStockFactory(
            beginningDatetime=datetime.datetime(2021, 5, 15),
            offer__isEducational=True)
        redactor_informations = AuthenticatedInformation(
            email=educational_redactor.email,
            civility=educational_redactor.civility,
            firstname=educational_redactor.firstName,
            lastname=educational_redactor.lastName,
            uai=educational_institution.institutionId,
        )

        # When
        with pytest.raises(exceptions.OfferIsNotEvent) as error:
            educational_api.book_educational_offer(
                redactor_informations=redactor_informations,
                stock_id=stock.id,
            )

        # Then
        assert error.value.errors == {
            "offer":
            [f"L'offre {stock.offer.id} n'est pas une offre évènementielle"]
        }

        saved_bookings = EducationalBooking.query.join(Booking).filter(
            Booking.stockId == stock.id).all()
        assert len(saved_bookings) == 0
    def test_confirm_educational_booking_sends_email(self, db_session):
        # Given
        educational_redactor = educational_factories.EducationalRedactorFactory(
            email="*****@*****.**",
            firstName="Georges",
            lastName="Moustaki")
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_year = educational_factories.EducationalYearFactory(
            adageId="1")
        educational_factories.EducationalDepositFactory(
            educationalInstitution=educational_institution,
            educationalYear=educational_year,
            amount=Decimal(1400.00),
            isFinal=True,
        )
        booking = bookings_factories.EducationalBookingFactory(
            amount=Decimal(20.00),
            quantity=20,
            educationalBooking__educationalInstitution=educational_institution,
            educationalBooking__educationalYear=educational_year,
            educationalBooking__educationalRedactor=educational_redactor,
            status=BookingStatus.PENDING,
            stock__offer__bookingEmail="*****@*****.**",
            stock__beginningDatetime=datetime.datetime(2021, 5, 15),
        )

        # When
        educational_api.confirm_educational_booking(
            booking.educationalBookingId)

        # Then
        assert len(mails_testing.outbox) == 1
        sent_data = mails_testing.outbox[0].sent_data
        offer = booking.stock.offer
        assert sent_data == {
            "FromEmail": "*****@*****.**",
            "MJ-TemplateID": 3174413,
            "MJ-TemplateLanguage": True,
            "To": "*****@*****.**",
            "Vars": {
                "lien_offre_pcpro":
                f"http://*****:*****@example.com",
                "is_event": 1,
            },
        }
    def test_should_create_educational_booking_on_requested_educational_offer(
            self):
        # Given
        stock = offers_factories.EducationalEventStockFactory(
            beginningDatetime=datetime.datetime(2021, 5, 15))
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_year = educational_factories.EducationalYearFactory(
            beginningDate=datetime.datetime(2020, 9, 1),
            expirationDate=datetime.datetime(2021, 8, 31))
        educational_factories.EducationalYearFactory(
            beginningDate=datetime.datetime(2021, 9, 1),
            expirationDate=datetime.datetime(2022, 8, 31))
        educational_redactor = educational_factories.EducationalRedactorFactory(
            email="*****@*****.**")
        redactor_informations = AuthenticatedInformation(
            email=educational_redactor.email,
            civility=educational_redactor.civility,
            firstname=educational_redactor.firstName,
            lastname=educational_redactor.lastName,
            uai=educational_institution.institutionId,
        )

        # When
        returned_booking = educational_api.book_educational_offer(
            redactor_informations=redactor_informations,
            stock_id=stock.id,
        )

        # Then
        saved_educational_booking = EducationalBooking.query.join(
            Booking).filter(Booking.stockId == stock.id).first()

        assert saved_educational_booking.booking.id == returned_booking.id
        assert saved_educational_booking.booking.stock.id == stock.id
        assert saved_educational_booking.booking.stock.dnBookedQuantity == 1
        assert saved_educational_booking.confirmationLimitDate == stock.bookingLimitDatetime
        assert saved_educational_booking.educationalInstitution.institutionId == educational_institution.institutionId
        assert saved_educational_booking.educationalYear.adageId == educational_year.adageId
        assert saved_educational_booking.booking.status == BookingStatus.PENDING
        # Assert we do not create an extra educational redactor when exist
        assert EducationalRedactor.query.count() == 1
 def test_data(self):
     stock = offer_factories.EducationalEventStockFactory(
         beginningDatetime=stock_date)
     educational_institution = educational_factories.EducationalInstitutionFactory(
     )
     educational_factories.EducationalYearFactory(
         beginningDate=educational_year_dates["start"],
         expirationDate=educational_year_dates["end"])
     educational_redactor = educational_factories.EducationalRedactorFactory(
         email="*****@*****.**")
     return (stock, educational_institution, educational_redactor)
    def test_should_create_educational_redactor_when_it_does_not_exist(self):
        # Given
        stock = offers_factories.EducationalEventStockFactory(
            beginningDatetime=datetime.datetime(2021, 5, 15))
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_factories.EducationalYearFactory(
            beginningDate=datetime.datetime(2020, 9, 1),
            expirationDate=datetime.datetime(2021, 8, 31))
        educational_factories.EducationalYearFactory(
            beginningDate=datetime.datetime(2021, 9, 1),
            expirationDate=datetime.datetime(2022, 8, 31))
        redactor_informations = AuthenticatedInformation(
            email="*****@*****.**",
            civility="Mme",
            firstname="Project",
            lastname="Redactor",
            uai=educational_institution.institutionId,
        )

        # When
        educational_api.book_educational_offer(
            redactor_informations=redactor_informations,
            stock_id=stock.id,
        )

        # Then
        saved_educational_booking = EducationalBooking.query.join(
            Booking).filter(Booking.stockId == stock.id).first()
        assert saved_educational_booking.educationalRedactor.email == redactor_informations.email
        educational_redactor: EducationalRedactor = EducationalRedactor.query.one(
        )
        assert educational_redactor.email == redactor_informations.email
        assert educational_redactor.firstName == "Project"
        assert educational_redactor.lastName == "Redactor"
        assert educational_redactor.civility == "Mme"
    def test_post_educational_booking_with_less_redactor_information(
            self, app):
        # Given
        stock = offer_factories.EducationalEventStockFactory(
            beginningDatetime=stock_date)
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_year = educational_factories.EducationalYearFactory(
            beginningDate=educational_year_dates["start"],
            expirationDate=educational_year_dates["end"])

        adage_jwt_fake_valid_token = _create_adage_valid_token_with_email(
            email="*****@*****.**",
            uai=educational_institution.institutionId,
            civility=None,
            firstname=None,
            lastname=None,
        )
        test_client = TestClient(app.test_client())
        test_client.auth_header = {
            "Authorization": f"Bearer {adage_jwt_fake_valid_token}"
        }

        # When
        response = test_client.post(
            "/adage-iframe/bookings",
            json={
                "stockId": stock.id,
            },
        )

        # Then
        assert response.status_code == 200
        booking = Booking.query.filter(Booking.stockId == stock.id).first()
        assert booking.educationalBookingId is not None
        assert booking.individualBookingId is None
        assert booking.stock.id == stock.id
        educational_booking = booking.educationalBooking
        assert educational_booking.educationalInstitution.institutionId == educational_institution.institutionId
        assert educational_booking.educationalYear.adageId == educational_year.adageId
        educational_redactor = educational_booking.educationalRedactor
        assert educational_redactor.civility == None
        assert educational_redactor.firstName == None
        assert educational_redactor.lastName == None
        assert educational_redactor.email == "*****@*****.**"

        assert response.json["bookingId"] == booking.id
    def test_confirm_educational_booking_lock(self, app):
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_year = educational_factories.EducationalYearFactory(
            adageId="1")
        deposit = educational_factories.EducationalDepositFactory(
            educationalInstitution=educational_institution,
            educationalYear=educational_year,
            amount=Decimal(1400.00),
            isFinal=True,
        )
        bookings_factories.EducationalBookingFactory(
            amount=Decimal(20.00),
            quantity=20,
            educationalBooking__educationalInstitution=educational_institution,
            educationalBooking__educationalYear=educational_year,
            status=BookingStatus.CONFIRMED,
        )

        booking = bookings_factories.EducationalBookingFactory(
            amount=Decimal(20.00),
            quantity=20,
            educationalBooking__educationalInstitution=educational_institution,
            educationalBooking__educationalYear=educational_year,
            status=BookingStatus.PENDING,
        )

        # open a second connection on purpose and lock the deposit
        engine = create_engine(app.config["SQLALCHEMY_DATABASE_URI"])
        with engine.connect() as connection:
            connection.execute(
                text(
                    """SELECT * FROM educational_deposit WHERE id = :educational_deposit_id FOR UPDATE"""
                ),
                educational_deposit_id=deposit.id,
            )

            with pytest.raises(sqlalchemy.exc.OperationalError):
                educational_api.confirm_educational_booking(
                    booking.educationalBookingId)

        refreshed_booking = Booking.query.filter(
            Booking.id == booking.id).one()
        assert refreshed_booking.status == BookingStatus.PENDING
    def test_update_educational_institutions_deposits(self):
        # Given
        educational_year = factories.EducationalYearFactory(
            beginningDate=datetime(2020, 9, 1),
            expirationDate=datetime(2021, 8, 30),
        )
        educational_institution1 = factories.EducationalInstitutionFactory(
            institutionId="0790032L")
        deposit1 = factories.EducationalDepositFactory(
            educationalInstitution=educational_institution1,
            educationalYear=educational_year,
            amount=500,
            isFinal=False,
        )

        educational_institution2 = factories.EducationalInstitutionFactory(
            institutionId="1790032L")
        deposit2 = factories.EducationalDepositFactory(
            educationalInstitution=educational_institution2,
            educationalYear=educational_year,
            amount=600,
            isFinal=False,
        )

        # When
        update_educational_institutions_deposits(
            "update_deposits.csv", "tests/scripts/educational/fixtures")

        # Then
        educational_institutions = models.EducationalInstitution.query.all()
        assert len(educational_institutions) == 2

        educational_deposits = models.EducationalDeposit.query.all()
        assert len(educational_deposits) == 2

        educational_deposit1 = models.EducationalDeposit.query.get(deposit1.id)
        assert educational_deposit1.isFinal is True
        assert educational_deposit1.amount == 6000

        educational_deposit2 = models.EducationalDeposit.query.get(deposit2.id)
        assert educational_deposit2.isFinal is True
        assert educational_deposit2.amount == 9000
    def test_import_educational_institutions_and_deposits(self, db_session):
        # Given
        factories.EducationalYearFactory(
            beginningDate=datetime(2020, 9, 1),
            expirationDate=datetime(2021, 8, 30),
        )

        # When
        import_educational_institutions_and_deposits(
            "institutions_and_deposits.csv",
            "tests/scripts/educational/fixtures")

        # Then
        educational_institutions = models.EducationalInstitution.query.all()
        assert len(educational_institutions) == 5

        educational_deposits = models.EducationalDeposit.query.all()
        assert len(educational_deposits) == 5
        assert all(not educational_deposit.isFinal
                   for educational_deposit in educational_deposits)
    def test_stop_execution_when_csv_is_invalid(self):
        # Given
        educational_year = factories.EducationalYearFactory(
            beginningDate=datetime(2020, 9, 1),
            expirationDate=datetime(2021, 8, 30),
        )
        educational_institution = factories.EducationalInstitutionFactory(
            institutionId="0790032L")
        educational_deposit = factories.EducationalDepositFactory(
            educationalInstitution=educational_institution,
            educationalYear=educational_year,
            amount=500,
            isFinal=False,
        )

        # When
        update_educational_institutions_deposits(
            "invalid.csv", "tests/scripts/educational/fixtures")

        # Then
        deposit = models.EducationalDeposit.query.get(educational_deposit.id)
        assert deposit.amount == 500
    def test_confirm_educational_booking(self, db_session):
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_year = educational_factories.EducationalYearFactory(
            adageId="1")
        educational_factories.EducationalDepositFactory(
            educationalInstitution=educational_institution,
            educationalYear=educational_year,
            amount=Decimal(1400.00),
            isFinal=True,
        )
        booking = bookings_factories.EducationalBookingFactory(
            amount=Decimal(20.00),
            quantity=20,
            educationalBooking__educationalInstitution=educational_institution,
            educationalBooking__educationalYear=educational_year,
            status=BookingStatus.PENDING,
        )
        educational_api.confirm_educational_booking(
            booking.educationalBookingId)

        assert booking.status == BookingStatus.CONFIRMED
    def test_update_institutions_deposits_with_institution_deposit_missing_ceases_execution(
            self):
        # Given
        educational_year = factories.EducationalYearFactory(
            beginningDate=datetime(2020, 9, 1),
            expirationDate=datetime(2021, 8, 30),
        )

        factories.EducationalInstitutionFactory(institutionId="4790032L")
        educational_institution2 = factories.EducationalInstitutionFactory(
            institutionId="1790032L")
        educational_deposit = factories.EducationalDepositFactory(
            educationalInstitution=educational_institution2,
            educationalYear=educational_year,
            amount=500,
            isFinal=False,
        )

        # When
        _process_educational_csv([
            {
                "UAICode": "4790032L",
                "depositAmount": 5000
            },
            {
                "UAICode": "1790032L",
                "depositAmount": 3000
            },
        ])

        # Then
        educational_deposit = models.EducationalDeposit.query.filter(
            models.EducationalDeposit.educationalInstitutionId ==
            educational_institution2.id,
            models.EducationalDeposit.educationalYearId ==
            educational_year.adageId,
        ).one()
        assert educational_deposit.amount == Decimal(500)
    def test_update_institutions_deposits_with_educational_year_missing_ceases_execution(
            self):
        # Given
        educational_year = factories.EducationalYearFactory(
            beginningDate=datetime(2018, 9, 1),
            expirationDate=datetime(2019, 8, 30),
        )
        educational_institution = factories.EducationalInstitutionFactory(
            institutionId="0790032L")
        educational_deposit = factories.EducationalDepositFactory(
            educationalInstitution=educational_institution,
            educationalYear=educational_year,
            amount=500,
            isFinal=False,
        )

        # When
        update_educational_institutions_deposits(
            "update_deposits.csv", "tests/scripts/educational/fixtures")

        # Then
        deposit1 = models.EducationalDeposit.query.get(educational_deposit.id)
        assert deposit1.amount == 500
        assert deposit1.isFinal == False
    def test_should_not_create_educational_booking_when_educational_year_not_found(
            self):
        # Given
        date_before_education_year_beginning = datetime.datetime(2018, 9, 20)
        stock = offers_factories.EducationalEventStockFactory(
            beginningDatetime=date_before_education_year_beginning)
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_factories.EducationalYearFactory()
        educational_redactor = educational_factories.EducationalRedactorFactory(
            email="*****@*****.**")
        redactor_informations = AuthenticatedInformation(
            email=educational_redactor.email,
            civility=educational_redactor.civility,
            firstname=educational_redactor.firstName,
            lastname=educational_redactor.lastName,
            uai=educational_institution.institutionId,
        )

        # When
        with pytest.raises(exceptions.EducationalYearNotFound) as error:
            educational_api.book_educational_offer(
                redactor_informations=redactor_informations,
                stock_id=stock.id,
            )

        # Then
        assert error.value.errors == {
            "educationalYear": [
                "Aucune année scolaire correspondant à la réservation demandée n'a été trouvée"
            ]
        }

        saved_bookings = EducationalBooking.query.join(Booking).filter(
            Booking.stockId == stock.id).all()
        assert len(saved_bookings) == 0
    def test_raises_insufficient_temporary_fund(self, db_session) -> None:
        # When
        educational_year = educational_factories.EducationalYearFactory(
            adageId="1")
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_factories.EducationalDepositFactory(
            educationalYear=educational_year,
            educationalInstitution=educational_institution,
            amount=Decimal(1000.00),
            isFinal=False,
        )
        booking = bookings_factories.EducationalBookingFactory(
            educationalBooking__educationalYear=educational_year,
            educationalBooking__educationalInstitution=educational_institution,
            amount=Decimal(900.00),
            quantity=1,
            status=BookingStatus.PENDING,
        )

        # Then
        with pytest.raises(exceptions.InsufficientTemporaryFund):
            educational_api.confirm_educational_booking(
                booking.educationalBookingId)
def create_industrial_educational_bookings() -> None:
    educational_current_year = educational_factories.EducationalYearFactory()
    educational_next_year = educational_factories.EducationalYearFactory()

    educational_institutions = [
        educational_factories.EducationalInstitutionFactory(
            institutionId="0780032L"),
        educational_factories.EducationalInstitutionFactory(
            institutionId="0781839A"),
        educational_factories.EducationalInstitutionFactory(
            institutionId="0290047U"),
        educational_factories.EducationalInstitutionFactory(
            institutionId="0290198H"),
        educational_factories.EducationalInstitutionFactory(
            institutionId="0910620E"),
        educational_factories.EducationalInstitutionFactory(
            institutionId="0560071Y"),
    ]

    now = datetime.datetime.now(datetime.timezone.utc)
    stocks = []
    venue = VenueFactory(name="Opéra Royal de Versailles", isPermanent=True)
    UserOffererFactory(validationToken=None, offerer=venue.managingOfferer)

    educational_redactor = educational_factories.EducationalRedactorFactory(
        email="*****@*****.**")
    user_offerer_reimbursements = UserOffererFactory(
        validationToken=None, user__email="*****@*****.**")
    venue_reimbursements = VenueFactory(
        name="Théâtre des potirons",
        isPermanent=True,
        managingOfferer=user_offerer_reimbursements.offerer)

    for stock_data in FAKE_STOCK_DATA:
        stocks.append(
            EducationalEventStockFactory(
                quantity=100,
                price=stock_data["price"],
                beginningDatetime=now +
                datetime.timedelta(days=stock_data["timedelta"]),
                offer__durationMinutes=60,
                offer__withdrawalDetails=
                "Récupération du ticket à l'adresse du lieu",
                offer__description=
                "Une description multi-lignes.\nOù il est notamment question du nombre d'élèves.\nNbr d'élèves max: 50",
                offer__name=stock_data["name"],
                offer__venue=venue,
            ))

    for stock in stocks:
        mediation = MediationFactory(offer=stock.offer, credit="Crédit photo")
        store_public_object_from_sandbox_assets("thumbs", mediation,
                                                mediation.offer.subcategoryId)

    next_year_stocks = [
        EducationalEventStockFactory(
            quantity=100,
            price=1200,
            beginningDatetime=educational_next_year.beginningDate +
            datetime.timedelta(days=10),
            offer__durationMinutes=60,
            offer__withdrawalDetails=
            "Récupération du ticket à l'adresse du lieu",
            offer__description=
            "Une description multi-lignes.\nOù il est notamment question du nombre d'élèves.\nNbr d'élèves max: 50",
            offer__name=
            "Stage d'initiation à la photographie : prise en main de l'appareil-photo",
            offer__venue=venue,
        ),
        EducationalEventStockFactory(
            quantity=60,
            price=1400,
            beginningDatetime=educational_next_year.beginningDate +
            datetime.timedelta(days=15),
            offer__durationMinutes=60,
            offer__withdrawalDetails=
            "Récupération du ticket à l'adresse du lieu",
            offer__description=
            "Une description multi-lignes.\nOù il est notamment question du nombre d'élèves.\nNbr d'élèves max: 50",
            offer__name=
            "Explorer la nature au Parc Zoologique et Botanique de Mulhouse",
            offer__venue=venue,
        ),
    ]

    deposits = []
    for educational_institution in educational_institutions:
        deposits.append(
            educational_factories.EducationalDepositFactory(
                educationalInstitution=educational_institution,
                educationalYear=educational_current_year,
                amount=20000,
            ))
        deposits.append(
            educational_factories.EducationalDepositFactory(
                educationalInstitution=educational_institution,
                educationalYear=educational_next_year,
                amount=25000,
                isFinal=False,
            ))

    for stock in stocks:
        for educational_institution in educational_institutions:
            EducationalBookingFactory(
                educationalBooking__educationalRedactor=educational_redactor,
                educationalBooking__educationalInstitution=
                educational_institution,
                educationalBooking__educationalYear=educational_current_year,
                educationalBooking__confirmationLimitDate=now +
                datetime.timedelta(days=10),
                cancellation_limit_date=now + datetime.timedelta(days=4),
                status=BookingStatus.PENDING,
                stock=stock,
            )

            UsedEducationalBookingFactory(
                educationalBooking__educationalRedactor=educational_redactor,
                educationalBooking__educationalInstitution=
                educational_institution,
                educationalBooking__educationalYear=educational_current_year,
                educationalBooking__confirmationLimitDate=now -
                datetime.timedelta(days=20),
                cancellation_limit_date=now - datetime.timedelta(days=15),
                dateUsed=now - datetime.timedelta(8),
                status=BookingStatus.USED,
                stock=EducationalEventStockFactory(
                    quantity=100,
                    price=1200,
                    beginningDatetime=now - datetime.timedelta(days=10),
                    bookingLimitDatetime=now - datetime.timedelta(days=10),
                    offer__venue=venue_reimbursements,
                ),
            )

    for next_year_stock in next_year_stocks:
        for educational_institution in educational_institutions:
            EducationalBookingFactory(
                educationalBooking__educationalRedactor=educational_redactor,
                educationalBooking__educationalInstitution=
                educational_institution,
                educationalBooking__educationalYear=educational_next_year,
                educationalBooking__confirmationLimitDate=now +
                datetime.timedelta(days=30),
                status=BookingStatus.PENDING,
                stock=next_year_stock,
            )