def test_delete_cascade_venue_should_abort_when_offerer_has_any_bookings():
    # Given
    booking = bookings_factories.BookingFactory()
    venue_to_delete = booking.venue

    # When
    with pytest.raises(CannotDeleteVenueWithBookingsException) as exception:
        delete_cascade_venue_by_id(venue_to_delete.id)

    # Then
    assert exception.value.errors[
        "cannotDeleteVenueWithBookingsException"] == [
            "Lieu non supprimable car il contient des réservations"
        ]
    assert Offerer.query.count() == 1
    assert Venue.query.count() == 1
    assert Stock.query.count() == 1
    assert Booking.query.count() == 1
Beispiel #2
0
        def when_booking_not_confirmed(self, mocked_check_is_usable, app):
            # Given
            next_week = datetime.utcnow() + timedelta(weeks=1)
            unconfirmed_booking = bookings_factories.BookingFactory(
                stock__beginningDatetime=next_week)
            pro_user = users_factories.UserFactory(email="*****@*****.**")
            offerer = unconfirmed_booking.stock.offer.venue.managingOfferer
            offers_factories.UserOffererFactory(user=pro_user, offerer=offerer)
            url = f"/v2/bookings/token/{unconfirmed_booking.token}"
            mocked_check_is_usable.side_effect = api_errors.ForbiddenError(
                errors={"booking": ["Not confirmed"]})

            # When
            response = TestClient(
                app.test_client()).with_auth("*****@*****.**").get(url)

            # Then
            assert response.status_code == 403
            assert response.json["booking"] == ["Not confirmed"]
Beispiel #3
0
def test_save_cancellation_date_postgresql_function():
    # In this test, we manually COMMIT so that save_cancellation_date
    # PotsgreSQL function is triggered.
    booking = factories.BookingFactory()
    assert booking.cancellationDate is None

    booking.isCancelled = True
    db.session.commit()
    assert booking.cancellationDate is not None

    # Don't change cancellationDate when another attribute is updated.
    previous = booking.cancellationDate
    booking.isUsed = True
    db.session.commit()
    assert booking.cancellationDate == previous

    booking.isCancelled = False
    db.session.commit()
    assert booking.cancellationDate is None
    def test_should_send_email_when_stock_date_have_been_changed(self):
        # Given
        stock = offers_factories.EventStockFactory(beginningDatetime=datetime(2019, 8, 20, 12, 0, 0))
        booking = bookings_factories.BookingFactory(stock=stock)

        # When
        booking_info_for_mailjet = retrieve_data_to_warn_user_after_stock_update_affecting_booking(booking)

        # Then
        assert booking_info_for_mailjet == {
            "MJ-TemplateID": 1332139,
            "MJ-TemplateLanguage": True,
            "Vars": {
                "offer_name": booking.stock.offer.name,
                "user_first_name": booking.firstName,
                "venue_name": booking.venue.name,
                "event_date": "mardi 20 août 2019",
                "event_hour": "14h",
            },
        }
Beispiel #5
0
    def test_digital_limit(self):
        beneficiary = users_factories.UserFactory(deposit__version=1)
        product = offers_factories.DigitalProductFactory(
            type=str(ThingType.AUDIOVISUEL))
        offer = offers_factories.OfferFactory(product=product)
        factories.BookingFactory(
            user=beneficiary,
            stock__price=190,
            stock__offer=offer,
        )

        validation.check_expenses_limits(beneficiary, 10,
                                         offer)  # should not raise

        with pytest.raises(
                exceptions.DigitalExpenseLimitHasBeenReached) as error:
            validation.check_expenses_limits(beneficiary, 11, offer)
        assert error.value.errors["global"] == [
            "Le plafond de 200 € pour les offres numériques ne vous permet pas de réserver cette offre."
        ]
