def test_should_mark_offers_and_products_as_incompatible_via_isbn(
            self, mocked_unindex_offer_ids):
        # Given
        product = ProductFactory(id=1, extraData={"isbn": "ABCDEFG"})
        product_1 = ProductFactory(id=2, extraData={"isbn": "HIJKLMN"})
        product_2 = ProductFactory(id=3, extraData={"isbn": "VWXYZ"})
        product_3 = ProductFactory(id=4, extraData={"isbn": "HFGDS"})
        offer = OfferFactory(id=1, product=product)
        offer_1 = OfferFactory(id=2, product=product_1)
        offer_2 = OfferFactory(id=3, product=product_2)
        offer_3 = OfferFactory(id=4, product=product_3)

        isbns_list = ["ABCDEFG", "HIJKLMN", "OPQRSTU", "HFGDS"]

        queries = 1  # update product
        queries += 1  # select offer
        queries += 2  # update offer; commit
        queries *= 2  # two batches

        # When
        with assert_num_queries(queries):
            bulk_update_is_gcu_compatible_via_isbns(isbns_list,
                                                    2,
                                                    is_compatible=False)

        # Then
        assert not product.isGcuCompatible
        assert not product_1.isGcuCompatible
        assert product_2.isGcuCompatible
        assert not product_3.isGcuCompatible
        assert not offer.isActive
        assert not offer_1.isActive
        assert offer_2.isActive
        assert not offer_3.isActive
        mocked_unindex_offer_ids.assert_has_calls([call([1, 2]), call([4])])
コード例 #2
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
コード例 #3
0
def test_update_last_provider_id():
    provider1 = offerers_factories.ProviderFactory()
    provider2 = offerers_factories.ProviderFactory()
    venue = VenueFactory()
    offer1_synced = OfferFactory(venue=venue, idAtProviders=1, lastProvider=provider1)
    offer2_manual = OfferFactory(venue=venue, idAtProviders=None)
    offer3_other_venue = OfferFactory(idAtProviders=2, lastProvider=provider1)

    api.update_last_provider_id(venue, provider2.id)

    assert offer1_synced.lastProvider == provider2
    assert offer2_manual.idAtProviders is None
    assert offer3_other_venue.lastProvider == provider1
コード例 #4
0
    def test_send_offer_link_notification(self, app):
        """
        Test that a push notification to the user is send with a link to the
        offer.
        """
        # offer.id must be used before the assert_num_queries context manager
        # because it triggers a SQL query.
        offer = OfferFactory()
        offer_id = offer.id

        user, test_client = create_user_and_test_client(app)

        # expected queries:
        #   * get user
        #   * get offer
        #   * get FeatureToggle WEBAPP_V2_ENABLED (to build URL)
        with assert_num_queries(3):
            response = test_client.post(
                f"/native/v1/send_offer_link_by_push/{offer_id}")
            assert response.status_code == 204

        assert len(notifications_testing.requests) == 1

        notification = notifications_testing.requests[0]
        assert notification["user_ids"] == [user.id]

        assert offer.name in notification["message"]["title"]
        assert "deeplink" in notification
コード例 #5
0
    def test_get_user_reported_offers(self, client):
        user = UserFactory()
        offers = OfferFactory.create_batch(3)
        reports = [
            OfferReportFactory(user=user, offer=offers[0]),
            OfferReportFactory(user=user, offer=offers[1]),
        ]

        # offers reported by this user should not be returned
        another_user = UserFactory()
        OfferReportFactory(user=another_user, offer=offers[2])

        client.with_token(user.email)
        response = client.get("/native/v1/offers/reports")

        assert response.status_code == 200

        response_reports = sorted(response.json["reportedOffers"],
                                  key=lambda x: x["offerId"])
        assert response_reports == [
            {
                "offerId": reports[0].offerId,
                "reportedAt": reports[0].reportedAt.isoformat(),
                "reason": reports[0].reason.value,
            },
            {
                "offerId": reports[1].offerId,
                "reportedAt": reports[1].reportedAt.isoformat(),
                "reason": reports[1].reason.value,
            },
        ]
コード例 #6
0
        def should_return_offers_with_id_at_providers_including_different_siret(self, app):
            # Given
            current_siret = "32363560700019"
            expected_venue = VenueFactory(siret=current_siret)
            other_venue = VenueFactory(siret="7863560700657")
            offer1 = OfferFactory(venue=expected_venue, idAtProviders="9782742785988@85234081900014")
            offer2 = OfferFactory(venue=expected_venue, idAtProviders="9782742785988@32363560700019")
            other_offer = OfferFactory(venue=other_venue, idAtProviders="9782742785988@7863560700657")

            repository.save(offer1, offer2, other_offer)

            # When
            offers_result = _get_titelive_offers_with_old_id_at_providers(expected_venue, current_siret)

            # Then
            assert offers_result == [offer1]
