Exemplo n.º 1
0
    def test_get_enabled_providers_for_pro(self, app):
        # Given
        Provider.query.delete()  # remove automatically added providers
        provider1 = offerers_factories.AllocineProviderFactory(
            localClass="Truc", isActive=True, enabledForPro=True)
        offerers_factories.APIProviderFactory(name="NotEnabledAPIProvider",
                                              isActive=True,
                                              enabledForPro=False)
        offerers_factories.APIProviderFactory(name="InactiveAPIProvider",
                                              isActive=False,
                                              enabledForPro=True)
        offerers_factories.APIProviderFactory(name="InactiveAPIProvider2",
                                              isActive=False,
                                              enabledForPro=False)
        provider2 = offerers_factories.APIProviderFactory(name="Provider2",
                                                          isActive=True,
                                                          enabledForPro=True)

        # When
        enabled_providers = get_enabled_providers_for_pro()

        # Then
        assert len(enabled_providers) == 2
        assert provider1 in enabled_providers
        assert provider2 in enabled_providers
Exemplo n.º 2
0
    def test_synchronize_venue_providers(self,
                                         mocked_synchronize_venue_provider,
                                         app):
        # Given
        api_provider_1 = offerers_factories.APIProviderFactory()
        api_provider_2 = offerers_factories.APIProviderFactory()
        specific_provider = offerers_factories.AllocineProviderFactory()
        inactive_provider = offerers_factories.APIProviderFactory(
            isActive=False)

        correct_venue_providers = [
            VenueProviderFactory(isActive=True, provider=api_provider_1),
            VenueProviderFactory(isActive=True, provider=api_provider_1),
            VenueProviderFactory(isActive=True, provider=api_provider_2),
        ]

        VenueProviderFactory(isActive=True, provider=specific_provider)
        VenueProviderFactory(isActive=False, provider=api_provider_1)
        VenueProviderFactory(isActive=True, provider=inactive_provider)

        # When
        synchronize_stocks()

        # Then
        assert mocked_synchronize_venue_provider.call_count == len(
            correct_venue_providers)
        mocked_synchronize_venue_provider.assert_has_calls(
            call(v) for v in correct_venue_providers)
    def when_venue_provider_is_successfully_created(
            self, mock_siret_can_be_synchronized,
            mock_synchronize_venue_provider, app):
        # Given
        user = user_factories.AdminFactory()
        venue = offer_factories.VenueFactory(siret="12345678912345")

        provider = offerers_factories.APIProviderFactory()

        venue_provider_data = {
            "providerId": humanize(provider.id),
            "venueId": humanize(venue.id),
        }
        mock_siret_can_be_synchronized.return_value = True

        auth_request = TestClient(
            app.test_client()).with_session_auth(email=user.email)
        # When
        response = auth_request.post("/venueProviders",
                                     json=venue_provider_data)

        # Then
        assert response.status_code == 201
        venue_provider = VenueProvider.query.one()
        assert venue_provider.venueId == venue.id
        assert venue_provider.providerId == provider.id
        assert venue_provider.venueIdAtOfferProvider == "12345678912345"
        assert "id" in response.json

        venue_provider_id = response.json["id"]
        mock_synchronize_venue_provider.assert_called_once_with(
            dehumanize(venue_provider_id))
    def when_provider_api_not_available(self, mock_siret_can_be_synchronized,
                                        app):
        # Given
        user = user_factories.AdminFactory()
        venue = offer_factories.VenueFactory(siret="12345678912345")

        provider = offerers_factories.APIProviderFactory()

        venue_provider_data = {
            "providerId": humanize(provider.id),
            "venueId": humanize(venue.id),
        }

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

        errors = ApiErrors()
        errors.status_code = 422
        errors.add_error(
            "provider",
            "L’importation d’offres avec LesLibraires n’est pas disponible "
            "pour le SIRET 12345678912345",
        )
        mock_siret_can_be_synchronized.side_effect = [errors]

        # When
        response = auth_request.post("/venueProviders",
                                     json=venue_provider_data)

        # Then
        assert response.status_code == 422
        assert response.json["provider"] == [
            "L’importation d’offres avec LesLibraires n’est pas disponible pour le SIRET 12345678912345"
        ]
        assert VenueProvider.query.count() == 0
    def test_when_add_same_provider(self, mock_siret_can_be_synchronized,
                                    mock_synchronize_venue_provider, app):
        # Given
        user = user_factories.AdminFactory()
        venue = offer_factories.VenueFactory(siret="12345678912345")
        provider = offerers_factories.APIProviderFactory()
        venue_provider = create_venue_provider(
            venue, provider, venue_id_at_offer_provider="12345678912345")
        repository.save(venue_provider)

        auth_request = TestClient(
            app.test_client()).with_session_auth(email=user.email)
        venue_provider_data = {
            "providerId": humanize(provider.id),
            "venueId": humanize(venue.id),
        }
        mock_siret_can_be_synchronized.return_value = True

        # When
        response = auth_request.post("/venueProviders",
                                     json=venue_provider_data)

        # Then
        assert response.status_code == 400
        assert response.json == {
            "global": ["Votre lieu est déjà lié à cette source"]
        }
        assert venue.venueProviders[0].provider.id == provider.id
