Example #1
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(type=str(offer_type.ThingType.INSTRUMENT))
        old_guitar_booking = BookingFactory(stock__offer__product=guitar,
                                            dateCreated=two_months_ago)
        disc = ProductFactory(type=str(offer_type.ThingType.MUSIQUE))
        old_disc_booking = BookingFactory(stock__offer__product=disc,
                                          dateCreated=two_months_ago)
        audio_book = ProductFactory(type=str(offer_type.ThingType.LIVRE_AUDIO))
        old_audio_book_booking = BookingFactory(
            stock__offer__product=audio_book, dateCreated=two_months_ago)

        handle_expired_bookings.cancel_expired_bookings()

        assert old_guitar_booking.isCancelled
        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.cancellationDate.timestamp() == pytest.approx(
            datetime.utcnow().timestamp(), rel=1)
        assert old_disc_booking.cancellationReason == BookingCancellationReasons.EXPIRED

        assert not old_audio_book_booking.isCancelled
        assert not old_audio_book_booking.cancellationDate
        assert not old_audio_book_booking.cancellationReason
    def should_call_email_service_for_bookings_which_will_expire_in_7_days(
            self, mocked_email_recap, app) -> None:
        # Given
        now = date.today()
        booking_date_23_days_ago = now - timedelta(days=23)
        booking_date_22_days_ago = now - timedelta(days=22)

        dvd = ProductFactory(type=str(offer_type.ThingType.AUDIOVISUEL))
        expire_in_7_days_dvd_booking = BookingFactory(
            stock__offer__product=dvd,
            dateCreated=booking_date_23_days_ago,
            isCancelled=False,
        )
        non_expired_cd = ProductFactory(type=str(offer_type.ThingType.MUSIQUE))
        dont_expire_in_7_days_cd_booking = BookingFactory(
            stock__offer__product=non_expired_cd,
            dateCreated=booking_date_22_days_ago,
            isCancelled=False,
        )
        repository.save(dont_expire_in_7_days_cd_booking)

        # When
        notify_users_of_soon_to_be_expired_bookings()

        # Then
        mocked_email_recap.assert_called_once_with(
            expire_in_7_days_dvd_booking.user, [expire_in_7_days_dvd_booking])
Example #3
0
def test_cancel_bookings_when_offerer_has_one_or_more():
    # Given
    fraudulent_emails_providers = ["example.com"]
    admin_user = AdminFactory(email="*****@*****.**")
    beneficiary1 = BeneficiaryGrant18Factory(email="*****@*****.**")
    beneficiary2 = BeneficiaryGrant18Factory(email="*****@*****.**")
    fraudulent_user = ProFactory(email="*****@*****.**", )
    offerer_with_bookings = OffererFactory()
    UserOffererFactory(user=fraudulent_user, offerer=offerer_with_bookings)
    offer1 = OfferFactory(venue__managingOfferer=offerer_with_bookings)
    offer2 = OfferFactory(venue__managingOfferer=offerer_with_bookings)
    stock1 = StockFactory(offer=offer1)
    stock2 = StockFactory(offer=offer2)
    booking1 = BookingFactory(user=beneficiary1, stock=stock1)
    booking2 = BookingFactory(user=beneficiary2, stock=stock2)

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

    # Then
    assert Offerer.query.count() == 1
    assert Venue.query.count() == 2
    assert Offer.query.count() == 2
    assert Stock.query.count() == 2
    assert Booking.query.count() == 2
    assert booking1.isCancelled
    assert booking1.status is BookingStatus.CANCELLED
    assert booking1.cancellationReason is BookingCancellationReasons.FRAUD
    assert booking2.isCancelled
    assert booking2.status is BookingStatus.CANCELLED
    assert booking2.cancellationReason is BookingCancellationReasons.FRAUD
