def test_should_cancel_old_thing_that_can_expire_booking(self,
                                                             app) -> None:
        now = datetime.utcnow()
        eleven_days_ago = now - timedelta(days=11)
        two_months_ago = now - timedelta(days=60)
        book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id)
        old_book_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=book, dateCreated=eleven_days_ago)
        dvd = ProductFactory(
            subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id)
        old_dvd_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=dvd, dateCreated=two_months_ago)

        handle_expired_bookings.cancel_expired_individual_bookings()

        assert old_book_booking.isCancelled
        assert old_book_booking.status is BookingStatus.CANCELLED
        assert old_book_booking.cancellationDate.timestamp() == pytest.approx(
            datetime.utcnow().timestamp(), rel=1)
        assert old_book_booking.cancellationReason == BookingCancellationReasons.EXPIRED
        assert old_book_booking.stock.dnBookedQuantity == 0

        assert old_dvd_booking.isCancelled
        assert old_dvd_booking.status is BookingStatus.CANCELLED
        assert old_dvd_booking.cancellationDate.timestamp() == pytest.approx(
            datetime.utcnow().timestamp(), rel=1)
        assert old_dvd_booking.cancellationReason == BookingCancellationReasons.EXPIRED
        assert old_dvd_booking.stock.dnBookedQuantity == 0
    def should_only_cancel_old_thing_that_can_expire_bookings_before_start_date(
            self, app) -> None:
        now = datetime.utcnow()
        two_months_ago = now - timedelta(days=60)
        guitar = ProductFactory(
            subcategoryId=subcategories.ACHAT_INSTRUMENT.id, )
        old_guitar_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=guitar, dateCreated=two_months_ago)
        disc = ProductFactory(
            subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE.id)
        old_disc_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=disc, dateCreated=two_months_ago)
        vod = ProductFactory(subcategoryId=subcategories.VOD.id)
        old_vod_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=vod, dateCreated=two_months_ago)

        handle_expired_bookings.cancel_expired_individual_bookings()

        assert old_guitar_booking.isCancelled
        assert old_guitar_booking.status is BookingStatus.CANCELLED
        assert old_guitar_booking.cancellationDate.timestamp(
        ) == pytest.approx(datetime.utcnow().timestamp(), rel=1)
        assert old_guitar_booking.cancellationReason == BookingCancellationReasons.EXPIRED

        assert old_disc_booking.isCancelled
        assert old_disc_booking.status is BookingStatus.CANCELLED
        assert old_disc_booking.cancellationDate.timestamp() == pytest.approx(
            datetime.utcnow().timestamp(), rel=1)
        assert old_disc_booking.cancellationReason == BookingCancellationReasons.EXPIRED

        assert not old_vod_booking.isCancelled
        assert old_vod_booking.status is not BookingStatus.CANCELLED
        assert not old_vod_booking.cancellationDate
        assert not old_vod_booking.cancellationReason
    def test_handle_expired_bookings_should_cancel_expired_individual_and_educational_bookings(
            self, app) -> None:
        # Given
        now = datetime.utcnow()
        yesterday = now - timedelta(days=1)
        two_months_ago = now - timedelta(days=60)
        tomorrow = now + timedelta(days=1)

        expired_pending_educational_booking: Booking = booking_factories.PendingEducationalBookingFactory(
            educationalBooking__confirmationLimitDate=yesterday)
        non_expired_pending_educational_booking: Booking = booking_factories.PendingEducationalBookingFactory(
            educationalBooking__confirmationLimitDate=tomorrow)

        dvd = ProductFactory(
            subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id)
        expired_individual_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=dvd, dateCreated=two_months_ago)

        book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id)
        book_individual_recent_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=book)

        # When
        handle_expired_bookings.handle_expired_bookings()

        # Then
        assert expired_pending_educational_booking.status == BookingStatus.CANCELLED
        assert expired_individual_booking.status == BookingStatus.CANCELLED
        assert book_individual_recent_booking.status != BookingStatus.CANCELLED
        assert non_expired_pending_educational_booking.status == BookingStatus.PENDING