コード例 #7
0
    def test_report_offer_with_custom_reason(self, app):
        user, test_client = create_user_and_test_client(app)
        offer = OfferFactory()

        # expected queries:
        #   * select offer
        #   * get user
        #   * insert report
        #   * release savepoint
        #
        #   * reload user
        #   * select offer
        #   * insert email into db
        #   * release savepoint
        with assert_num_queries(8):
            data = {"reason": "OTHER", "customReason": "saynul"}
            response = test_client.post(f"/native/v1/offer/{offer.id}/report",
                                        json=data)
            assert response.status_code == 204

        assert OfferReport.query.count() == 1
        report = OfferReport.query.first()

        assert report.user == user
        assert report.offer == offer

        assert len(mails_testing.outbox) == 1

        email = mails_testing.outbox[0]
        assert email.sent_data["To"] == "*****@*****.**"
        assert email.sent_data["Vars"]["user_id"] == user.id
        assert email.sent_data["Vars"]["offer_id"] == offer.id
        assert "saynul" in email.sent_data["Vars"]["reason"]
        assert "offer_url" in email.sent_data["Vars"]
コード例 #8
0
def test_get_user_attributes():
    user = BeneficiaryGrant18Factory(deposit__version=1)
    offer = OfferFactory(product__id=list(TRACKED_PRODUCT_IDS.keys())[0])
    b1 = IndividualBookingFactory(individualBooking__user=user,
                                  amount=10,
                                  stock__offer=offer)
    b2 = IndividualBookingFactory(individualBooking__user=user,
                                  amount=10,
                                  dateUsed=datetime(2021, 5, 6),
                                  stock__offer=offer)
    IndividualBookingFactory(
        individualBooking__user=user,
        amount=100,
        status=BookingStatus.CANCELLED)  # should be ignored

    last_date_created = max(booking.dateCreated for booking in [b1, b2])

    n_query_get_user = 1
    n_query_get_bookings = 1
    n_query_get_deposit = 1
    n_query_is_pro = 1
    n_query_get_last_favorite = 1

    with assert_num_queries(n_query_get_user + n_query_get_bookings +
                            n_query_get_deposit + n_query_is_pro +
                            n_query_get_last_favorite):
        attributes = get_user_attributes(user)

    assert attributes == UserAttributes(
        domains_credit=DomainsCredit(
            all=Credit(initial=Decimal("500"), remaining=Decimal("480.00")),
            digital=Credit(initial=Decimal("200"), remaining=Decimal("200")),
            physical=Credit(initial=200, remaining=Decimal("180.00")),
        ),
        booking_categories=["FILM"],
        date_created=user.dateCreated,
        date_of_birth=user.dateOfBirth,
        departement_code="75",
        deposit_expiration_date=user.deposit_expiration_date,
        eligibility=EligibilityType.AGE18,
        first_name="Jeanne",
        is_beneficiary=True,
        is_pro=False,
        last_booking_date=last_date_created,
        last_name="Doux",
        marketing_push_subscription=True,
        postal_code=None,
        products_use_date={"product_brut_x_use": datetime(2021, 5, 6, 0, 0)},
        booking_count=2,
        booking_subcategories=["SUPPORT_PHYSIQUE_FILM"],
        deposit_activation_date=user.deposit_activation_date,
        has_completed_id_check=None,
        user_id=user.id,
        is_eligible=True,
        is_email_validated=True,
        last_favorite_creation_date=None,
        last_visit_date=None,
        marketing_email_subscription=True,
    )
コード例 #9
0
    def __init__(self, nb_duplicates, nb_regulars):
        self.venue = VenueFactory()

        self.duplicates = [(
            OfferFactory(idAtProviders=
                         f"duplicate-id-{count}@siret-venue-{self.venue.id}",
                         venue=self.venue),
            OfferFactory(
                idAtProviders=
                f"duplicate-id-{count}@other-siret-venue-{self.venue.id}",
                venue=self.venue),
        ) for count in range(nb_duplicates)]

        self.others = [
            OfferFactory(
                idAtProviders=f"regular-id-{count}@siret-venue-{self.venue.id}",
                venue=self.venue) for count in range(nb_regulars)
        ]