Example #4
0
    def test_should_send_email_to_beneficiary_when_expired_bookings_cancelled(
            self, app):
        amnesiac_user = users_factories.UserFactory(email="*****@*****.**")
        expired_today_dvd_booking = BookingFactory(user=amnesiac_user, )
        expired_today_cd_booking = BookingFactory(user=amnesiac_user, )
        send_expired_bookings_recap_email_to_beneficiary(
            amnesiac_user,
            [expired_today_cd_booking, expired_today_dvd_booking])

        assert mails_testing.outbox[0].sent_data["Mj-TemplateID"] == 1951103
Example #5
0
    def test_should_send_email_to_offerer_when_expired_bookings_cancelled(
            self, app):
        offerer = OffererFactory()
        expired_today_dvd_booking = BookingFactory()
        expired_today_cd_booking = BookingFactory()

        send_expired_bookings_recap_email_to_offerer(
            offerer, [expired_today_cd_booking, expired_today_dvd_booking])

        assert mails_testing.outbox[0].sent_data["Mj-TemplateID"] == 1952508
Example #6
0
def test_should_send_email_to_offerer_when_expired_bookings_cancelled(
        self, app):
    now = datetime.utcnow()
    amnesiac_user = users_factories.UserFactory(email="*****@*****.**",
                                                firstName="Dory")
    long_ago = now - timedelta(days=31)
    dvd = ProductFactory(type=str(offer_type.ThingType.AUDIOVISUEL))
    expired_today_dvd_booking = BookingFactory(
        stock__offer__product=dvd,
        stock__offer__name="Memento",
        stock__offer__venue__name="Mnémosyne",
        dateCreated=long_ago,
        isCancelled=True,
        cancellationReason=BookingCancellationReasons.EXPIRED,
        user=amnesiac_user,
    )

    cd = ProductFactory(type=str(offer_type.ThingType.MUSIQUE))
    expired_today_cd_booking = BookingFactory(
        stock__offer__product=cd,
        stock__offer__name="Random Access Memories",
        stock__offer__venue__name="Virgin Megastore",
        dateCreated=long_ago,
        isCancelled=True,
        cancellationReason=BookingCancellationReasons.EXPIRED,
        user=amnesiac_user,
    )

    email_data = build_expired_bookings_recap_email_data_for_beneficiary(
        amnesiac_user,
        [expired_today_dvd_booking, expired_today_cd_booking],
    )

    assert email_data == {
        "FromEmail": "*****@*****.**",
        "Mj-TemplateID": 1951103,
        "Mj-TemplateLanguage": True,
        "To": "*****@*****.**",
        "Vars": {
            "user_firstName":
            "Dory",
            "bookings": [
                {
                    "offer_name": "Memento",
                    "venue_name": "Mnémosyne"
                },
                {
                    "offer_name": "Random Access Memories",
                    "venue_name": "Virgin Megastore"
                },
            ],
            "env":
            "-development",
        },
    }
Example #7
0
    def test_should_send_email_to_beneficiary_when_expired_bookings_cancelled(
            self, app):
        amnesiac_user = users_factories.UserFactory(email="*****@*****.**")
        expired_today_dvd_booking = BookingFactory(user=amnesiac_user, )
        expired_today_cd_booking = BookingFactory(user=amnesiac_user, )
        mocked_send_email = Mock()

        send_expired_bookings_recap_email_to_beneficiary(
            amnesiac_user,
            [expired_today_cd_booking, expired_today_dvd_booking],
            mocked_send_email)

        mocked_send_email.assert_called_once()
        mocked_send_email.call_args_list[0][1]["MJ-TemplateID"] = 1951103
