def test_reimburses_95_percent_for_book_product_when_bookings_exceed_100000_euros(
            self):
        # Given
        cutoff = datetime.datetime.now()
        before_cutoff = cutoff - datetime.timedelta(days=1)

        beneficiary = users_factories.BeneficiaryGrant18Factory(
            email="*****@*****.**")
        offerer1 = offers_factories.OffererFactory(siren="123456789")
        offers_factories.BankInformationFactory(
            bic="BDFEFR2LCCB",
            iban="FR7630006000011234567890189",
            offerer=offerer1)
        venue1 = offers_factories.VenueFactory(managingOfferer=offerer1,
                                               siret="12345678912345")
        venue2 = offers_factories.VenueFactory(managingOfferer=offerer1,
                                               siret="98765432154321")
        venue3 = offers_factories.VenueFactory(managingOfferer=offerer1,
                                               siret="98123432154321")
        product = offers_factories.ThingProductFactory(
            subcategoryId=subcategories.LIVRE_PAPIER.id)
        offer1 = offers_factories.ThingOfferFactory(venue=venue1,
                                                    product=product)
        offer2 = offers_factories.ThingOfferFactory(venue=venue2,
                                                    product=product)
        offer3 = offers_factories.ThingOfferFactory(venue=venue3,
                                                    product=product)

        paying_stock1 = offers_factories.ThingStockFactory(offer=offer1,
                                                           price=10000)
        paying_stock2 = offers_factories.ThingStockFactory(offer=offer2,
                                                           price=10000)
        paying_stock3 = offers_factories.ThingStockFactory(offer=offer3,
                                                           price=100000)
        offers_factories.ThingStockFactory(offer=offer1, price=0)

        beneficiary.deposit.amount = 120000
        repository.save(beneficiary.deposit)

        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock1,
                                              dateUsed=before_cutoff,
                                              quantity=1)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock2,
                                              dateUsed=before_cutoff,
                                              quantity=1)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock3,
                                              dateUsed=before_cutoff,
                                              quantity=1)

        # When
        generate_new_payments(cutoff, batch_date=datetime.datetime.now())

        # Then
        pending = get_pending_payments()
        assert pending.count() == 3
        assert total_amount(pending) == 115000
        assert get_not_processable_payments().count() == 0
    def test_does_not_allow_beginning_datetime_on_thing_offer_on_creation_and_edition(
            self, mock_update_confirmation_dates):
        # Given
        offer = factories.ThingOfferFactory()
        beginning_date = datetime.utcnow() + timedelta(days=4)
        existing_stock = factories.StockFactory(offer=offer, price=10)
        created_stock_data = StockCreationBodyModel(
            price=-1,
            beginningDatetime=beginning_date,
            bookingLimitDatetime=beginning_date)
        edited_stock_data = StockEditionBodyModel(
            id=existing_stock.id,
            price=0,
            beginningDatetime=beginning_date,
            bookingLimitDatetime=beginning_date)

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

        # Then
        assert error.value.errors == {
            "global": [
                "Impossible de mettre une date de début si l'offre ne porte pas sur un événement"
            ],
        }
    def when_mediation_is_created_with_bad_thumb_url(self, app):
        # given
        offer = offers_factories.ThingOfferFactory()
        offerer = offer.venue.managingOfferer
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offerer,
        )

        # when
        client = TestClient(
            app.test_client()).with_auth(email="*****@*****.**")
        data = {
            "offerId": humanize(offer.id),
            "offererId": humanize(offerer.id),
            "thumbUrl": "https://example.com/image.jpg",
        }
        with requests_mock.Mocker() as mock:
            mock.get("https://example.com/image.jpg", status_code=404)
            response = client.post("/mediations", form=data)

        # then
        assert response.status_code == 400
        assert response.json == {
            "thumbUrl": ["L'adresse saisie n'est pas valide"]
        }
    def when_mediation_is_created_with_thumb_file(self, app):
        # given
        offer = offers_factories.ThingOfferFactory()
        offerer = offer.venue.managingOfferer
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offerer,
        )

        # when
        client = TestClient(
            app.test_client()).with_auth(email="*****@*****.**")
        thumb = (IMAGES_DIR / "mouette_full_size.jpg").read_bytes()
        files = {
            "offerId": humanize(offer.id),
            "offererId": humanize(offerer.id),
            "thumb": (BytesIO(thumb), "image.png"),
        }
        response = client.post("/mediations", files=files)

        # then
        assert response.status_code == 201
        mediation = Mediation.query.one()
        assert mediation.thumbCount == 1
        assert response.status_code == 201
    def when_mediation_is_created_with_thumb_url(self, app):
        # given
        offer = offers_factories.ThingOfferFactory()
        offerer = offer.venue.managingOfferer
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offerer,
        )

        # when
        client = TestClient(
            app.test_client()).with_auth(email="*****@*****.**")
        image_as_bytes = (IMAGES_DIR / "mouette_full_size.jpg").read_bytes()
        data = {
            "offerId": humanize(offer.id),
            "offererId": humanize(offerer.id),
            "thumbUrl": "https://example.com/image.jpg",
        }
        with requests_mock.Mocker() as mock:
            mock.get(
                "https://example.com/image.jpg",
                content=image_as_bytes,
                headers={"Content-Type": "image/jpeg"},
            )
            response = client.post("/mediations", form=data)

        # then
        assert response.status_code == 201
        mediation = Mediation.query.one()
        assert mediation.thumbCount == 1
        assert response.json == {
            "id": humanize(mediation.id),
        }
    def test_upsert_multiple_stocks(self, mocked_add_offer_id,
                                    mock_update_confirmation_dates):
        # Given
        offer = factories.ThingOfferFactory()
        existing_stock = factories.StockFactory(offer=offer, price=10)
        created_stock_data = StockCreationBodyModel(price=10, quantity=7)
        edited_stock_data = StockEditionBodyModel(id=existing_stock.id,
                                                  price=5,
                                                  quantity=7)

        # When
        stocks_upserted = api.upsert_stocks(
            offer_id=offer.id,
            stock_data_list=[created_stock_data, edited_stock_data])

        # Then
        created_stock = Stock.query.filter_by(id=stocks_upserted[0].id).first()
        assert created_stock.offer == offer
        assert created_stock.price == 10
        assert created_stock.quantity == 7
        edited_stock = Stock.query.filter_by(id=existing_stock.id).first()
        assert edited_stock.price == 5
        assert edited_stock.quantity == 7
        mocked_add_offer_id.assert_called_once_with(client=app.redis_client,
                                                    offer_id=offer.id)
    def test_edit_one_stock(self, app):
        # Given
        offer = offers_factories.ThingOfferFactory()
        existing_stock = offers_factories.StockFactory(offer=offer, price=10)
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offer.venue.managingOfferer,
        )

        # When
        stock_data = {
            "offerId": humanize(offer.id),
            "stocks": [{
                "id": humanize(existing_stock.id),
                "price": 20
            }],
        }
        response = TestClient(
            app.test_client()).with_auth("*****@*****.**").post(
                "/stocks/bulk/", json=stock_data)

        # Then
        assert response.status_code == 201

        response_dict = response.json
        assert len(response_dict["stockIds"]) == len(stock_data["stocks"])

        edited_stock = Stock.query.get(
            dehumanize(response_dict["stockIds"][0]["id"]))
        assert edited_stock.price == 20
    def when_user_has_no_rights_and_creating_stock_from_offer_id(
            self, app, db_session):
        # Given
        user = users_factories.UserFactory(email="*****@*****.**")
        offer = offers_factories.ThingOfferFactory()
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offer.venue.managingOfferer)
        booking_datetime = datetime.utcnow()

        # When
        stock_data = {
            "offerId":
            humanize(offer.id),
            "stocks": [
                {
                    "quantity": 10,
                    "price": 0,
                    "bookingLimitDatetime": serialize(booking_datetime),
                },
            ],
        }
        response = TestClient(app.test_client()).with_auth(user.email).post(
            "/stocks/bulk/", json=stock_data)

        # Then
        assert response.status_code == 403
        assert response.json == {
            "global": [
                "Vous n'avez pas les droits d'accès suffisant pour accéder à cette information."
            ]
        }
    def when_missing_offer_id(self, app):
        # Given
        offer = offers_factories.ThingOfferFactory()
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offer.venue.managingOfferer,
        )
        booking_limit_datetime = datetime(2019, 2, 14)

        # When
        stock_data = {
            "stocks": [
                {
                    "quantity": -2,
                    "price": 0,
                    "bookingLimitDatetime": serialize(booking_limit_datetime),
                },
            ],
        }

        response = TestClient(
            app.test_client()).with_auth("*****@*****.**").post(
                "/stocks/bulk/", json=stock_data)

        # Then
        assert response.status_code == 400
        assert response.json == {"offerId": ["Ce champ est obligatoire"]}
    def test_erase_former_mediations(self):
        # Given
        user = users_factories.UserFactory()
        offer = factories.ThingOfferFactory()
        image_as_bytes = (IMAGES_DIR / "mouette_full_size.jpg").read_bytes()
        existing_number_of_files = len(os.listdir(self.THUMBS_DIR))

        mediation_1 = api.create_mediation_v2(user, offer, "©Photographe",
                                              image_as_bytes)
        mediation_2 = api.create_mediation_v2(user, offer, "©Alice",
                                              image_as_bytes)
        thumb_1_id = humanize(mediation_1.id)
        thumb_2_id = humanize(mediation_2.id)

        # When
        api.create_mediation_v2(user, offer, "©moi", image_as_bytes)

        # Then
        mediation_3 = models.Mediation.query.one()
        assert mediation_3.credit == "©moi"
        thumb_3_id = humanize(mediation_3.id)

        assert not (self.THUMBS_DIR / thumb_1_id).exists()
        assert not (self.THUMBS_DIR / (thumb_1_id + ".type")).exists()
        assert not (self.THUMBS_DIR / thumb_2_id).exists()
        assert not (self.THUMBS_DIR / (thumb_2_id + ".type")).exists()

        assert len(os.listdir(self.THUMBS_DIR)) == existing_number_of_files + 2
        assert (self.THUMBS_DIR / thumb_3_id).exists()
        assert (self.THUMBS_DIR / (thumb_3_id + ".type")).exists()