コード例 #10
0
    def test_update_offer_and_stock_id_at_providers(self):
        # Given
        current_siret = "88888888888888"
        venue = VenueFactory(siret=current_siret)
        offer = OfferFactory(venue=venue,
                             idAtProviders="1111111111111@22222222222222")
        other_venue_offer = OfferFactory(
            venue=venue, idAtProviders="3333333333333@12222222222222")
        stock = StockFactory(offer=offer,
                             idAtProviders="1111111111111@22222222222222")

        # When
        update_offer_and_stock_id_at_providers(venue, "22222222222222")

        # Then
        assert offer.idAtProviders == "1111111111111@88888888888888"
        assert stock.idAtProviders == "1111111111111@88888888888888"
        assert other_venue_offer.idAtProviders == "3333333333333@12222222222222"
コード例 #11
0
    def test_get_no_reported_offers(self, client):
        user = UserFactory()
        OfferFactory()

        client.with_token(user.email)
        response = client.get("/native/v1/offers/reports")

        assert response.status_code == 200
        assert not response.json["reportedOffers"]
コード例 #12
0
    def test_should_mark_offers_and_products_as_incompatible_via_offer_ids(
            self):
        # Given
        offer = OfferFactory(id=1)
        offer_1 = OfferFactory(id=2)
        offer_2 = OfferFactory(id=5)
        repository.save(offer, offer_1, offer_2)

        offer_ids_list = ["1", "2", "3"]

        # When
        bulk_inactivate_offers(offer_ids_list, 2)

        # Then
        offers = Offer.query.order_by(Offer.id).all()
        assert not offers[0].isActive
        assert not offers[1].isActive
        assert offers[2].isActive
    def should_update_offer_withdrawal_details(self):
        # Given
        new_withdrawals_details = "Some withdrawal informations"
        active_offer_1 = OfferFactory(isActive=True)
        active_offer_2 = OfferFactory(isActive=True, venue=active_offer_1.venue)
        inactive_offer = OfferFactory(isActive=False, venue=active_offer_1.venue)
        different_offerer_offer = OfferFactory()

        # When
        batch_update_offer_withdrawal_details_for_offerer(
            active_offer_1.venue.managingOffererId, new_withdrawals_details, 1
        )

        # Then
        assert active_offer_1.withdrawalDetails == new_withdrawals_details
        assert active_offer_2.withdrawalDetails == new_withdrawals_details
        assert inactive_offer.withdrawalDetails is None
        assert different_offerer_offer.withdrawalDetails is None
コード例 #14
0
    def test_when_mailjet_status_code_200_sends_email_to_administration_email(self, app):
        author = users_factories.UserFactory(email="*****@*****.**")
        offer = OfferFactory(author=author)

        # When
        send_offer_rejection_notification_to_administration(offer)

        # Then
        assert len(mails_testing.outbox) == 1
        assert mails_testing.outbox[0].sent_data["To"] == "*****@*****.**"
コード例 #15
0
def test_reset_stock_quantity():
    offer = OfferFactory(idAtProviders="1")
    venue = offer.venue
    stock1_no_bookings = StockFactory(offer=offer, quantity=10)
    stock2_only_cancelled_bookings = StockFactory(offer=offer, quantity=10)
    CancelledBookingFactory(stock=stock2_only_cancelled_bookings)
    stock3_mix_of_bookings = StockFactory(offer=offer, quantity=10)
    BookingFactory(stock=stock3_mix_of_bookings)
    CancelledBookingFactory(stock=stock3_mix_of_bookings)
    manually_added_offer = OfferFactory(venue=venue)
    stock4_manually_added = StockFactory(offer=manually_added_offer, quantity=10)
    stock5_other_venue = StockFactory(quantity=10)

    api.reset_stock_quantity(venue)

    assert stock1_no_bookings.quantity == 0
    assert stock2_only_cancelled_bookings.quantity == 0
    assert stock3_mix_of_bookings.quantity == 1
    assert stock4_manually_added.quantity == 10
    assert stock5_other_venue.quantity == 10
コード例 #16
0
    def test_send_approval_notification(self, app):
        author = users_factories.UserFactory(email="*****@*****.**")
        offer = OfferFactory(name="Test Book", author=author)

        # When
        send_offer_validation_notification_to_administration(OfferValidationStatus.APPROVED, offer)

        # Then
        assert len(mails_testing.outbox) == 1
        assert mails_testing.outbox[0].sent_data["To"] == "*****@*****.**"
        assert mails_testing.outbox[0].sent_data["Subject"] == "[Création d’offre - 75] Test Book"