Beispiel #6
0
    def when_pro_user_has_rights_on_managing_offerer(self, app):
        # given
        booking = bookings_factories.BookingFactory()
        bookings_factories.UsedBookingFactory(stock=booking.stock)
        venue = booking.venue
        venue_owner = offers_factories.UserOffererFactory(
            offerer=venue.managingOfferer).user

        auth_request = TestClient(
            app.test_client()).with_session_auth(email=venue_owner.email)

        # when
        response = auth_request.get("/venues/%s/stats" % humanize(venue.id))

        # then
        assert response.status_code == 200
        response_json = response.json
        assert response_json["activeBookingsQuantity"] == 1
        assert response_json["validatedBookingsQuantity"] == 1
        assert response_json["activeOffersCount"] == 1
        assert response_json["soldOutOffersCount"] == 0
Beispiel #7
0
    def test_does_not_allow_a_negative_remaining_quantity_on_edition(
            self, mock_update_confirmation_dates):
        # Given
        offer = factories.ThingOfferFactory()
        booking = bookings_factories.BookingFactory(stock__offer=offer,
                                                    stock__quantity=10)
        existing_stock = booking.stock
        edited_stock_data = StockEditionBodyModel(id=existing_stock.id,
                                                  quantity=0,
                                                  price=10)

        # When
        with pytest.raises(api_errors.ApiErrors) as error:
            api.upsert_stocks(offer_id=offer.id,
                              stock_data_list=[edited_stock_data])

        # Then
        assert error.value.errors == {
            "quantity": [
                "Le stock total ne peut être inférieur au nombre de réservations"
            ]
        }
Beispiel #8
0
def test_fully_sync_venue():
    api_url = "https://example.com/provider/api"
    provider = offerers_factories.APIProviderFactory(apiUrl=api_url)
    venue_provider = offerers_factories.VenueProviderFactory(provider=provider)
    venue = venue_provider.venue
    stock = offers_factories.StockFactory(quantity=10,
                                          offer__venue=venue,
                                          offer__idAtProviders="1")
    bookings_factories.BookingFactory(stock=stock)
    product2 = offers_factories.ProductFactory(
        idAtProviders="1234",
        extraData={"prix_livre": 10},
        subcategoryId=subcategories.LIVRE_PAPIER.id,
    )

    with requests_mock.Mocker() as mock:
        response = {
            "total": 1,
            "stocks": [{
                "ref": "1234",
                "available": 5
            }],
        }
        mock.get(f"{api_url}/{venue_provider.venueIdAtOfferProvider}",
                 [{
                     "json": response
                 }, {
                     "json": {
                         "stocks": []
                     }
                 }])
        fully_sync_venue.fully_sync_venue(venue)

    # Check that the quantity of existing stocks has been reset.
    assert stock.quantity == 1
    # Check that offers and stocks have been created or updated.
    offer2 = offers_models.Offer.query.filter_by(product=product2).one()
    assert offer2.stocks[0].quantity == 5
Beispiel #9
0
def make_booking(**kwargs):
    attributes = dict(
        dateCreated=datetime(2019, 10, 3, 13, 24, 6, tzinfo=timezone.utc),
        token="ABC123",
        user__firstName="Joe",
        stock__beginningDatetime=datetime(2019,
                                          11,
                                          6,
                                          14,
                                          59,
                                          5,
                                          tzinfo=timezone.utc),
        stock__price=23.99,
        stock__offer__name="Super événement",
        stock__offer__product__type=str(models.EventType.SPECTACLE_VIVANT),
        stock__offer__venue__name="Lieu de l'offreur",
        stock__offer__venue__address="25 avenue du lieu",
        stock__offer__venue__postalCode="75010",
        stock__offer__venue__city="Paris",
        stock__offer__venue__managingOfferer__name="Théâtre du coin",
    )
    attributes.update(kwargs)
    return bookings_factories.BookingFactory(**attributes)
Beispiel #10
0
    def should_invalidate_booking_token_when_event_is_reported(self):
        # Given
        now = datetime.datetime.now()
        booking_made_3_days_ago = now - datetime.timedelta(days=3)
        event_in_4_days = now + datetime.timedelta(days=4)
        event_reported_in_10_days = now + datetime.timedelta(days=10)
        stock = factories.EventStockFactory(beginningDatetime=event_in_4_days)
        booking = bookings_factories.BookingFactory(stock=stock, dateCreated=booking_made_3_days_ago, isUsed=True)

        # When
        api.edit_stock(
            stock,
            price=5,
            quantity=20,
            beginning=event_reported_in_10_days,
            booking_limit_datetime=stock.bookingLimitDatetime,
        )

        # Then
        updated_booking = Booking.query.get(booking.id)
        assert updated_booking.isUsed is False
        assert updated_booking.dateUsed is None
        assert updated_booking.confirmationDate == booking.confirmationDate