Exemplo n.º 6
0
def test_change_venue_provider():
    api_url = "https://example.com/provider/api"
    provider = offerers_factories.APIProviderFactory()
    venue_provider = offerers_factories.VenueProviderFactory(provider=provider)
    venue = venue_provider.venue
    stock = StockFactory(quantity=10, offer__venue=venue, offer__idAtProviders="1")
    BookingFactory(stock=stock)
    new_provider = offerers_factories.APIProviderFactory(apiUrl=api_url)

    api.change_venue_provider(venue_provider, new_provider.id)

    # Check venue_provider has change provider and sync date reset
    assert len(venue.venueProviders) == 1
    assert venue.venueProviders[0].providerId == new_provider.id
    assert venue.venueProviders[0].lastSyncDate == None
    # Check that the quantity of existing stocks has been reset.
    assert stock.quantity == 1
    assert stock.offer.lastProviderId == new_provider.id
    def test_non_allocine_provider_offer(self):
        offerer = offerers_factories.APIProviderFactory()
        provider_offer = offers_factories.OfferFactory(lastProvider=offerer,
                                                       idAtProviders="1")

        with pytest.raises(ApiErrors) as error:
            validation.check_offer_existing_stocks_are_editable(provider_offer)

        assert error.value.errors["global"] == [
            "Les offres importées ne sont pas modifiables"
        ]
    def test_offer_from_non_allocine_provider(self):
        provider = offerers_factories.APIProviderFactory()
        offer = offers_factories.OfferFactory(lastProvider=provider,
                                              idAtProviders="1")
        stock = offers_factories.StockFactory(offer=offer)

        with pytest.raises(ApiErrors) as error:
            validation.check_stock_is_updatable(stock)

        assert error.value.errors["global"] == [
            "Les offres importées ne sont pas modifiables"
        ]
Exemplo n.º 9
0
def test_use_siret_as_default(can_be_synchronized, app):
    # Given
    venue = VenueFactory(siret="12345678912345")
    provider = offerers_factories.APIProviderFactory()

    # When
    connect_venue_to_provider(venue, provider, None)

    # Then
    venue_provider = VenueProvider.query.one()
    assert venue_provider.venueIdAtOfferProvider == "12345678912345"
    can_be_synchronized.assert_called_once_with("12345678912345")
Exemplo n.º 10
0
    def test_should_get_actives_and_enabled_providers_for_pro(self, app):
        # Given
        Provider.query.delete()  # remove automatically added providers
        offerers_factories.AllocineProviderFactory(name="Provider1",
                                                   isActive=True,
                                                   enabledForPro=True)
        offerers_factories.APIProviderFactory(name="NotEnabledAPIProvider",
                                              isActive=True,
                                              enabledForPro=False)
        offerers_factories.APIProviderFactory(name="InactiveAPIProvider",
                                              isActive=False,
                                              enabledForPro=True)
        provider = offerers_factories.APIProviderFactory(name="Provider2",
                                                         isActive=True,
                                                         enabledForPro=True)

        # When
        providers = get_providers_enabled_for_pro_excluding_specific_provider(
            "AllocineStocks")

        # Then
        assert providers == [provider]