def test_fill_individual_booking_deposit_id(caplog):
    already_filled_bookings = bookings_factories.IndividualBookingFactory.create_batch(3)
    db.session.execute("ALTER TABLE booking DISABLE TRIGGER booking_update;")
    to_update_bookings = bookings_factories.IndividualBookingFactory.create_batch(
        3, individualBooking__attached_deposit="forced_none"
    )
    not_updated_booking = bookings_factories.IndividualBookingFactory(
        amount=0,
        dateCreated=(datetime.utcnow() + relativedelta(years=3)),
        individualBooking__attached_deposit="forced_none",
    )

    warning_booking = bookings_factories.IndividualBookingFactory(
        amount=10,
        dateCreated=(datetime.utcnow() + relativedelta(years=3)),
        individualBooking__attached_deposit="forced_none",
    )
    db.session.execute("ALTER TABLE booking ENABLE TRIGGER booking_update;")

    with caplog.at_level(logging.WARNING):
        fill_individual_booking_deposit_id(3)

    for booking in already_filled_bookings + to_update_bookings:
        assert booking.individualBooking.depositId == booking.individualBooking.user.deposit.id

    assert not not_updated_booking.individualBooking.depositId

    assert not warning_booking.individualBooking.depositId
    assert caplog.messages == [f"Booking with amount > 0 made after deposit expiration date id={warning_booking.id}"]
    def test_should_send_two_emails_to_offerer_when_expired_books_bookings_and_other_bookings_cancelled(
            self):
        offerer = OffererFactory()
        expired_today_dvd_booking = booking_factories.IndividualBookingFactory(
            stock__offer__name="Intouchables",
            stock__offer__bookingEmail="*****@*****.**",
            stock__offer__subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id,
        )
        expired_today_book_booking = booking_factories.IndividualBookingFactory(
            stock__offer__name="Les misérables",
            stock__offer__bookingEmail="*****@*****.**",
            stock__offer__subcategoryId=subcategories.LIVRE_PAPIER.id,
        )

        send_expired_individual_bookings_recap_email_to_offerer(
            offerer, [expired_today_dvd_booking, expired_today_book_booking])

        assert len(mails_testing.outbox) == 2
        assert mails_testing.outbox[0].sent_data["Mj-TemplateID"] == 3095184
        assert mails_testing.outbox[0].sent_data["Vars"][
            "withdrawal_period"] == 10
        assert mails_testing.outbox[0].sent_data["Vars"]["bookings"][0][
            "offer_name"] == "Les misérables"
        assert mails_testing.outbox[1].sent_data["Mj-TemplateID"] == 3095184
        assert mails_testing.outbox[1].sent_data["Vars"][
            "withdrawal_period"] == 30
        assert mails_testing.outbox[1].sent_data["Vars"]["bookings"][0][
            "offer_name"] == "Intouchables"
Ejemplo n.º 6
0
    def test_cancel_all_bookings_from_stock(self, app):
        stock = offers_factories.StockFactory(dnBookedQuantity=1)
        booking_1 = booking_factories.IndividualBookingFactory(stock=stock)
        booking_2 = booking_factories.IndividualBookingFactory(stock=stock)
        used_booking = booking_factories.UsedIndividualBookingFactory(stock=stock)
        cancelled_booking = booking_factories.CancelledIndividualBookingFactory(stock=stock)

        api.cancel_bookings_when_offerer_deletes_stock(stock)

        # cancellation can trigger more than one request to Batch
        assert len(push_testing.requests) >= 1

        assert models.Booking.query.filter().count() == 4
        assert models.Booking.query.filter(models.Booking.isCancelled == True).count() == 3
        assert models.Booking.query.filter(models.Booking.isUsed == True).count() == 1
        assert booking_1.isCancelled
        assert booking_1.status is BookingStatus.CANCELLED
        assert booking_1.cancellationReason == BookingCancellationReasons.OFFERER
        assert booking_2.isCancelled
        assert booking_2.status is BookingStatus.CANCELLED
        assert booking_2.cancellationReason == BookingCancellationReasons.OFFERER
        assert not used_booking.isCancelled
        assert used_booking.status is not BookingStatus.CANCELLED
        assert not used_booking.cancellationReason
        assert cancelled_booking.isCancelled
        assert cancelled_booking.status is BookingStatus.CANCELLED
        assert cancelled_booking.cancellationReason == BookingCancellationReasons.BENEFICIARY