コード例 #17
0
    def test_report_inappropriate(self):
        # Given
        user = BeneficiaryGrant18Factory()
        offer = OfferFactory()
        reason = Reason.INAPPROPRIATE.value

        # When
        send_report_notification(user, offer, reason, "blabla")

        # Then
        assert mails_testing.outbox[0].sent_data[
            "To"] == settings.REPORT_OFFER_EMAIL_ADDRESS
コード例 #18
0
    def test_report_other(self):
        # Given
        user = BeneficiaryGrant18Factory()
        offer = OfferFactory()
        reason = Reason.OTHER.value

        # When
        send_report_notification(user, offer, reason, "blabla")

        # Then
        assert mails_testing.outbox[0].sent_data[
            "To"] == settings.SUPPORT_EMAIL_ADDRESS
コード例 #19
0
def test_get_bookings_categories_and_subcategories():
    user = BeneficiaryGrant18Factory()
    offer = OfferFactory(product__id=list(TRACKED_PRODUCT_IDS.keys())[0])

    assert _get_bookings_categories_and_subcategories(
        _get_user_bookings(user)) == ([], [])

    IndividualBookingFactory(individualBooking__user=user, stock__offer=offer)
    IndividualBookingFactory(individualBooking__user=user, stock__offer=offer)
    IndividualBookingFactory(individualBooking__user=user, isCancelled=True)

    assert _get_bookings_categories_and_subcategories(
        _get_user_bookings(user)) == (["FILM"], ["SUPPORT_PHYSIQUE_FILM"])
コード例 #20
0
    def test_report_offer_unknown_reason(self, app, client):
        offer = OfferFactory()
        offer_id = offer.id

        with assert_num_queries(0):
            data = {"reason": "UNKNOWN"}
            response = client.post(f"/native/v1/offer/{offer_id}/report",
                                   json=data)
            assert response.status_code == 400
            assert response.json["reason"] == ["unknown reason"]

        assert OfferReport.query.count() == 0  # no new report
        assert not mails_testing.outbox
コード例 #21
0
    def test_report_offer_custom_reason_too_long(self, app, client):
        offer = OfferFactory()
        offer_id = offer.id

        with assert_num_queries(0):
            data = {"reason": "OTHER", "customReason": "a" * 513}
            response = client.post(f"/native/v1/offer/{offer_id}/report",
                                   json=data)
            assert response.status_code == 400
            assert response.json["customReason"] == [
                "custom reason is too long"
            ]

        assert OfferReport.query.count() == 0  # no new report
        assert not mails_testing.outbox
コード例 #22
0
    def should_call_synchronize_on_expected_venue_provider(self, mock_do_sync_venue_provider, app):
        # Given
        venue = VenueFactory()
        offer = OfferFactory(venue=venue)
        stock = StockFactory(offer=offer)
        titelive = activate_provider(provider_classname="TiteLiveStocks")
        venue_provider = create_venue_provider(venue=venue, provider=titelive)

        repository.save(venue_provider, stock)

        # When
        fully_sync_library(venue_id=venue.id)

        # Then
        mock_do_sync_venue_provider.assert_called_once_with(venue_provider)
コード例 #23
0
    def should_update_id_at_providers_for_offers_and_stocks_with_current_siret(self, mock_repository, app):
        # Given
        current_siret = "32363560700019"
        venue = VenueFactory(siret=current_siret, id=12)
        offer = OfferFactory(venue=venue, idAtProviders="9782742785988@85234081900014")
        stock = StockFactory(offer=offer, idAtProviders="9782742785988@85234081900014")

        # When
        update_offer_and_stock_id_at_providers(venue_id=12)

        # Then
        assert offer.idAtProviders == "9782742785988@32363560700019"
        assert stock.idAtProviders == "9782742785988@32363560700019"
        assert mock_repository.save.call_count == 2
        assert mock_repository.save.call_args_list == [call(offer), call(stock)]
コード例 #24
0
    def test_get_thing_offer(self, app):
        offer_type = ThingType.MUSEES_PATRIMOINE_ABO
        offer = OfferFactory(type=str(offer_type))
        ThingStockFactory(offer=offer, price=12.34)

        response = TestClient(
            app.test_client()).get(f"/native/v1/offer/{offer.id}")

        assert response.status_code == 200
        assert not response.json["stocks"][0]["beginningDatetime"]
        assert response.json["stocks"][0]["price"] == 1234
        assert response.json["category"] == {
            "categoryType": "Thing",
            "label": "Musée, arts visuels et patrimoine",
            "name": "VISITE",
        }
        assert response.json["image"] is None