Example #8
0
    def should_notify_of_todays_expired_bookings(self, mocked_send_email_recap,
                                                 mocked_send_raw_email, app,
                                                 caplog) -> None:
        caplog.set_level(logging.INFO)
        now = datetime.utcnow()
        yesterday = now - timedelta(days=1)
        long_ago = now - timedelta(days=31)
        very_long_ago = now - timedelta(days=32)
        dvd = ProductFactory(type=str(offer_type.ThingType.AUDIOVISUEL))
        expired_today_dvd_booking = BookingFactory(
            stock__offer__product=dvd,
            dateCreated=long_ago,
            isCancelled=True,
            cancellationReason=BookingCancellationReasons.EXPIRED,
        )
        cd = ProductFactory(type=str(offer_type.ThingType.MUSIQUE))
        expired_today_cd_booking = BookingFactory(
            stock__offer__product=cd,
            dateCreated=long_ago,
            isCancelled=True,
            cancellationReason=BookingCancellationReasons.EXPIRED,
        )
        painting = ProductFactory(type=str(offer_type.ThingType.OEUVRE_ART))
        expired_yesterday_painting_booking = BookingFactory(
            stock__offer__product=painting,
            dateCreated=very_long_ago,
            isCancelled=True,
            cancellationReason=BookingCancellationReasons.EXPIRED,
        )
        expired_yesterday_painting_booking.cancellationDate = yesterday
        repository.save(expired_yesterday_painting_booking)

        handle_expired_bookings.notify_offerers_of_expired_bookings()

        assert (
            caplog.records[1].message ==
            f"[notify_users_of_expired_bookings] 2 Offerers have been notified: [{expired_today_dvd_booking.stock.offer.venue.managingOfferer},"
            f" {expired_today_cd_booking.stock.offer.venue.managingOfferer}]")
        assert str(expired_yesterday_painting_booking) not in caplog.text
        assert mocked_send_email_recap.call_args_list[0][0] == (
            expired_today_dvd_booking.stock.offer.venue.managingOfferer,
            [expired_today_dvd_booking],
            mocked_send_raw_email,
        )
        assert mocked_send_email_recap.call_args_list[1][0] == (
            expired_today_cd_booking.stock.offer.venue.managingOfferer,
            [expired_today_cd_booking],
            mocked_send_raw_email,
        )
Example #9
0
    def test_should_send_email_to_offerer_when_expired_bookings_cancelled(
            self, app):
        offerer = OffererFactory()
        expired_today_dvd_booking = BookingFactory()
        expired_today_cd_booking = BookingFactory()
        mocked_send_email = Mock()

        send_expired_bookings_recap_email_to_offerer(
            offerer, [expired_today_cd_booking, expired_today_dvd_booking],
            mocked_send_email)

        mocked_send_email.assert_called_once()
        mocked_send_email.call_args_list[0][1]["MJ-TemplateID"] = 1952508
        mocked_send_email.call_args_list[0][1][
            "recipients"] = "*****@*****.**"
Example #10
0
    def test_should_sends_email_to_beneficiary_when_pro_cancels_booking(self):
        # Given
        booking = BookingFactory(user__email="*****@*****.**",
                                 user__firstName="Jeanne")

        # When
        send_warning_to_beneficiary_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.stock.offer.venue.managingOfferer.name,
                "user_first_name": "Jeanne",
                "can_book_again": True,
                "venue_name": booking.stock.offer.venue.name,
                "env": "-development",
            },
        }
    def test_should_return_booking_with_expected_information(self):
        # Given
        booking = BookingFactory(
            amount=1,
            quantity=1,
            token="GQTQR9",
            stock__price=10,
        )

        # When
        serialized = serialize_booking_minimal(booking)

        # Then
        assert serialized == {
            "amount": 1.0,
            "isCancelled": booking.isCancelled,
            "id": humanize(booking.id),
            "stockId": humanize(booking.stockId),
            "quantity": 1,
            "stock": {
                "price": 10,
            },
            "token": "GQTQR9",
            "completedUrl": None,
        }
Example #12
0
    def test_send_only_to_admin(self):
        booking = BookingFactory()

        send_booking_recap_emails(booking)

        assert mails_testing.outbox[0].sent_data[
            "To"] == "*****@*****.**"