Ejemplo n.º 7
0
    def test_make_offerer_driven_cancellation_email_for_offerer_event_when_other_booking(
            self, app):
        # Given
        other_beneficiary = users_factories.BeneficiaryGrant18Factory()
        stock = offers_factories.EventStockFactory(beginningDatetime=datetime(
            2019, 7, 20, 12, 0, 0, tzinfo=timezone.utc),
                                                   price=20,
                                                   quantity=10)
        booking1 = bookings_factories.IndividualBookingFactory(stock=stock,
                                                               token="98765")
        booking2 = bookings_factories.IndividualBookingFactory(
            individualBooking__user=other_beneficiary,
            stock=stock,
            token="12345")

        # When
        with patch("pcapi.utils.mailing.find_ongoing_bookings_by_stock",
                   return_value=[booking2]):
            email = make_offerer_driven_cancellation_email_for_offerer(
                booking1)

        # Then
        email_html = BeautifulSoup(email["Html-part"], "html.parser")
        html_recap_table = email_html.find("table", {"id": "recap-table"}).text
        assert "Prénom" in html_recap_table
        assert "Nom" in html_recap_table
        assert "Email" in html_recap_table
        assert other_beneficiary.firstName in html_recap_table
        assert other_beneficiary.lastName in html_recap_table
        assert other_beneficiary.email in html_recap_table
        assert booking2.token in html_recap_table
    def test_should_return_mailjet_data_when_multiple_bookings_and_offer_is_a_thing(self, build_pc_pro_offer_link):
        # Given
        beneficiary = users_factories.BeneficiaryGrant18Factory(
            publicName="John Doe", firstName="John", lastName="Doe", email="*****@*****.**"
        )
        offer = offer_factories.ThingOfferFactory(
            venue__name="La petite librairie",
            venue__publicName="La grande librairie",
            product__name="Le récit de voyage",
        )
        booking = booking_factories.IndividualBookingFactory(
            user=beneficiary,
            individualBooking__user=beneficiary,
            stock__offer=offer,
            stock__price=0,
            token="12346",
            quantity=6,
        )

        other_beneficiary = users_factories.BeneficiaryGrant18Factory(
            publicName="James Bond", firstName="James", lastName="Bond", email="*****@*****.**"
        )
        booking2 = booking_factories.IndividualBookingFactory(
            user=other_beneficiary,
            individualBooking__user=other_beneficiary,
            stock__offer=offer,
            stock__price=0,
            token="12345",
            quantity=1,
        )
        bookings = [booking, booking2]

        # When
        mailjet_data = retrieve_offerer_bookings_recap_email_data_after_offerer_cancellation(bookings)

        # Then
        assert mailjet_data == {
            "MJ-TemplateID": 1116333,
            "MJ-TemplateLanguage": True,
            "Vars": {
                "offer_name": "Le récit de voyage",
                "lien_offre_pcpro": "http://pc_pro.com/offer_link",
                "venue_name": "La grande librairie",
                "price": "Gratuit",
                "is_event": 0,
                "event_date": "",
                "event_hour": "",
                "quantity": 7,
                "reservations_number": 2,
                "users": [
                    {"countermark": "12346", "email": "*****@*****.**", "firstName": "John", "lastName": "Doe"},
                    {"countermark": "12345", "email": "*****@*****.**", "firstName": "James", "lastName": "Bond"},
                ],
            },
        }
    def test_should_send_two_emails_to_beneficiary_when_they_book_and_other_things_have_soon_to_be_expired_bookings(
            self,
            build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary
    ):
        # given
        now = datetime.utcnow()
        user = users_factories.BeneficiaryGrant18Factory(
            email="*****@*****.**")
        created_5_days_ago = now - timedelta(days=5)
        created_23_days_ago = now - timedelta(days=23)

        book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id)
        soon_to_be_expired_book_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=book,
            stock__offer__name="Fondation",
            stock__offer__venue__name="Première Fondation",
            dateCreated=created_5_days_ago,
            user=user,
        )

        cd = ProductFactory(
            subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE.id)
        soon_to_be_expired_cd_booking = booking_factories.IndividualBookingFactory(
            stock__offer__product=cd,
            stock__offer__name="Fondation et Empire",
            stock__offer__venue__name="Seconde Fondation",
            dateCreated=created_23_days_ago,
            user=user,
        )

        # when
        send_soon_to_be_expired_individual_bookings_recap_email_to_beneficiary(
            user,
            [soon_to_be_expired_book_booking, soon_to_be_expired_cd_booking])

        # then
        call1 = call(beneficiary=user,
                     bookings=[soon_to_be_expired_book_booking],
                     days_before_cancel=5,
                     days_from_booking=5)
        call2 = call(beneficiary=user,
                     bookings=[soon_to_be_expired_cd_booking],
                     days_before_cancel=7,
                     days_from_booking=23)
        calls = [call1, call2]

        build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary.assert_has_calls(
            calls, any_order=False)

        assert build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary.call_count == 2
        assert len(mails_testing.outbox) == 2  # test number of emails sent
        assert mails_testing.outbox[0].sent_data["MJ-TemplateID"] == 12345
        assert mails_testing.outbox[1].sent_data["MJ-TemplateID"] == 12345
    def test_should_send_email_to_offerer_when_expired_bookings_cancelled(
            self, app):
        offerer = OffererFactory()
        expired_today_dvd_booking = booking_factories.IndividualBookingFactory(
            stock__offer__bookingEmail="*****@*****.**")
        expired_today_cd_booking = booking_factories.IndividualBookingFactory(
            stock__offer__bookingEmail="*****@*****.**")

        send_expired_individual_bookings_recap_email_to_offerer(
            offerer, [expired_today_cd_booking, expired_today_dvd_booking])
        assert len(mails_testing.outbox) == 1
        assert mails_testing.outbox[0].sent_data["Mj-TemplateID"] == 3095184
        assert mails_testing.outbox[0].sent_data["Vars"]