Exemple #11
0
    def test_when_offer_is_not_digital(self, app):
        # Given
        offer = offers_factories.ThingOfferFactory(url=None)
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offer.venue.managingOfferer,
        )

        # When
        stock_data = {
            "offerId":
            humanize(offer.id),
            "stocks": [{
                "price":
                20,
                "activationCodes": ["AZ3"],
                "bookingLimitDatetime":
                "2021-06-15T02:59:59Z",
                "activationCodesExpirationDatetime":
                "2021-07-15T02:59:59Z",
            }],
        }

        response = (TestClient(
            app.test_client()).with_session_auth("*****@*****.**").post(
                "/stocks/bulk/", json=stock_data))

        # Then
        assert response.status_code == 400
        assert response.json["global"] == [
            "Impossible de créer des codes d'activation sur une offre non-numérique"
        ]
Exemple #12
0
    def test_invalid_booking_limit_datetime(self, app):
        # Given
        offer = offers_factories.ThingOfferFactory(url="https://chartreu.se")
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offer.venue.managingOfferer,
        )
        existing_stock = offers_factories.StockFactory(offer=offer)
        offers_factories.ActivationCodeFactory(expirationDate=datetime(
            2020, 5, 2, 23, 59, 59),
                                               stock=existing_stock)
        offers_factories.ActivationCodeFactory(expirationDate=datetime(
            2020, 5, 2, 23, 59, 59),
                                               stock=existing_stock)

        # When
        stock_data = {
            "offerId":
            humanize(offer.id),
            "stocks": [{
                "id": humanize(existing_stock.id),
                "bookingLimitDatetime": "2020-05-2T23:59:59Z",
                "price": 20.0,
            }],
        }

        response = (TestClient(
            app.test_client()).with_session_auth("*****@*****.**").post(
                "/stocks/bulk/", json=stock_data))

        # Then
        assert response.status_code == 400
        assert response.json["activationCodesExpirationDatetime"] == [(
            "La date limite de validité des codes d'activation doit être ultérieure"
            " d'au moins 7 jours à la date limite de réservation")]