コード例 #25
0
    def test_report_offer_twice(self, app):
        user, test_client = create_user_and_test_client(app)
        offer = OfferFactory()

        OfferReportFactory(user=user, offer=offer)

        # expected queries:
        #   * get user
        #   * get offer
        #   * rollback
        with assert_num_queries(3):
            response = test_client.post(f"/native/v1/offer/{offer.id}/report",
                                        json={"reason": "PRICE_TOO_HIGH"})
            assert response.status_code == 400
            assert response.json["code"] == "OFFER_ALREADY_REPORTED"

        assert OfferReport.query.count() == 1  # no new report
        assert not mails_testing.outbox
コード例 #26
0
    def should_update_quantity_to_booking_amount_for_each_synchronized_stock_on_venue(
        self, mock_do_sync_venue_provider, app
    ):
        # Given
        titelive = activate_provider(provider_classname="TiteLiveStocks")
        venue = VenueFactory()
        offer = OfferFactory(venue=venue, idAtProviders="titelive")
        stock = StockFactory(offer=offer, quantity=2, lastProviderId=titelive.id, idAtProviders="titelive")
        booking = BookingFactory(stock=stock)
        venue_provider = create_venue_provider(venue=venue, provider=titelive)

        repository.save(venue_provider, booking)

        # When
        fully_sync_library(venue_id=venue.id)

        # Then
        assert stock.quantity == 1
コード例 #27
0
    def test_send_offer_webapp_link_by_email(self, app):
        offer_id = OfferFactory().id
        user, test_client = create_user_and_test_client(app)

        # expected queries:
        #   * get User
        #   * find Offer
        #   * find FeatureToggle WEBAPP_V2_ENABLED (to build URL)
        #   * save email to DB (testing backend)
        #   * release savepoint after saving email
        with assert_num_queries(5):
            response = test_client.post(
                f"/native/v1/send_offer_webapp_link_by_email/{offer_id}")
            assert response.status_code == 204

        assert len(mails_testing.outbox) == 1

        mail = mails_testing.outbox[0]
        assert mail.sent_data["To"] == user.email
コード例 #28
0
    def test_get_thing_offer(self, app):
        product = ProductFactory(thumbCount=1,
                                 subcategoryId=subcategories.ABO_MUSEE.id)
        offer = OfferFactory(product=product,
                             isEducational=True,
                             venue__isPermanent=True)
        ThingStockFactory(offer=offer, price=12.34)

        offer_id = offer.id
        with assert_num_queries(1):
            response = TestClient(
                app.test_client()).get(f"/native/v1/offer/{offer_id}")

        assert response.status_code == 200
        assert not response.json["stocks"][0]["beginningDatetime"]
        assert response.json["stocks"][0]["price"] == 1234
        assert response.json["subcategoryId"] == "ABO_MUSEE"
        assert response.json["isEducational"]
        assert not response.json["isExpired"]
        assert response.json["venue"]["isPermanent"]
コード例 #29
0
    def test_send_offer_refusing_email(self, ):
        # Given
        venue = VenueFactory(name="Sibérie orientale")
        offer = OfferFactory(name="Michel Strogoff", venue=venue)

        # When
        send_offer_validation_status_update_email(
            offer, OfferValidationStatus.REJECTED, ["*****@*****.**"])

        # Then
        assert len(mails_testing.outbox) == 1  # test number of emails sent
        assert mails_testing.outbox[0].sent_data["MJ-TemplateID"] == 2613942
        assert mails_testing.outbox[0].sent_data["Vars"][
            "offer_name"] == "Michel Strogoff"
        assert mails_testing.outbox[0].sent_data["Vars"][
            "venue_name"] == "Sibérie orientale"
        assert mails_testing.outbox[0].sent_data[
            "To"] == "*****@*****.**"
        assert humanize(
            offer.id
        ) in mails_testing.outbox[0].sent_data["Vars"]["pc_pro_offer_link"]
コード例 #30
0
    def test_report_offer_malformed(self, app, client):
        user = UserFactory()
        offer = OfferFactory()

        # user.email triggers an SQL request, same for offer.id
        # therefore, these attributes should be read outside of the
        # assert_num_queries() block
        email = user.email
        offer_id = offer.id

        # expected queries:
        #   * get user
        #   * rollback
        with assert_num_queries(2):
            dst = f"/native/v1/offer/{offer_id}/report"
            response = client.with_token(email).post(dst,
                                                     json={"reason": "OTHER"})
            assert response.status_code == 400
            assert response.json["code"] == "REPORT_MALFORMED"

        assert OfferReport.query.count() == 0  # no new report
        assert not mails_testing.outbox