Ejemplo n.º 11
0
    def test_insufficient_funds_when_user_has_negative_deposit(self):
        # The user once booked.
        user = users_factories.BeneficiaryGrant18Factory(deposit__version=1)
        factories.IndividualBookingFactory(individualBooking__user=user)
        assert user.wallet_balance == 490

        # But now their deposit expired.
        self._expire_deposit(user)

        # They are not allowed to book non-free offers anymore.
        with pytest.raises(sqlalchemy.exc.InternalError) as exc:
            factories.IndividualBookingFactory(individualBooking__user=user)
            assert "insufficientFunds" in exc.args[0]
Ejemplo n.º 12
0
    def test_user_can_cancel_even_if_expired_deposit(self):
        # The user once booked.
        booking = factories.IndividualBookingFactory()
        user = booking.individualBooking.user
        booking_to_cancel = factories.IndividualBookingFactory(
            individualBooking__user=user)

        # But now their deposit expired.
        self._expire_deposit(user)

        # They should be able to cancel their booking.
        api.cancel_booking_by_beneficiary(user, booking_to_cancel)
        assert booking_to_cancel.isCancelled
        assert booking_to_cancel.status is BookingStatus.CANCELLED
Ejemplo n.º 13
0
 def should_update_bookings_cancellation_limit_dates_for_event_beginning_in_a_week(self):
     #  Given
     recent_booking = booking_factories.IndividualBookingFactory(
         stock__beginningDatetime=datetime.now() + timedelta(days=90)
     )
     old_booking = booking_factories.IndividualBookingFactory(
         stock=recent_booking.stock, dateCreated=(datetime.now() - timedelta(days=7))
     )
     # When
     updated_bookings = api.update_cancellation_limit_dates(
         bookings_to_update=[recent_booking, old_booking], new_beginning_datetime=datetime.now() + timedelta(days=7)
     )
     # Then
     assert updated_bookings == [recent_booking, old_booking]
     assert recent_booking.cancellationLimitDate == old_booking.cancellationLimitDate == datetime(2020, 11, 19, 15)