Exemple #13
0
    def test_invalid_activation_codes_expiration_datetime(self, app):
        # Given
        offer = offers_factories.ThingOfferFactory(url="https://chartreu.se")
        offers_factories.UserOffererFactory(
            user__email="*****@*****.**",
            offerer=offer.venue.managingOfferer,
        )

        # When
        stock_data = {
            "offerId":
            humanize(offer.id),
            "stocks": [{
                "price":
                20,
                "activationCodes": ["AZ3"],
                "bookingLimitDatetime":
                "2021-06-15T02:59:59Z",
                "activationCodesExpirationDatetime":
                "2021-06-16T02:59:59Z",
            }],
        }

        response = (TestClient(
            app.test_client()).with_session_auth("*****@*****.**").post(
                "/stocks/bulk/", json=stock_data))

        # Then
        assert response.status_code == 400
        assert response.json["activationCodesExpirationDatetime"] == [(
            "La date limite de validité des codes d'activation doit être ultérieure"
            " d'au moins 7 jours à la date limite de réservation")]
Exemple #14
0
    def when_setting_beginning_datetime_on_offer_with_thing(
            self, app, db_session):
        # Given
        user = users_factories.UserFactory(isAdmin=True)
        offer = offers_factories.ThingOfferFactory()

        beginningDatetime = datetime(2019, 2, 14)

        data = {
            "price":
            0,
            "offerId":
            humanize(offer.id),
            "beginningDatetime":
            serialize(beginningDatetime),
            "bookingLimitDatetime":
            serialize(beginningDatetime - timedelta(days=2)),
        }

        # When
        response = TestClient(app.test_client()).with_auth(user.email).post(
            "/stocks", json=data)

        # Then
        assert response.status_code == 400
        assert response.json == {
            "global": [
                "Impossible de mettre une date de début si l'offre ne porte pas sur un événement"
            ]
        }
    def test_thing_prices(self):
        offer = offers_factories.ThingOfferFactory()
        validation.check_stock_price(0, offer)
        validation.check_stock_price(1.5, offer)

        with pytest.raises(ApiErrors) as error:
            validation.check_stock_price(-1.5, offer)
        assert error.value.errors["price"] == ["Le prix doit être positif"]
