def _setup_venues_for_users(self): offerer = offers_factories.OffererFactory() user_offerer = offers_factories.UserOffererFactory(offerer=offerer) venue = offers_factories.VenueFactory(name="venue", managingOfferer=offerer) offerer_not_validated = offers_factories.OffererFactory( validationToken="token") offers_factories.UserOffererFactory(user=user_offerer.user, offerer=offerer_not_validated) venue_not_validated = offers_factories.VenueFactory( name="venue_not_validated", managingOfferer=offerer_not_validated) other_offerer = offers_factories.OffererFactory() other_user_offerer = offers_factories.UserOffererFactory( offerer=other_offerer) other_venue = offers_factories.VenueFactory( name="other_venue", managingOfferer=other_offerer) other_offerer_not_validated = offers_factories.OffererFactory( validationToken="other_token") offers_factories.UserOffererFactory( user=other_user_offerer.user, offerer=other_offerer_not_validated) other_venue_not_validated = offers_factories.VenueFactory( name="other_venue_not_validated", managingOfferer=other_offerer_not_validated, ) return { "venue": venue, "venue_not_validated": venue_not_validated, "other_venue": other_venue, "other_venue_not_validated": other_venue_not_validated, }
def test_returns_404_if_api_key_cant_access_venue(mock_synchronize_stocks, app): offerer = offers_factories.OffererFactory(siren=123456789) offers_factories.VenueFactory(managingOfferer=offerer, id=3) offerer2 = offers_factories.OffererFactory(siren=123456780) ApiKeyFactory(offerer=offerer2) mock_synchronize_stocks.return_value = {} test_client = TestClient(app.test_client()) test_client.auth_header = { "Authorization": f"Bearer {DEFAULT_CLEAR_API_KEY}" } response1 = test_client.post( "/v2/venue/3/stocks", json={"stocks": [{ "ref": "123456789", "available": 4 }]}) response2 = test_client.post( "/v2/venue/123/stocks", json={"stocks": [{ "ref": "123456789", "available": 4 }]}) assert response1.status_code == 404 assert response2.status_code == 404 mock_synchronize_stocks.assert_not_called()
def test_with_user_linked_to_offerers(app): offerer1 = offers_factories.OffererFactory() offerer2 = offers_factories.OffererFactory(siren="123456788") venue1 = offers_factories.VenueFactory(managingOfferer=offerer1) venue2 = offers_factories.VenueFactory(managingOfferer=offerer1) venue3 = offers_factories.VenueFactory(managingOfferer=offerer1) venue4 = offers_factories.VenueFactory(managingOfferer=offerer2) for venue in (venue1, venue2, venue3, venue4): payments_factories.PaymentFactory( booking__stock__offer__venue=venue, transactionLabel= "pass Culture Pro - remboursement 1ère quinzaine 06-21") pro = users_factories.ProFactory(offerers=[offerer1, offerer2]) # When client = TestClient(app.test_client()).with_session_auth(pro.email) response = client.get("/reimbursements/csv") # Then assert response.status_code == 200 assert response.headers["Content-type"] == "text/csv; charset=utf-8;" assert response.headers[ "Content-Disposition"] == "attachment; filename=remboursements_pass_culture.csv" rows = response.data.decode("utf-8").splitlines() assert len(rows) == 1 + 4 # header + payments
def test_invalid_offerer_id(mock_get_filtered_venues, app): pro_user = users_factories.ProFactory(email="*****@*****.**") offerer = offers_factories.OffererFactory() offers_factories.UserOffererFactory(user=pro_user, offerer=offerer) offers_factories.VenueFactory(managingOfferer=offerer) query_params = [ f"offererId={humanize(666)}", ] # when response = TestClient(app.test_client()).with_session_auth(pro_user.email).get(f"/venues?{'&'.join(query_params)}") # then # then assert response.status_code == 200 mock_get_filtered_venues.assert_called_once_with( active_offerers_only=None, offerer_id=666, pro_user_id=pro_user.id, user_is_admin=False, validated_offerer=None, validated_offerer_for_user=None, ) assert "venues" in response.json assert len(response.json["venues"]) == 0
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_offerer_with_validated_offers(self): offerer = offers_factories.OffererFactory() offers_factories.OfferFactory.create_batch( size=2, validation=OfferValidationStatus.APPROVED, venue__managingOfferer=offerer ) assert offerer.nApprovedOffers == 2
def test_accepts_request_with_price(price, expected_price, app): ProviderFactory(name="Pass Culture API Stocks", localClass="PCAPIStocks") offerer = offers_factories.OffererFactory(siren=123456789) venue = offers_factories.VenueFactory(managingOfferer=offerer) offer_to_update = offers_factories.OfferFactory( product__idAtProviders="123456789", product__subcategoryId="LIVRE_PAPIER", idAtProviders=f"123456789@{venue.id}", product__extraData={"prix_livre": expected_price}, venue=venue, ) ApiKeyFactory(offerer=offerer) test_client = TestClient(app.test_client()) test_client.auth_header = { "Authorization": f"Bearer {DEFAULT_CLEAR_API_KEY}" } response = test_client.post(f"/v2/venue/{venue.id}/stocks", json={ "stocks": [{ "ref": "123456789", "available": 4, "price": price }] }) assert response.status_code == 204 assert offer_to_update.stocks[0].price == expected_price
def test_results_are_filtered_by_given_period_ending_date(self, mocked_list_offers, app, db_session): # given pro = users_factories.ProFactory() offerer = offers_factories.OffererFactory() offers_factories.UserOffererFactory(user=pro, offerer=offerer) # when response = ( TestClient(app.test_client()) .with_session_auth(email=pro.email) .get("/offers?periodEndingDate=2020-10-11T23:59:59Z") ) # then assert response.status_code == 200 mocked_list_offers.assert_called_once_with( user_id=pro.id, user_is_admin=pro.isAdmin, offerer_id=None, venue_id=None, category_id=None, name_keywords_or_isbn=None, period_beginning_date=None, period_ending_date="2020-10-11T23:59:59Z", status=None, creation_mode=None, )
def test_should_not_set_not_processable_payments_to_retry_when_bank_information_status_is_not_accepted(self): # Given offerer = offers_factories.OffererFactory(name="first offerer") stock = offers_factories.ThingStockFactory(offer__venue__managingOfferer=offerer) booking = bookings_factories.UsedBookingFactory(stock=stock) offers_factories.BankInformationFactory( offerer=offerer, iban=None, bic=None, status=BankInformationStatus.DRAFT ) not_processable_payment = payments_factories.PaymentFactory(booking=booking, amount=10, iban=None, bic=None) payments_factories.PaymentStatusFactory( payment=not_processable_payment, status=TransactionStatus.NOT_PROCESSABLE ) sent_payment = payments_factories.PaymentFactory(booking=booking, amount=10) payments_factories.PaymentStatusFactory(payment=sent_payment, status=TransactionStatus.SENT) new_batch_date = datetime.datetime.now() # When set_not_processable_payments_with_bank_information_to_retry(new_batch_date) # Then queried_not_processable_payment = Payment.query.filter_by(id=not_processable_payment.id).one() queried_sent_payment = Payment.query.filter_by(id=sent_payment.id).one() assert queried_not_processable_payment.iban == None assert queried_not_processable_payment.bic == None assert queried_not_processable_payment.batchDate != new_batch_date assert queried_not_processable_payment.currentStatus.status == TransactionStatus.NOT_PROCESSABLE assert queried_sent_payment.currentStatus.status == TransactionStatus.SENT
def test_should_set_not_processable_payments_to_retry_and_update_payments_bic_and_iban_using_venue_information( self, ): # Given offerer = offers_factories.OffererFactory(name="first offerer") stock = offers_factories.ThingStockFactory(offer__venue__managingOfferer=offerer) booking = bookings_factories.UsedBookingFactory(stock=stock) offers_factories.BankInformationFactory(offerer=offerer, iban="FR7611808009101234567890147", bic="CCBPFRPPVER") not_processable_payment = payments_factories.PaymentFactory(booking=booking, amount=10, iban=None, bic=None) payments_factories.PaymentStatusFactory( payment=not_processable_payment, status=TransactionStatus.NOT_PROCESSABLE ) sent_payment = payments_factories.PaymentFactory( booking=booking, amount=10, iban="FR7630007000111234567890144", bic="BDFEFR2LCCB" ) payments_factories.PaymentStatusFactory(payment=sent_payment, status=TransactionStatus.SENT) new_batch_date = datetime.datetime.now() # When set_not_processable_payments_with_bank_information_to_retry(new_batch_date) # Then queried_not_processable_payment = Payment.query.filter_by(id=not_processable_payment.id).one() assert queried_not_processable_payment.iban == "FR7611808009101234567890147" assert queried_not_processable_payment.bic == "CCBPFRPPVER" assert queried_not_processable_payment.batchDate == new_batch_date
def test_full_valid_call_with_false(mock_get_filtered_venues, app): pro_user = users_factories.ProFactory(email="*****@*****.**") offerer = offers_factories.OffererFactory() offers_factories.UserOffererFactory(user=pro_user, offerer=offerer) query_params = [ "validated=false", "validatedForUser=false", f"offererId={humanize(offerer.id)}", "activeOfferersOnly=false", ] # when response = TestClient(app.test_client()).with_session_auth(pro_user.email).get(f"/venues?{'&'.join(query_params)}") # then assert response.status_code == 200 mock_get_filtered_venues.assert_called_once_with( active_offerers_only=False, offerer_id=offerer.id, pro_user_id=pro_user.id, user_is_admin=False, validated_offerer=False, validated_offerer_for_user=False, )
def test_edit_product_gcu_compatibility(self, mocked_validate_csrf_token, mocked_async_index_offer_ids, app, db_session): # Given users_factories.AdminFactory(email="*****@*****.**") offerer = offers_factories.OffererFactory() product_1 = offers_factories.ThingProductFactory( description="premier produit inapproprié", extraData={"isbn": "isbn-de-test"}) venue = offers_factories.VenueFactory(managingOfferer=offerer) offers_factories.OfferFactory(product=product_1, venue=venue) offers_factories.OfferFactory(product=product_1, venue=venue) # When client = TestClient( app.test_client()).with_session_auth("*****@*****.**") response = client.post( "/pc/back-office/many_offers_operations/product_gcu_compatibility?isbn=isbn-de-test" ) # Then assert response.status_code == 302 assert response.headers[ "location"] == "http://localhost/pc/back-office/many_offers_operations/" products = Product.query.all() offers = Offer.query.all() first_product = products[0] first_offer = offers[0] second_offer = offers[1] assert not first_product.isGcuCompatible assert not first_offer.isActive assert not second_offer.isActive mocked_async_index_offer_ids.assert_called_once_with( [offer.id for offer in offers])
def test_offerer_without_validated_offer(self): offerer = offers_factories.OffererFactory() offers_factories.OfferFactory(validation=OfferValidationStatus.DRAFT, venue__managingOfferer=offerer) offers_factories.OfferFactory(validation=OfferValidationStatus.REJECTED, venue__managingOfferer=offerer) offers_factories.OfferFactory(validation=OfferValidationStatus.PENDING, venue__managingOfferer=offerer) assert offerer.nApprovedOffers == 0
def test_with_venue_filter(app): beginning_date_iso_format = (date.today() - timedelta(days=2)).isoformat() ending_date_iso_format = (date.today() + timedelta(days=2)).isoformat() offerer = offers_factories.OffererFactory() venue1 = offers_factories.VenueFactory(managingOfferer=offerer) venue2 = offers_factories.VenueFactory(managingOfferer=offerer) for venue in (venue1, venue2): payments_factories.PaymentStatusFactory( payment__booking__stock__offer__venue=venue, status=TransactionStatus.SENT, payment__transactionLabel= "pass Culture Pro - remboursement 1ère quinzaine 06-21", ) pro = users_factories.ProFactory(offerers=[offerer]) # When client = TestClient(app.test_client()).with_session_auth(pro.email) response = client.get( f"/reimbursements/csv?reimbursementPeriodBeginningDate={beginning_date_iso_format}&reimbursementPeriodEndingDate={ending_date_iso_format}&venueId={humanize(venue1.id)}" ) # Then assert response.status_code == 200 assert response.headers["Content-type"] == "text/csv; charset=utf-8;" assert response.headers[ "Content-Disposition"] == "attachment; filename=remboursements_pass_culture.csv" rows = response.data.decode("utf-8").splitlines() assert len(rows) == 1 + 1 # header + payments
def should_filter_offers_by_given_offerer_id(self, mocked_list_offers, app, db_session): # given pro = users_factories.ProFactory() offerer = offers_factories.OffererFactory() offers_factories.UserOffererFactory(user=pro, offerer=offerer) offers_factories.VenueFactory(managingOfferer=offerer) # when response = ( TestClient(app.test_client()) .with_session_auth(email=pro.email) .get("/offers?offererId=" + humanize(offerer.id)) ) # then assert response.status_code == 200 mocked_list_offers.assert_called_once_with( user_id=pro.id, user_is_admin=pro.isAdmin, offerer_id=offerer.id, venue_id=None, category_id=None, name_keywords_or_isbn=None, period_beginning_date=None, period_ending_date=None, status=None, creation_mode=None, )
def test_basics(self): offerer = offers_factories.OffererFactory(name="offerer", siren="123456") booking = bookings_factories.IndividualBookingFactory( stock__offer__venue__managingOfferer=offerer) reimbursement = BookingReimbursement(booking, PhysicalOffersReimbursement(), Decimal(10)) batch_date = datetime.utcnow() payment = create_payment_for_booking(reimbursement, batch_date) assert payment.bookingId == booking.id assert payment.amount == 10 assert payment.reimbursementRule == PhysicalOffersReimbursement( ).description assert payment.reimbursementRate == PhysicalOffersReimbursement().rate assert payment.comment is None assert payment.author == "batch" assert payment.transactionLabel == "pass Culture Pro - remboursement 1ère quinzaine 01-2021" assert payment.batchDate == batch_date assert payment.iban is None assert payment.bic is None assert payment.recipientName == "offerer" assert payment.recipientSiren == "123456"
def test_returns_pro_users_with_matching_email_provider(self): pro_user_with_matching_email = users_factories.ProFactory( email="*****@*****.**", isActive=True) offerer = offers_factories.OffererFactory() offers_factories.UserOffererFactory(user=pro_user_with_matching_email, offerer=offerer) pro_user_with_not_matching_email = users_factories.ProFactory( email="*****@*****.**", isActive=True) offerer2 = offers_factories.OffererFactory() offers_factories.UserOffererFactory( user=pro_user_with_not_matching_email, offerer=offerer2) users = find_pro_users_by_email_provider("suspect.com") assert len(users) == 1 assert users[0] == pro_user_with_matching_email
def test_legacy_api_key(self): offerer = offers_factories.OffererFactory() value = random_token(64) ApiKey(value=value, offerer=offerer) found_api_key = offerers_api.find_api_key(value) assert found_api_key.offerer == offerer
def test_generate_and_save_api_key(self): offerer = offers_factories.OffererFactory() generated_key = offerers_api.generate_and_save_api_key(offerer.id) found_api_key = offerers_api.find_api_key(generated_key) assert found_api_key.offerer == offerer
def test_error_get_by_offerer_on_non_prod_env(self, mocked_get_by_offerer): mocked_get_by_offerer.side_effect = [ApiEntrepriseException] offerer = offers_factories.OffererFactory() assert get_offerer_legal_category(offerer) == { "legal_category_code": "XXXX", "legal_category_label": "Catégorie factice (hors Prod)", }
def test_generate_and_save_api_key_for_offerer(): # Given siren_unknown = "291893841948" offerer_1_having_api_key = offers_factories.OffererFactory() ApiKeyFactory(offerer=offerer_1_having_api_key) offerer_2_needing_api_key = offers_factories.OffererFactory() # When generate_and_save_api_key_for_offerer([ siren_unknown, offerer_1_having_api_key.siren, offerer_2_needing_api_key.siren ]) # Then assert ApiKey.query.count() == 2 offerers = {k.offerer for k in ApiKey.query.all()} assert offerers == {offerer_1_having_api_key, offerer_2_needing_api_key}
def test_do_nothing_when_no_user_provided(self): # Given offerer = offers_factories.OffererFactory() # When created_user_offerer = offerer.grant_access(None) # Then assert created_user_offerer is None
def test_get_query_and_count(self, db_session): offer_view = ValidationView(model=Offer, session=db_session) validated_offerer = offers_factories.OffererFactory() non_validated_offerer = offers_factories.OffererFactory(validationToken="token") offer_1 = offers_factories.OfferFactory( validation=OfferValidationStatus.PENDING, venue__managingOfferer=validated_offerer, ) offers_factories.OfferFactory( validation=OfferValidationStatus.PENDING, venue__managingOfferer=non_validated_offerer, ) get_query_offers_list = offer_view.get_query().all() get_count_query_scalar = offer_view.get_count_query().scalar() assert get_query_offers_list == [offer_1] assert get_count_query_scalar == 1
def test_update_product_if_owning_offerer_is_the_venue_managing_offerer(self): offerer = factories.OffererFactory() product = factories.ProductFactory(owningOfferer=offerer) offer = factories.OfferFactory(product=product, venue__managingOfferer=offerer) offer = api.update_offer(offer, name="New name") assert offer.name == "New name" assert product.name == "New name"
def should_not_return_deactivated_offerers(self) -> None: # Given admin = users_factories.AdminFactory() offers_factories.OffererFactory(isActive=False) # When offerers = get_all_offerers_for_user(user=admin, filters={}) # Then assert len(offerers) == 0
def test_raises_if_user_cannot_access_offerer(self, app): user = users_factories.UserFactory() offerer = offers_factories.OffererFactory() with pytest.raises(ApiErrors) as error: check_user_has_access_to_offerer(user, offerer.id) assert error.value.errors["global"] == [ "Vous n'avez pas les droits d'accès suffisant pour accéder à cette information." ] assert error.value.status_code == 403
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_offerer_legal_category_called_many_times(self, mocked_get_offerer_legal_category): mocked_get_offerer_legal_category.return_value = { "legal_category_code": "5202", "legal_category_label": "Société en nom collectif", } offerer = offers_factories.OffererFactory() assert offerer.legal_category == "5202" assert offerer.legal_category == "5202" assert offerer.legal_category == "5202" assert mocked_get_offerer_legal_category.call_count == 1
def should_return_all_offerers_for_an_admin(self) -> None: # Given admin = users_factories.AdminFactory() offerer = offers_factories.OffererFactory() # When offerers = get_all_offerers_for_user(user=admin, filters={}) # Then assert len(offerers) == 1 assert offerers[0].id == offerer.id
def test_error_get_by_offerer_on_prod_env(self, mocked_get_by_offerer): mocked_get_by_offerer.side_effect = [ ApiEntrepriseException( "Error getting API entreprise DATA for SIREN : xxx") ] offerer = offers_factories.OffererFactory() with pytest.raises(ApiEntrepriseException) as error: get_offerer_legal_category(offerer) assert "Error getting API entreprise DATA for SIREN : xxx" in str( error.value)