Ejemplo n.º 14
0
    def test_should_return_bookings_by_beneficiary_id(self, app):
        # Given
        beneficiary_1 = BeneficiaryGrant18Factory()
        beneficiary_2 = BeneficiaryGrant18Factory()
        offer = EventOfferFactory()
        stock = EventStockFactory(offer=offer)
        booking1 = booking_factories.IndividualBookingFactory(individualBooking__user=beneficiary_1, stock=stock)
        booking_factories.IndividualBookingFactory(individualBooking__user=beneficiary_2, stock=stock)

        # When
        result = BeneficiaryBookingsSQLRepository().get_beneficiary_bookings(beneficiary_id=beneficiary_1.id)

        # Then
        assert len(result.bookings) == 1
        assert result.bookings[0].id == booking1.id
Ejemplo n.º 15
0
    def test_deposit_balance(self):
        deposit = users_factories.DepositGrantFactory()

        bookings_factories.IndividualBookingFactory(
            individualBooking__attached_deposit=deposit,
            isUsed=True,
            amount=10)
        bookings_factories.IndividualBookingFactory(
            individualBooking__attached_deposit=deposit,
            isUsed=False,
            amount=1)

        assert db.session.query(func.get_deposit_balance(
            deposit.id, False)).first()[0] == 289
        assert db.session.query(func.get_deposit_balance(
            deposit.id, True)).first()[0] == 290
Ejemplo n.º 16
0
    def test_should_returns_204_with_cancellation_allowed(self, client):
        # Given
        stock = offers_factories.EventStockFactory(
            offer__name="Chouette concert")
        booking = bookings_factories.IndividualBookingFactory(stock=stock)
        ApiKeyFactory(offerer=booking.offerer)

        # When
        response = client.patch(
            f"/v2/bookings/cancel/token/{booking.token}",
            headers={"Authorization": "Bearer " + DEFAULT_CLEAR_API_KEY},
        )

        # Then
        # cancellation can trigger more than one request to Batch
        assert len(push_testing.requests) >= 1
        assert response.status_code == 204
        updated_booking = Booking.query.one()
        assert updated_booking.isCancelled
        assert updated_booking.status is BookingStatus.CANCELLED

        assert push_testing.requests[-1] == {
            "group_id": "Cancel_booking",
            "message": {
                "body":
                """Ta réservation "Chouette concert" a été annulée par l'offreur.""",
                "title": "Réservation annulée",
            },
            "user_ids": [booking.individualBooking.userId],
        }
    def test_should_sends_email_to_beneficiary_when_pro_cancels_booking(self):
        # Given
        booking = booking_factories.IndividualBookingFactory(
            individualBooking__user__email="*****@*****.**",
            user__firstName="Jeanne",
        )

        # When
        send_warning_to_user_after_pro_booking_cancellation(booking)

        # Then
        assert mails_testing.outbox[0].sent_data == {
            "FromEmail": "*****@*****.**",
            "MJ-TemplateID": 1116690,
            "MJ-TemplateLanguage": True,
            "To": "*****@*****.**",
            "Vars": {
                "event_date": "",
                "event_hour": "",
                "is_event": 0,
                "is_free_offer": 0,
                "is_thing": 1,
                "is_online": 0,
                "offer_name": booking.stock.offer.name,
                "offer_price": "10.00",
                "offerer_name": booking.offerer.name,
                "user_first_name": "Jeanne",
                "user_last_name": "Doux",
                "venue_name": booking.venue.name,
                "env": "-development",
            },
        }