Exemplo n.º 11
0
def test_when_venue_id_at_offer_provider_is_given(can_be_synchronized, app):
    # Given
    venue_id_at_offer_provider = "id_for_remote_system"
    venue = VenueFactory(siret="12345678912345")
    provider = offerers_factories.APIProviderFactory()

    # When
    connect_venue_to_provider(venue, provider, venue_id_at_offer_provider)

    # Then
    venue_provider = VenueProvider.query.one()
    assert venue_provider.venueIdAtOfferProvider == venue_id_at_offer_provider
    can_be_synchronized.assert_called_once_with("id_for_remote_system")
    def when_no_regression_on_format(self, mock_siret_can_be_synchronized,
                                     mock_synchronize_venue_provider, app):
        # Given
        user = user_factories.AdminFactory()
        venue = offer_factories.VenueFactory(siret="12345678912345")

        provider = offerers_factories.APIProviderFactory()

        venue_provider_data = {
            "providerId": humanize(provider.id),
            "venueId": humanize(venue.id),
        }

        auth_request = TestClient(
            app.test_client()).with_session_auth(email=user.email)
        mock_siret_can_be_synchronized.return_value = True

        # When
        response = auth_request.post("/venueProviders",
                                     json=venue_provider_data)

        # Then
        assert response.status_code == 201
        assert set(response.json.keys()) == {
            "dateModifiedAtLastProvider",
            "fieldsUpdated",
            "id",
            "idAtProviders",
            "isActive",
            "isDuo",
            "isFromAllocineProvider",
            "lastProviderId",
            "lastSyncDate",
            "nOffers",
            "price",
            "provider",
            "providerId",
            "quantity",
            "venueId",
            "venueIdAtOfferProvider",
        }
        assert set(response.json["provider"].keys()) == {
            "enabledForPro",
            "id",
            "isActive",
            "localClass",
            "name",
        }
Exemplo n.º 13
0
    def should_not_connect_venue_when_venue_has_no_siret(self, app):
        # Given
        offerer = create_offerer()
        venue = create_venue(offerer, siret=None, is_virtual=True)
        provider = offerers_factories.APIProviderFactory(name="FNAC")

        repository.save(venue)

        self.find_by_id.return_value = venue

        # when
        with pytest.raises(NoSiretSpecified):
            connect_venue_to_provider(venue, provider)

        # then
        assert not VenueProvider.query.first()
Exemplo n.º 14
0
    def should_not_connect_venue_when_synchronization_is_not_allowed(
            self, app):
        # Given
        offerer = create_offerer()
        venue = create_venue(offerer, siret="12345678912345")
        provider = offerers_factories.APIProviderFactory(name="FNAC")

        repository.save(venue)

        self.find_by_id.return_value = venue
        stock_repository = MagicMock()
        stock_repository.can_be_synchronized.return_value = False

        # when
        with pytest.raises(VenueSiretNotRegistered):
            connect_venue_to_provider(venue, provider)

        # then
        assert not VenueProvider.query.first()
Exemplo n.º 15
0
    def should_connect_venue_when_synchronization_is_allowed(self, app):
        # Given
        offerer = create_offerer()

        venue = create_venue(offerer)
        provider = offerers_factories.APIProviderFactory()

        repository.save(venue)

        self.find_by_id.return_value = venue
        stock_repository = MagicMock()
        stock_repository.can_be_synchronized.return_value = True

        # When
        connect_venue_to_provider(venue, provider)

        # Then
        fnac_venue_provider = VenueProvider.query.one()
        assert fnac_venue_provider.venue == venue
    def when_venue_does_not_exist(self, app):
        # Given
        user = user_factories.AdminFactory()

        provider = offerers_factories.APIProviderFactory()

        venue_provider_data = {
            "providerId": humanize(provider.id),
            "venueId": "AZERT",
        }

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

        # When
        response = auth_request.post("/venueProviders",
                                     json=venue_provider_data)

        # Then
        assert response.status_code == 404