Beispiel #11
0
    def test_a_list_of_payments_is_returned_with_statuses_in_error_or_retry_or_pending(
            self):
        # Given
        booking = bookings_factories.BookingFactory()
        offerer = booking.stock.offer.venue.managingOfferer

        error_payment = create_payment(booking, offerer, 10)
        retry_payment = create_payment(booking, offerer, 10)
        pending_payment = create_payment(booking, offerer, 10)
        not_processable_payment = create_payment(booking, offerer, 10)

        error_status = PaymentStatus()
        error_status.status = TransactionStatus.ERROR
        error_payment.statuses.append(error_status)

        retry_status = PaymentStatus()
        retry_status.status = TransactionStatus.RETRY
        retry_payment.statuses.append(retry_status)

        not_processable_status = PaymentStatus()
        not_processable_status.status = TransactionStatus.NOT_PROCESSABLE
        not_processable_payment.statuses.append(not_processable_status)

        repository.save(error_payment, retry_payment, pending_payment)

        # When
        payments = concatenate_payments_with_errors_and_retries(
            [pending_payment])

        # Then
        assert len(payments) == 3
        allowed_statuses = (TransactionStatus.RETRY, TransactionStatus.ERROR,
                            TransactionStatus.PENDING)
        assert all(
            map(lambda p: p.currentStatus.status in allowed_statuses,
                payments))
Beispiel #12
0
    def should_not_invalidate_booking_token_when_event_is_reported_in_less_than_48_hours(self, mock_mark_as_unused):
        # Given
        now = datetime.datetime.now()
        date_used_in_48_hours = datetime.datetime.now() + datetime.timedelta(days=2)
        event_in_3_days = now + datetime.timedelta(days=3)
        event_reported_in_less_48_hours = now + datetime.timedelta(days=1)
        stock = factories.EventStockFactory(beginningDatetime=event_in_3_days)
        booking = bookings_factories.BookingFactory(
            stock=stock, dateCreated=now, isUsed=True, dateUsed=date_used_in_48_hours
        )

        # When
        api.edit_stock(
            stock,
            price=5,
            quantity=20,
            beginning=event_reported_in_less_48_hours,
            booking_limit_datetime=event_reported_in_less_48_hours,
        )

        # Then
        updated_booking = Booking.query.get(booking.id)
        assert updated_booking.isUsed is True
        assert updated_booking.dateUsed == date_used_in_48_hours
Beispiel #13
0
 def test_dont_raise_if_user_cancelled(self):
     booking = factories.BookingFactory(isCancelled=True)
     validation.check_offer_already_booked(booking.user, booking.stock.offer)  # should not raise
Beispiel #14
0
 def should_does_not_raise_error_if_not_cancelled_but_used_and_no_beginning_datetime(self):
     booking = factories.BookingFactory(
         isUsed=True,
         stock__beginningDatetime=None,
     )
     validation.check_booking_token_is_keepable(booking)  # should not raise
Beispiel #15
0
 def should_dont_raise_if_stock_beginning_datetime_in_less_than_72_hours(self):
     booking = factories.BookingFactory(
         isUsed=True,
         stock__beginningDatetime=datetime.utcnow() + timedelta(days=2),
     )
     validation.check_booking_token_is_keepable(booking)  # should not raise
Beispiel #16
0
 def test_raise_if_not_the_benficiary(self):
     booking = factories.BookingFactory()
     other_user = users_factories.UserFactory()
     with pytest.raises(exceptions.BookingDoesntExist):
         validation.check_beneficiary_can_cancel_booking(other_user, booking)
Beispiel #17
0
 def test_bookable_if_stock_is_unlimited(self):
     stock = factories.ThingStockFactory(quantity=None)
     bookings_factories.BookingFactory(stock=stock)
     assert stock.isBookable