Ejemplo n.º 18
0
    def test_use_activation_code_instead_of_token_if_possible(self):
        booking = bookings_factories.IndividualBookingFactory(
            individualBooking__user__email="*****@*****.**",
            quantity=10,
            stock__price=0,
            stock__offer__product__subcategoryId=subcategories.VOD.id,
            stock__offer__product__url="http://example.com?token={token}&offerId={offerId}&email={email}",
            stock__offer__name="Super offre numérique",
            dateCreated=datetime.utcnow(),
        )
        offers_factories.ActivationCodeFactory(stock=booking.stock, booking=booking, code="code_toto")
        mediation = offers_factories.MediationFactory(offer=booking.stock.offer)

        email_data = retrieve_data_for_beneficiary_booking_confirmation_email(booking.individualBooking)

        expected = get_expected_base_email_data(
            booking,
            mediation,
            all_but_not_virtual_thing=0,
            all_things_not_virtual_thing=0,
            event_date="",
            event_hour="",
            is_event=0,
            is_single_event=0,
            offer_name="Super offre numérique",
            offer_price="Gratuit",
            can_expire=0,
            offer_token="code_toto",
            is_digital_booking_with_activation_code_and_no_expiration_date=1,
            code_expiration_date="",
            has_offer_url=1,
            digital_offer_url=f"http://example.com?token=code_toto&offerId={humanize(booking.stock.offer.id)}&[email protected]",
            expiration_delay="",
        )
        assert email_data == expected
    def test_returns_payments_matching_message(self, app):
        # given
        beneficiary = users_factories.BeneficiaryGrant18Factory()
        booking = bookings_factories.IndividualBookingFactory(individualBooking__user=beneficiary)
        offerer = booking.offerer
        transaction1 = create_payment_message(name="XML1")
        transaction2 = create_payment_message(name="XML2")
        transaction3 = create_payment_message(name="XML3")
        uuid1, uuid2, uuid3 = uuid.uuid4(), uuid.uuid4(), uuid.uuid4()
        payments = [
            create_payment(booking, offerer, 5, transaction_end_to_end_id=uuid1, payment_message=transaction1),
            create_payment(booking, offerer, 5, transaction_end_to_end_id=uuid2, payment_message=transaction2),
            create_payment(booking, offerer, 5, transaction_end_to_end_id=uuid1, payment_message=transaction3),
            create_payment(booking, offerer, 5, transaction_end_to_end_id=uuid3, payment_message=transaction1),
            create_payment(booking, offerer, 5, transaction_end_to_end_id=uuid1, payment_message=transaction1),
        ]
        repository.save(*payments)

        # when
        matching_payments = payment_queries.find_payments_by_message("XML1")

        # then
        assert len(matching_payments) == 3
        for payment in matching_payments:
            assert payment.paymentMessageName == "XML1"
Ejemplo n.º 20
0
def test_booking_completed_url_gets_normalized():
    booking = factories.IndividualBookingFactory(
        token="ABCDEF",
        individualBooking__user__email="*****@*****.**",
        stock__offer__url="example.com?token={token}&email={email}",
    )
    assert booking.completedUrl == "http://example.com?token=ABCDEF&[email protected]"
