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)
Exemplo n.º 2
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_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
Exemplo n.º 4
0
    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
Exemplo n.º 5
0
    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_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_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)
Exemplo n.º 8
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 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 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,
            )