Exemplo n.º 17
0
def test_fully_sync_venue():
    api_url = "https://example.com/provider/api"
    provider = offerers_factories.APIProviderFactory(apiUrl=api_url)
    venue_provider = offerers_factories.VenueProviderFactory(provider=provider)
    venue = venue_provider.venue
    stock = offers_factories.StockFactory(quantity=10,
                                          offer__venue=venue,
                                          offer__idAtProviders="1")
    bookings_factories.BookingFactory(stock=stock)
    product2 = offers_factories.ProductFactory(
        idAtProviders="1234",
        extraData={"prix_livre": 10},
        subcategoryId=subcategories.LIVRE_PAPIER.id,
    )

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

    # Check that the quantity of existing stocks has been reset.
    assert stock.quantity == 1
    # Check that offers and stocks have been created or updated.
    offer2 = offers_models.Offer.query.filter_by(product=product2).one()
    assert offer2.stocks[0].quantity == 5
    def should_inject_the_appropriate_repository_to_the_usecase(
            self, mocked_connect_venue_to_provider,
            mock_siret_can_be_synchronized, app):
        # Given
        user = user_factories.AdminFactory()
        venue = offer_factories.VenueFactory(siret="12345678912345")

        provider = offerers_factories.APIProviderFactory()

        venue_provider_data = {
            "providerId": humanize(provider.id),
            "venueId": humanize(venue.id),
        }

        auth_request = TestClient(
            app.test_client()).with_session_auth(email=user.email)
        mock_siret_can_be_synchronized.return_value = True

        # When
        auth_request.post("/venueProviders", json=venue_provider_data)

        # Then
        mocked_connect_venue_to_provider.assert_called_once_with(
            venue, provider, None)
Exemplo n.º 19
0
    def test_execution(self, mock_async_index_offer_ids):
        # Given
        spec = [
            {"ref": "3010000101789", "available": 6},
            {"ref": "3010000101797", "available": 4},
            {"ref": "3010000103769", "available": 18},
            {"ref": "3010000107163", "available": 12},
            {"ref": "3010000108123", "available": 17},
            {"ref": "3010000108124", "available": 17},
            {"ref": "3010000108125", "available": 17},
            {"ref": "3010000101790", "available": 1},
            {"ref": "3010000102735", "available": 1},
        ]
        offerers_factories.APIProviderFactory(apiUrl="https://provider_url", authToken="fake_token")
        venue = VenueFactory()
        siret = venue.siret
        provider = offerers_factories.ProviderFactory()
        stock_details = synchronize_provider_api._build_stock_details_from_raw_stocks(spec, siret, provider, venue.id)

        stock = create_stock(
            spec[0]["ref"],
            siret,
            quantity=20,
        )
        offer = create_offer(spec[1]["ref"], siret)
        product = create_product(spec[2]["ref"])
        create_product(spec[4]["ref"])
        create_product(spec[6]["ref"], isGcuCompatible=False)
        create_product(spec[8]["ref"], isSynchronizationCompatible=False)

        stock_with_booking = create_stock(spec[5]["ref"], siret, quantity=20)
        BookingFactory(stock=stock_with_booking)
        BookingFactory(stock=stock_with_booking, quantity=2)

        create_product(spec[7]["ref"])
        OfferFactory(venue=venue, idAtProviders="out-of-date-id-at-p", idAtProvider=spec[7]["ref"])

        # When
        api.synchronize_stocks(stock_details, venue, provider_id=provider.id)

        # Then
        # Test updates stock if already exists
        assert stock.quantity == 6
        assert stock.rawProviderQuantity == 6

        # Test creates stock if does not exist
        assert len(offer.stocks) == 1
        created_stock = offer.stocks[0]
        assert created_stock.quantity == 4
        assert created_stock.rawProviderQuantity == 4

        # Test creates offer if does not exist
        created_offer = Offer.query.filter_by(idAtProviders=f"{spec[2]['ref']}@{siret}").one()
        assert created_offer.stocks[0].quantity == 18

        # Test doesn't create offer if product does not exist or not gcu compatible or not synchronization compatible
        assert Offer.query.filter_by(idAtProviders=f"{spec[3]['ref']}@{siret}").count() == 0
        assert Offer.query.filter_by(idAtProviders=f"{spec[6]['ref']}@{siret}").count() == 0
        assert Offer.query.filter_by(idAtProviders=f"{spec[8]['ref']}@{siret}").count() == 0

        # Test second page is actually processed
        second_created_offer = Offer.query.filter_by(idAtProviders=f"{spec[4]['ref']}@{siret}").one()
        assert second_created_offer.stocks[0].quantity == 17

        # Test existing bookings are added to quantity
        assert stock_with_booking.quantity == 17 + 1 + 2
        assert stock_with_booking.rawProviderQuantity == 17

        # Test fill stock attributes
        assert created_stock.price == Decimal("12.00")
        assert created_stock.idAtProviders == f"{spec[1]['ref']}@{siret}"

        # Test fill offers attributes
        assert created_offer.bookingEmail == venue.bookingEmail
        assert created_offer.description == product.description
        assert created_offer.extraData == product.extraData
        assert created_offer.name == product.name
        assert created_offer.productId == product.id
        assert created_offer.venueId == venue.id
        assert created_offer.idAtProviders == f"{spec[2]['ref']}@{siret}"
        assert created_offer.lastProviderId == provider.id

        # Test offer reindexation
        mock_async_index_offer_ids.assert_called_with(
            {stock.offer.id, offer.id, stock_with_booking.offer.id, created_offer.id, second_created_offer.id}
        )