Example #13
0
        def when_user_has_cancelled_some_offers(self, app):
            # Given
            BookingFactory(isCancelled=True,
                           user__email="*****@*****.**",
                           user__postalCode="75130")

            # When
            response = TestClient(app.test_client()).with_auth(
                "*****@*****.**").get("/beneficiaries/current")

            # Then
            assert response.json["wallet_balance"] == 500.0
            assert response.json["expenses"] == [
                {
                    "domain": "all",
                    "current": 0.0,
                    "max": 500.0
                },
                {
                    "domain": "digital",
                    "current": 0.0,
                    "max": 200.0
                },
                {
                    "domain": "physical",
                    "current": 0.0,
                    "max": 200.0
                },
            ]
    def test_cancellation_limit_date_is_saved_to_db(self):
        booking = BookingFactory(
            stock__beginningDatetime=datetime.datetime.utcnow())
        generated_cancellation_limit_date = booking.cancellationLimitDate

        booking_from_db = Booking.query.first()

        assert booking_from_db.cancellationLimitDate == generated_cancellation_limit_date
Example #15
0
    def test_send_to_offerer_and_admin(self):
        booking = BookingFactory(
            stock__offer__bookingEmail="*****@*****.**", )

        send_booking_recap_emails(booking)

        assert mails_testing.outbox[0].sent_data[
            "To"] == "[email protected], [email protected]"
Example #16
0
    def should_not_cancel_new_thing_that_can_expire_booking(self, app) -> None:
        book = ProductFactory(type=str(offer_type.ThingType.LIVRE_EDITION))
        book_booking = BookingFactory(stock__offer__product=book)

        handle_expired_bookings.cancel_expired_bookings()

        assert not book_booking.isCancelled
        assert not book_booking.cancellationDate
        assert not book_booking.cancellationReason
Example #17
0
    def test_send_only_to_admin(self, feature_send_mail_to_users_enabled):
        booking = BookingFactory()
        mocked_send_email = Mock()

        send_booking_recap_emails(booking, mocked_send_email)

        mocked_send_email.assert_called_once()
        data = mocked_send_email.call_args_list[0][1]["data"]
        assert data["To"] == "*****@*****.**"
Example #18
0
    def test_queries_performance(self, app) -> None:
        now = datetime.utcnow()
        two_months_ago = now - timedelta(days=60)
        book = ProductFactory(type=str(offer_type.ThingType.LIVRE_EDITION))
        user = UserFactory()
        BookingFactory.create_batch(size=10,
                                    stock__offer__product=book,
                                    dateCreated=two_months_ago,
                                    user=user)
        n_queries = (
            1  # select count
            + 1  # select initial ids
            + 1  # release savepoint/COMMIT
            + 4 * 3  # update, release savepoint/COMMIT, select next ids
        )

        with assert_num_queries(n_queries):
            handle_expired_bookings.cancel_expired_bookings(batch_size=3)
Example #19
0
    def test_build_soon_to_be_expired_bookings_data(self, app):
        # Given
        beneficiary = UserFactory(email="*****@*****.**",
                                  firstName="ASIMOV",
                                  isBeneficiary=True,
                                  isAdmin=False)
        bookings = [
            BookingFactory(
                stock__offer__name="offre 1",
                stock__offer__venue__name="venue 1",
            ),
            BookingFactory(
                stock__offer__name="offre 2",
                stock__offer__venue__name="venue 2",
            ),
        ]

        # When
        data = build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary(
            beneficiary, bookings)

        # Then
        assert data == {
            "FromEmail": "*****@*****.**",
            "Mj-TemplateID": 1927224,
            "Mj-TemplateLanguage": True,
            "To": "*****@*****.**",
            "Vars": {
                "user_firstName":
                "ASIMOV",
                "bookings": [
                    {
                        "offer_name": "offre 1",
                        "venue_name": "venue 1"
                    },
                    {
                        "offer_name": "offre 2",
                        "venue_name": "venue 2"
                    },
                ],
                "env":
                "-development",
            },
        }
Example #20
0
            def test_returns_max_500_and_actual_210(self):
                # Given
                beneficiary = UserFactory()
                BookingFactory(
                    user=beneficiary,
                    amount=90,
                )
                BookingFactory(user=beneficiary, amount=60, quantity=2)
                BookingFactory(user=beneficiary, amount=20, isCancelled=True)

                # when
                expenses = beneficiary.expenses

                # Then
                assert expenses == [
                    {"domain": "all", "current": 210.0, "max": 500},
                    {"domain": "digital", "current": 0.0, "max": 200},
                    {"domain": "physical", "current": 210.0, "max": 200},
                ]