Ejemplo n.º 21
0
    def test_does_not_modify_statuses_on_given_payments_if_a_payment_id_is_not_found(
            self, app):
        # given
        booking = booking_factories.IndividualBookingFactory()
        offerer = booking.offerer

        transaction1 = create_payment_message(name="XML1")
        transaction2 = create_payment_message(name="XML2")

        uuid1, uuid2 = uuid.uuid4(), uuid.uuid4()

        payment1 = create_payment(booking,
                                  offerer,
                                  5,
                                  transaction_end_to_end_id=uuid1,
                                  payment_message=transaction1)
        payment2 = create_payment(booking,
                                  offerer,
                                  5,
                                  transaction_end_to_end_id=uuid2,
                                  payment_message=transaction2)

        repository.save(payment1, payment2)

        # when
        do_ban_payments("XML1", [payment1.id, 123456])

        # then
        assert payment1.currentStatus.status == TransactionStatus.PENDING
        assert payment2.currentStatus.status == TransactionStatus.PENDING
    def expect_the_booking_to_be_cancelled_by_current_user(self, app):
        # Given
        in_four_days = datetime.utcnow() + timedelta(days=4)
        stock = offers_factories.EventStockFactory(
            beginningDatetime=in_four_days)
        booking = bookings_factories.IndividualBookingFactory(stock=stock)

        # When
        client = TestClient(app.test_client()).with_session_auth(booking.email)
        response = client.put(f"/bookings/{humanize(booking.id)}/cancel")
        booking = Booking.query.get(booking.id)

        # Then
        assert response.status_code == 200
        assert booking.isCancelled
        assert booking.status is BookingStatus.CANCELLED
        assert response.json == {
            "amount": 10.0,
            "completedUrl": None,
            "id": humanize(booking.id),
            "isCancelled": True,
            "quantity": booking.quantity,
            "stock": {
                "price": 10.0
            },
            "stockId": humanize(stock.id),
            "token": booking.token,
            "activationCode": None,
            "qrCode": None,
        }
Ejemplo n.º 23
0
    def test_toggle_visibility(self, app):
        user = users_factories.BeneficiaryGrant18Factory(email=self.identifier)
        access_token = create_access_token(identity=self.identifier)

        booking = booking_factories.IndividualBookingFactory(
            individualBooking__user=user, displayAsEnded=None)
        booking_id = booking.id

        test_client = TestClient(app.test_client())
        test_client.auth_header = {"Authorization": f"Bearer {access_token}"}

        response = test_client.post(
            f"/native/v1/bookings/{booking_id}/toggle_display",
            json={"ended": True})

        assert response.status_code == 204
        db.session.refresh(booking)
        assert booking.displayAsEnded

        response = test_client.post(
            f"/native/v1/bookings/{booking_id}/toggle_display",
            json={"ended": False})

        assert response.status_code == 204
        db.session.refresh(booking)
        assert not booking.displayAsEnded
    def test_only_suspend_beneficiary_users_in_given_emails_providers_list(
            self):
        # Given
        fraudulent_emails_providers = ["example.com"]
        admin_user = AdminFactory()
        beneficiary_fraudulent_user = BeneficiaryGrant18Factory(
            email="*****@*****.**")
        beneficiary_fraudulent_user_with_uppercase_domain = BeneficiaryGrant18Factory(
            email="*****@*****.**")
        beneficiary_fraudulent_user_with_subdomain = BeneficiaryGrant18Factory(
            email="*****@*****.**")
        non_beneficiary_fraudulent_user = UserFactory(
            email="*****@*****.**")
        booking_factories.IndividualBookingFactory(
            individualBooking__user=beneficiary_fraudulent_user,
            stock__price=1)

        # When
        suspend_fraudulent_beneficiary_users_by_email_providers(
            fraudulent_emails_providers, admin_user, dry_run=False)

        # Then
        assert not beneficiary_fraudulent_user.isActive
        assert not beneficiary_fraudulent_user_with_uppercase_domain.isActive

        # Do not handle sub-domains
        assert beneficiary_fraudulent_user_with_subdomain.isActive

        assert non_beneficiary_fraudulent_user.isActive
Ejemplo n.º 25
0
 def test_should_raises_resource_gone_error_if_not_used(self, app):
     booking = factories.IndividualBookingFactory(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"
     ]