Exemplo n.º 20
0
    def test_build_new_offers_from_stock_details(self, db_session):
        # Given
        spec = [
            StockDetail(  # known offer, must be ignored
                available_quantity=1,
                offers_provider_reference="offer_ref1",
                venue_reference="venue_ref1",
                products_provider_reference="isbn_product_ref",
                stocks_provider_reference="stock_ref",
                price=28.989,
            ),
            StockDetail(  # new one, will be created
                available_quantity=17,
                offers_provider_reference="offer_ref_2",
                price=28.989,
                products_provider_reference="isbn_product_ref",
                stocks_provider_reference="stock_ref",
                venue_reference="venue_ref2",
            ),
            # no quantity, must be ignored
            StockDetail(
                available_quantity=0,
                offers_provider_reference="offer_ref_3",
                price=28.989,
                products_provider_reference="isbn_product_ref",
                stocks_provider_reference="stock_ref",
                venue_reference="venue_ref3",
            ),
        ]

        existing_offers_by_provider_reference = {"offer_ref1": 1}
        existing_offers_by_venue_reference = {"venue_ref1": 1}
        provider = offerers_factories.APIProviderFactory(apiUrl="https://provider_url", authToken="fake_token")
        venue = VenueFactory(bookingEmail="booking_email", withdrawalDetails="My withdrawal details")
        product = Product(
            id=456,
            name="product_name",
            description="product_desc",
            extraData="extra",
            subcategoryId=subcategories.LIVRE_PAPIER.id,
        )
        products_by_provider_reference = {"isbn_product_ref": product}

        # When
        new_offers = api._build_new_offers_from_stock_details(
            spec,
            existing_offers_by_provider_reference,
            products_by_provider_reference,
            existing_offers_by_venue_reference,
            venue,
            provider_id=provider.id,
        )

        # Then
        assert new_offers == [
            Offer(
                bookingEmail="booking_email",
                description="product_desc",
                extraData="extra",
                idAtProviders="offer_ref_2",
                lastProviderId=provider.id,
                name="product_name",
                productId=456,
                venueId=venue.id,
                subcategoryId=subcategories.LIVRE_PAPIER.id,
                withdrawalDetails=venue.withdrawalDetails,
            ),
        ]
        new_offer = new_offers[0]
        assert new_offer.bookingEmail == "booking_email"
        assert new_offer.description == "product_desc"
        assert new_offer.extraData == "extra"
        assert new_offer.idAtProviders == "offer_ref_2"
        assert new_offer.idAtProvider == "isbn_product_ref"
        assert new_offer.lastProviderId == provider.id
        assert new_offer.name == "product_name"
        assert new_offer.productId == 456
        assert new_offer.venueId == venue.id
        assert new_offer.subcategoryId == subcategories.LIVRE_PAPIER.id
        assert new_offer.withdrawalDetails == venue.withdrawalDetails