Example #21
0
    def test_send_to_developers(self, mock_feature_send_mail_to_users_enabled):
        booking = BookingFactory(
            stock__offer__bookingEmail="*****@*****.**", )
        mocked_send_email = Mock()

        send_booking_recap_emails(booking, mocked_send_email)

        mocked_send_email.assert_called_once()
        data = mocked_send_email.call_args_list[0][1]["data"]
        assert data["To"] == "*****@*****.**"
Example #22
0
    def should_not_update_cancelled_old_thing_that_can_expire_booking(
            self, app) -> None:
        fifty_days_ago = datetime.utcnow() - timedelta(days=50)
        forty_days_ago = datetime.utcnow() - timedelta(days=40)
        book = ProductFactory(type=str(offer_type.ThingType.LIVRE_EDITION))
        old_book_booking = BookingFactory(
            stock__offer__product=book,
            dateCreated=fifty_days_ago,
            isCancelled=True,
            cancellationReason=BookingCancellationReasons.BENEFICIARY,
        )
        old_book_booking.cancellationDate = forty_days_ago
        repository.save()

        handle_expired_bookings.cancel_expired_bookings()

        assert old_book_booking.isCancelled
        assert old_book_booking.cancellationDate == forty_days_ago
        assert old_book_booking.cancellationReason == BookingCancellationReasons.BENEFICIARY
Example #23
0
    def test_should_return_0_offer_when_all_available_stock_is_booked(self, app):
        # Given
        beneficiary = users_factories.BeneficiaryGrant18Factory()
        offer = ThingOfferFactory()
        stock = ThingStockFactory(offer=offer, price=0, quantity=3)
        BookingFactory(user=beneficiary, stock=stock, quantity=2)
        BookingFactory(user=beneficiary, stock=stock, quantity=1)

        # When
        bookings_quantity = _build_bookings_quantity_subquery()
        offers_count = (
            Offer.query.join(Stock)
            .outerjoin(bookings_quantity, Stock.id == bookings_quantity.c.stockId)
            .filter((Stock.quantity == None) | ((Stock.quantity - func.coalesce(bookings_quantity.c.quantity, 0)) > 0))
            .count()
        )

        # Then
        assert offers_count == 0
Example #24
0
    def test_should_send_email_to_beneficiary_when_they_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.UserFactory(email="*****@*****.**",
                                           isBeneficiary=True,
                                           isAdmin=False)
        created_23_days_ago = now - timedelta(days=23)

        dvd = ProductFactory(type=str(offer_type.ThingType.AUDIOVISUEL))
        soon_to_be_expired_dvd_booking = BookingFactory(
            stock__offer__product=dvd,
            stock__offer__name="Fondation",
            stock__offer__venue__name="Première Fondation",
            dateCreated=created_23_days_ago,
            user=user,
        )

        cd = ProductFactory(type=str(offer_type.ThingType.MUSIQUE))
        soon_to_be_expired_cd_booking = BookingFactory(
            stock__offer__product=cd,
            stock__offer__name="Fondation et Empire",
            stock__offer__venue__name="Seconde Fondation",
            dateCreated=created_23_days_ago,
            user=user,
        )
        mocked_send_email = Mock()

        # when
        send_soon_to_be_expired_bookings_recap_email_to_beneficiary(
            user,
            [soon_to_be_expired_cd_booking, soon_to_be_expired_dvd_booking],
            mocked_send_email)

        # then
        build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary.assert_called_once_with(
            user,
            [soon_to_be_expired_cd_booking, soon_to_be_expired_dvd_booking])
        mocked_send_email.assert_called_once_with(
            data={"MJ-TemplateID": 12345})
    def test_build_soon_to_be_expired_bookings_data(self, app):
        # Given
        beneficiary = BeneficiaryGrant18Factory(email="*****@*****.**",
                                                firstName="ASIMOV")
        bookings = [
            BookingFactory(
                stock__offer__name="offre 1",
                stock__offer__venue__name="venue 1",
            ),
            BookingFactory(
                stock__offer__name="offre 2",
                stock__offer__venue__name="venue 2",
            ),
        ]

        # When
        data = build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary(
            beneficiary, bookings, days_before_cancel=7, days_from_booking=23)

        # Then
        assert data == {
            "Mj-TemplateID": 3095065,
            "Mj-TemplateLanguage": True,
            "Vars": {
                "user_firstName":
                "ASIMOV",
                "bookings": [
                    {
                        "offer_name": "offre 1",
                        "venue_name": "venue 1"
                    },
                    {
                        "offer_name": "offre 2",
                        "venue_name": "venue 2"
                    },
                ],
                "days_before_cancel":
                7,
                "days_from_booking":
                23,
            },
        }