Exemple #16
0
    def test_thing_offer_ok_without_booking_limit_datetime(self):
        offer = factories.ThingOfferFactory()

        validation.check_required_dates_for_stock(
            offer,
            beginning=None,
            booking_limit_datetime=None,
        )
Exemple #17
0
    def test_fail_if_offer_is_not_editable(self):
        provider = offerers_factories.ProviderFactory()
        offer = factories.ThingOfferFactory(lastProvider=provider)

        with pytest.raises(api_errors.ApiErrors) as error:
            api.create_stock(offer=offer, price=10, beginning=None, booking_limit_datetime=None)

        assert error.value.errors == {"global": ["Les offres importées ne sont pas modifiables"]}
Exemple #18
0
    def test_check_image_quality(self):
        user = users_factories.UserFactory()
        offer = factories.ThingOfferFactory()
        image_as_bytes = (IMAGES_DIR / "mouette_small.jpg").read_bytes()

        with pytest.raises(models.ApiErrors) as error:
            api.create_mediation(user, offer, "credits", image_as_bytes)

        assert error.value.errors["thumb"] == ["L'image doit faire 400 * 400 px minimum"]
        assert models.Mediation.query.count() == 0
    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_creates_pending_and_not_processable_payments(self):
        # Given
        cutoff = datetime.datetime.now()
        before_cutoff = cutoff - datetime.timedelta(days=1)

        beneficiary = users_factories.BeneficiaryGrant18Factory(
            email="*****@*****.**")
        offerer1 = offers_factories.OffererFactory(siren="123456789")
        offerer2 = offers_factories.OffererFactory(siren="987654321")
        offers_factories.BankInformationFactory(
            bic="BDFEFR2LCCB",
            iban="FR7630006000011234567890189",
            offerer=offerer1)
        venue1 = offers_factories.VenueFactory(managingOfferer=offerer1,
                                               siret="12345678912345")
        venue2 = offers_factories.VenueFactory(managingOfferer=offerer2,
                                               siret="98765432154321")
        offer1 = offers_factories.ThingOfferFactory(venue=venue1)
        offer2 = offers_factories.ThingOfferFactory(venue=venue2)

        paying_stock1 = offers_factories.ThingStockFactory(offer=offer1)
        paying_stock2 = offers_factories.ThingStockFactory(offer=offer2)
        free_stock1 = offers_factories.ThingStockFactory(offer=offer1, price=0)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock1,
                                              dateUsed=before_cutoff)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock1,
                                              dateUsed=before_cutoff)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock2,
                                              dateUsed=before_cutoff)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=free_stock1,
                                              dateUsed=before_cutoff)

        # When
        generate_new_payments(cutoff, batch_date=datetime.datetime.now())

        # Then
        assert get_pending_payments().count() == 2
        assert get_not_processable_payments().count() == 1
    def test_returns_a_list_of_beneficiary_favorites(self, app):
        # given
        beneficiary = users_factories.UserFactory()
        venue = offers_factories.VenueFactory()
        offer_1 = offers_factories.ThingOfferFactory(venue=venue)
        mediation_1 = offers_factories.MediationFactory(offer=offer_1)
        users_factories.FavoriteFactory(mediation=mediation_1,
                                        offer=offer_1,
                                        user=beneficiary)
        offer_2 = offers_factories.ThingOfferFactory(venue=venue)
        users_factories.FavoriteFactory(offer=offer_2, user=beneficiary)

        # when
        favorites = repository.find_favorites_domain_by_beneficiary(
            beneficiary.id)

        # then
        assert len(favorites) == 2
        assert isinstance(favorites[0], FavoriteDomain)
        assert isinstance(favorites[1], FavoriteDomain)