Ejemplo n.º 26
0
    def test_basics(self):
        offerer = offers_factories.OffererFactory(name="offerer",
                                                  siren="123456")
        booking = bookings_factories.IndividualBookingFactory(
            stock__offer__venue__managingOfferer=offerer)
        reimbursement = BookingReimbursement(booking,
                                             PhysicalOffersReimbursement(),
                                             Decimal(10))
        batch_date = datetime.utcnow()

        payment = create_payment_for_booking(reimbursement, batch_date)

        assert payment.bookingId == booking.id
        assert payment.amount == 10
        assert payment.reimbursementRule == PhysicalOffersReimbursement(
        ).description
        assert payment.reimbursementRate == PhysicalOffersReimbursement().rate
        assert payment.comment is None
        assert payment.author == "batch"
        assert payment.transactionLabel == "pass Culture Pro - remboursement 1ère quinzaine 01-2021"
        assert payment.batchDate == batch_date
        assert payment.iban is None
        assert payment.bic is None
        assert payment.recipientName == "offerer"
        assert payment.recipientSiren == "123456"
Ejemplo n.º 27
0
 def test_mark_as_used_when_stock_starts_soon(self):
     booking = booking_factories.IndividualBookingFactory(
         stock__beginningDatetime=datetime.now() + timedelta(days=1)
     )
     api.mark_as_used(booking)
     assert booking.isUsed
     assert booking.status is BookingStatus.USED
Ejemplo n.º 28
0
    def test_should_return_digital_thing_specific_data_for_email_when_offer_is_a_digital_thing(self):
        booking = bookings_factories.IndividualBookingFactory(
            quantity=10,
            stock__price=0,
            stock__offer__product__subcategoryId=subcategories.VOD.id,
            stock__offer__product__url="http://example.com",
            stock__offer__name="Super offre numérique",
            dateCreated=datetime.utcnow(),
        )
        mediation = offers_factories.MediationFactory(offer=booking.stock.offer)

        email_data = retrieve_data_for_beneficiary_booking_confirmation_email(booking.individualBooking)

        expected = get_expected_base_email_data(
            booking,
            mediation,
            all_but_not_virtual_thing=0,
            all_things_not_virtual_thing=0,
            event_date="",
            event_hour="",
            is_event=0,
            is_single_event=0,
            offer_name="Super offre numérique",
            offer_price="Gratuit",
            can_expire=0,
            has_offer_url=1,
            digital_offer_url="http://example.com",
            expiration_delay="",
        )
        assert email_data == expected
Ejemplo n.º 29
0
 def should_pass_when_event_begins_in_more_than_72_hours_and_booking_created_more_than_48_hours_ago(
         self):
     next_week = datetime.utcnow() + timedelta(weeks=1)
     three_days_ago = datetime.utcnow() - timedelta(days=3)
     booking = factories.IndividualBookingFactory(
         stock__beginningDatetime=next_week, dateCreated=three_days_ago)
     validation.check_is_usable(booking)
Ejemplo n.º 30
0
    def test_reject_approved_offer_with_bookings(
        self,
        mocked_send_cancel_booking_notification,
        mocked_send_offer_validation_notification_to_administration,
        mocked_send_offer_validation_status_update_email,
        mocked_validate_csrf_token,
        app,
    ):
        users_factories.AdminFactory(email="*****@*****.**")
        with freeze_time("2020-11-17 15:00:00") as frozen_time:
            offer = offers_factories.OfferFactory(validation=OfferValidationStatus.APPROVED, isActive=True)
            stock = offers_factories.StockFactory(offer=offer, price=10)
            unused_booking = booking_factories.IndividualBookingFactory(stock=stock)
            used_booking = booking_factories.UsedBookingFactory(stock=stock)
            frozen_time.move_to("2020-12-20 15:00:00")
            data = dict(validation=OfferValidationStatus.REJECTED.value)
            client = TestClient(app.test_client()).with_session_auth("*****@*****.**")

            response = client.post(f"/pc/back-office/offer/edit/?id={offer.id}", form=data)

        assert response.status_code == 302
        assert offer.validation == OfferValidationStatus.REJECTED
        assert offer.lastValidationDate == datetime.datetime(2020, 12, 20, 15)
        assert unused_booking.isCancelled
        assert unused_booking.status is BookingStatus.CANCELLED
        assert not used_booking.isCancelled
        assert used_booking.status is not BookingStatus.CANCELLED

        mocked_send_cancel_booking_notification.assert_called_once_with([unused_booking.id])