Example #26
0
    def test_should_send_booking_cancellation_email_only_to_administration_when_no_booking_email_provided(
            self):
        # Given
        booking = BookingFactory(stock__offer__bookingEmail="")

        # When
        send_user_driven_cancellation_email_to_offerer(booking)

        # Then
        assert mails_testing.outbox[0].sent_data[
            "To"] == "*****@*****.**"
def test_pc_send_tomorrow_events_notifications_only_to_individual_bookings_users(
):
    """
    Test that each stock that is linked to an offer that occurs tomorrow and
    creates a job that will send a notification to all of the stock's users
    with a valid (not cancelled) booking, for individual bookings only.
    """
    tomorrow = datetime.now() + timedelta(days=1)
    stock_tomorrow = EventStockFactory(beginningDatetime=tomorrow,
                                       offer__name="my_offer")

    begin = datetime.now() + timedelta(days=7)
    stock_next_week = EventStockFactory(beginningDatetime=begin)

    bookings_tomorrow = IndividualBookingFactory.create_batch(
        2, stock=stock_tomorrow, isCancelled=False)
    BookingFactory.create_batch(2,
                                stock=stock_tomorrow,
                                isCancelled=True,
                                status=BookingStatus.CANCELLED)
    BookingFactory.create_batch(2, stock=stock_next_week, isCancelled=False)
    EducationalBookingFactory.create_batch(2,
                                           stock=stock_tomorrow,
                                           isCancelled=False)

    pc_send_tomorrow_events_notifications()

    assert len(testing.requests) == 1
    assert all(data["message"]["title"] == "my_offer, c'est demain !"
               for data in testing.requests)

    user_ids = set()
    for data in testing.requests:
        for user_id in data["user_ids"]:
            user_ids.add(user_id)

    expected_user_ids = {
        booking.individualBooking.userId
        for booking in bookings_tomorrow
    }
    assert user_ids == expected_user_ids
        def when_user_is_logged_in_expect_booking_with_token_in_lower_case_to_be_used(self, app):
            booking = BookingFactory(token="ABCDEF")
            pro_user = UserFactory(email="*****@*****.**")
            offerer = booking.stock.offer.venue.managingOfferer
            offers_factories.UserOffererFactory(user=pro_user, offerer=offerer)

            url = f"/v2/bookings/use/token/{booking.token.lower()}"
            response = TestClient(app.test_client()).with_auth("*****@*****.**").patch(url)

            assert response.status_code == 204
            booking = Booking.query.one()
            assert booking.isUsed
Example #29
0
        def expect_booking_to_be_used(self, app):
            booking = BookingFactory(token="ABCDEF")

            url = (
                f"/bookings/token/{booking.token}?"
                f"email={booking.user.email}&offer_id={humanize(booking.stock.offerId)}"
            )
            response = TestClient(app.test_client()).patch(url)

            assert response.status_code == 204
            booking = Booking.query.one()
            assert booking.isUsed
    def test_already_booked(self, app):
        user = users_factories.UserFactory(email=self.identifier)
        booking = BookingFactory(user=user)

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

        response = test_client.post("/native/v1/book_offer", json={"stockId": booking.stock.id, "quantity": 1})

        assert response.status_code == 400
        assert response.json["code"] == "ALREADY_BOOKED"