Exemple #22
0
    def test_crop_params(self, mocked_store_public_object):
        user = users_factories.UserFactory()
        offer = factories.ThingOfferFactory()
        image_as_bytes = (IMAGES_DIR / "mouette_full_size.jpg").read_bytes()
        crop_params = (0.8, 0.8, 1)

        mediation = api.create_mediation(user, offer, "credits", image_as_bytes, crop_params)
        assert mediation.thumbCount == 1
        resized_as_bytes = mocked_store_public_object.call_args[1]["blob"]
        resized = PIL.Image.open(io.BytesIO(resized_as_bytes))
        assert resized.size == (357, 357)
Exemple #23
0
    def test_create_thing_offer(self, mocked_add_offer_id):
        offer = factories.ThingOfferFactory()

        stock = api.create_stock(offer=offer, price=10)

        assert stock.offer == offer
        assert stock.price == 10
        assert stock.quantity is None
        assert stock.beginningDatetime is None
        assert stock.bookingLimitDatetime is None
        mocked_add_offer_id.assert_called_once_with(client=app.redis_client, offer_id=offer.id)
Exemple #24
0
def create_digital_booking(quantity=1, price=10, user=None, product_type=None):
    user = user or users_factories.UserFactory()
    product_kwargs = {}
    if product_type:
        product_kwargs = {"type": product_type}
    product = offers_factories.DigitalProductFactory(**product_kwargs)
    stock = offers_factories.StockFactory(
        price=price,
        offer=offers_factories.ThingOfferFactory(product=product),
    )
    return bookings_factories.BookingFactory(user=user, stock=stock, quantity=quantity)
def get_pro_user():
    user_offerer = offers_factories.UserOffererFactory(
        validationToken=None,
        offerer__validationToken=None,
        user__validationToken=None,
        user__phoneNumber="01 00 00 00 00",
    )
    venue = offers_factories.VenueFactory(managingOfferer=user_offerer.offerer)
    offers_factories.ThingOfferFactory(venue=venue, isActive=True)

    return {"user": get_pro_helper(user_offerer.user)}
Exemple #26
0
    def test_create_mediation_basics(self, mocked_add_offer_id):
        user = users_factories.UserFactory()
        offer = factories.ThingOfferFactory()
        image_as_bytes = (IMAGES_DIR / "mouette_full_size.jpg").read_bytes()

        mediation = api.create_mediation(user, offer, "credits", image_as_bytes)

        assert mediation.author == user
        assert mediation.offer == offer
        assert mediation.credit == "credits"
        assert mediation.thumbCount == 1
        mocked_add_offer_id.assert_called_once_with(client=app.redis_client, offer_id=offer.id)
    def test_do_not_sync_algolia_if_feature_is_disabled(
            self, mocked_add_offer_id, mock_update_confirmation_dates):
        # Given
        offer = factories.ThingOfferFactory()
        created_stock_data = StockCreationBodyModel(price=10)

        # When
        api.upsert_stocks(offer_id=offer.id,
                          stock_data_list=[created_stock_data])

        # Then
        mocked_add_offer_id.assert_not_called()
Exemple #28
0
    def test_thing_offer_must_not_have_beginning(self):
        offer = factories.ThingOfferFactory()

        with pytest.raises(ApiErrors) as error:
            validation.check_required_dates_for_stock(
                offer,
                beginning=datetime.datetime.now(),
                booking_limit_datetime=None,
            )

        assert error.value.errors["global"] == [
            "Impossible de mettre une date de début si l'offre ne porte pas sur un événement"
        ]
Exemple #29
0
    def test_access_even_if_offerer_has_no_siren(self, app):
        # Given
        beneficiary = users_factories.UserFactory()
        offer = offers_factories.ThingOfferFactory(
            venue__managingOfferer__siren=None, )

        # When
        client = TestClient(
            app.test_client()).with_auth(email=beneficiary.email)
        response = client.get(f"/offers/{humanize(offer.id)}")

        # Then
        assert response.status_code == 200
    def test_does_not_allow_edition_of_stock_of_another_offer_than_given(
            self, mock_update_confirmation_dates):
        # Given
        offer = factories.ThingOfferFactory()
        other_offer = factories.ThingOfferFactory()
        existing_stock_on_other_offer = factories.StockFactory(
            offer=other_offer, price=10)
        edited_stock_data = StockEditionBodyModel(
            id=existing_stock_on_other_offer.id, price=30)

        # 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.status_code == 403
        assert error.value.errors == {
            "global": [
                "Vous n'avez pas les droits d'accès suffisant pour accéder à cette information."
            ]
        }