Beispiel #18
0
 def should_raises_resource_gone_error_if_not_used(self, app):
     booking = factories.BookingFactory(isUsed=False)
     with pytest.raises(api_errors.ResourceGoneError) as exc:
         validation.check_can_be_mark_as_unused(booking)
     assert exc.value.errors["booking"] == ["Cette réservation n'a pas encore été validée"]
Beispiel #19
0
 def test_can_cancel(self):
     booking = factories.BookingFactory()
     validation.check_beneficiary_can_cancel_booking(booking.user, booking)  # should not raise
Beispiel #20
0
def test_should_send_email_to_users_address_when_environment_is_production(
        mock_feature_send_mail_to_users_enabled):
    booking = bookings_factories.BookingFactory(user__email="*****@*****.**")
    email_data = retrieve_data_for_beneficiary_booking_confirmation_email(
        booking)
    assert email_data["To"] == "*****@*****.**"
Beispiel #21
0
 def test_can_cancel(self):
     booking = factories.BookingFactory()
     validation.check_offerer_can_cancel_booking(booking)  # should not raise
Beispiel #22
0
    def test_raise_if_already_booked(self):
        booking = factories.BookingFactory()

        with pytest.raises(exceptions.OfferIsAlreadyBooked) as error:
            validation.check_offer_already_booked(booking.user, booking.stock.offer)
        assert error.value.errors == {"offerId": ["Cette offre a déja été reservée par l'utilisateur"]}
Beispiel #23
0
 def test_raise_if_already_used(self):
     booking = factories.BookingFactory(isUsed=True)
     with pytest.raises(exceptions.BookingIsAlreadyUsed):
         validation.check_beneficiary_can_cancel_booking(booking.user, booking)
Beispiel #24
0
 def should_raises_forbidden_error_if_validated_and_cancelled(self, app):
     booking = factories.BookingFactory(isUsed=True, isCancelled=True)
     with pytest.raises(api_errors.ForbiddenError) as exc:
         validation.check_can_be_mark_as_unused(booking)
     assert exc.value.errors["booking"] == ["Cette réservation a été annulée"]
Beispiel #25
0
 def test_not_bookable_if_no_remaining_stock(self):
     stock = factories.StockFactory(quantity=1)
     bookings_factories.BookingFactory(stock=stock)
     assert not stock.isBookable
Beispiel #26
0
 def should_raises_resource_gone_error_if_payement_exists(self, app):
     booking = factories.BookingFactory(isUsed=True)
     payments_factories.PaymentFactory(booking=booking)
     with pytest.raises(api_errors.ResourceGoneError) as exc:
         validation.check_can_be_mark_as_unused(booking)
     assert exc.value.errors["payment"] == ["Le remboursement est en cours de traitement"]
Beispiel #27
0
 def test_raise_if_already_cancelled(self):
     booking = factories.BookingFactory(isCancelled=True)
     with pytest.raises(api_errors.ResourceGoneError) as exc:
         validation.check_offerer_can_cancel_booking(booking)
     assert exc.value.errors["global"] == ["Cette contremarque a déjà été annulée"]
Beispiel #28
0
 def test_can_cancel_if_event_is_in_a_long_time(self):
     booking = factories.BookingFactory(
         stock__beginningDatetime=datetime.utcnow() + timedelta(days=10),
     )
     validation.check_beneficiary_can_cancel_booking(booking.user, booking)  # should not raise
Beispiel #29
0
def test_should_return_total_price_for_duo_offers():
    booking = bookings_factories.BookingFactory(quantity=2, stock__price=10)
    email_data = retrieve_data_for_beneficiary_booking_confirmation_email(
        booking)
    assert email_data["Vars"]["offer_price"] == "20.00"
Beispiel #30
0
 def test_raise_if_already_used(self):
     booking = factories.BookingFactory(isUsed=True)
     with pytest.raises(api_errors.ForbiddenError) as exc:
         validation.check_offerer_can_cancel_booking(booking)
     assert exc.value.errors["global"] == ["Impossible d'annuler une réservation consommée"]