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
def test_update_venue_other_offer_id_at_provider( self, mocked_validate_csrf_token, app): AdminFactory(email="*****@*****.**") venue = VenueFactory(siret="22222222222222") id_at_providers = "id_at_provider_ne_contenant_pas_le_siret" stock = StockFactory(offer__venue=venue, idAtProviders=id_at_providers, offer__idAtProviders=id_at_providers) data = dict( name=venue.name, siret="88888888888888", city=venue.city, postalCode=venue.postalCode, address=venue.address, publicName=venue.publicName, latitude=venue.latitude, longitude=venue.longitude, isPermanent=venue.isPermanent, ) client = TestClient( app.test_client()).with_session_auth("*****@*****.**") response = client.post(f"/pc/back-office/venue/edit/?id={venue.id}", form=data) assert response.status_code == 302 venue_edited = Venue.query.get(venue.id) stock = Stock.query.get(stock.id) offer = Offer.query.get(stock.offer.id) assert venue_edited.siret == "88888888888888" assert stock.idAtProviders == "id_at_provider_ne_contenant_pas_le_siret" assert offer.idAtProviders == "id_at_provider_ne_contenant_pas_le_siret"
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
def test_insufficient_credit(self, app): users_factories.UserFactory(email=self.identifier) stock = StockFactory(price=501) access_token = create_access_token(identity=self.identifier) test_client = TestClient(app.test_client()) test_client.auth_header = {"Authorization": f"Bearer {access_token}"} response = test_client.post("/native/v1/book_offer", json={"stockId": stock.id, "quantity": 1}) assert response.status_code == 400 assert response.json["code"] == "INSUFFICIENT_CREDIT"
def test_edit_venue_provider(self, mock_siret_can_be_synchronized, mock_synchronize_venue_provider, validate_csrf_token, client, app): # Given AdminFactory(email="*****@*****.**") venue = VenueFactory() old_provider = ProviderFactory(name="old provider", enabledForPro=True, localClass=None, apiUrl="https://example.com") new_provider = ProviderFactory(name="new provider", enabledForPro=True, localClass=None, apiUrl="https://example2.com") venue_provider = VenueProviderFactory(provider=old_provider, venue=venue) existing_stock = StockFactory(quantity=10, offer__venue=venue, offer__idAtProviders="1") BookingFactory(stock=existing_stock) mock_siret_can_be_synchronized.return_value = True data = dict( provider=new_provider.id, venue=venue.id, venueIdAtOfferProvider="hsf4uiagèy12386dq", ) client.with_session_auth("*****@*****.**") response = client.post( f"/pc/back-office/venue_providers/edit/?id={venue_provider.id}", form=data) assert response.status_code == 302 # Then venue_provider = VenueProvider.query.one() # Check that venue_provider model have been updated assert venue_provider.venue == venue assert venue_provider.provider == new_provider assert venue_provider.venueIdAtOfferProvider == "hsf4uiagèy12386dq" # Check that the quantity of existing stocks have been updated and quantity reset to booked_quantity. assert existing_stock.quantity == 1 assert existing_stock.offer.lastProviderId == new_provider.id mock_synchronize_venue_provider.assert_called_once_with(venue_provider)
def test_book_offer(self, app): stock = StockFactory() user = users_factories.UserFactory(email=self.identifier) access_token = create_access_token(identity=self.identifier) test_client = TestClient(app.test_client()) test_client.auth_header = {"Authorization": f"Bearer {access_token}"} response = test_client.post("/native/v1/book_offer", json={"stockId": stock.id, "quantity": 1}) assert response.status_code == 204 booking = Booking.query.filter(Booking.stockId == stock.id).first() assert booking.userId == user.id
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)]
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)
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"
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 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
def test_post_bookings(self, app): stock = StockFactory() user = users_factories.BeneficiaryGrant18Factory(email=self.identifier) access_token = create_access_token(identity=self.identifier) test_client = TestClient(app.test_client()) test_client.auth_header = {"Authorization": f"Bearer {access_token}"} response = test_client.post("/native/v1/bookings", json={ "stockId": stock.id, "quantity": 1 }) assert response.status_code == 200 booking = (Booking.query.filter(Booking.stockId == stock.id).options( joinedload(Booking.individualBooking)).first()) assert booking.individualBooking.userId == user.id assert response.json["bookingId"] == booking.id
def test_get_bookings(self, app): OFFER_URL = "https://demo.pass/some/path?token={token}&email={email}&offerId={offerId}" user = users_factories.BeneficiaryGrant18Factory(email=self.identifier) permanent_booking = booking_factories.UsedIndividualBookingFactory( individualBooking__user=user, stock__offer__subcategoryId=subcategories. TELECHARGEMENT_LIVRE_AUDIO.id, dateUsed=datetime(2021, 2, 3), ) event_booking = booking_factories.IndividualBookingFactory( individualBooking__user=user, stock=EventStockFactory(beginningDatetime=datetime(2021, 3, 14))) digital_stock = StockWithActivationCodesFactory() first_activation_code = digital_stock.activationCodes[0] second_activation_code = digital_stock.activationCodes[1] digital_booking = booking_factories.UsedIndividualBookingFactory( individualBooking__user=user, stock=digital_stock, activationCode=first_activation_code, ) ended_digital_booking = booking_factories.UsedIndividualBookingFactory( individualBooking__user=user, displayAsEnded=True, stock=digital_stock, activationCode=second_activation_code, ) expire_tomorrow = booking_factories.IndividualBookingFactory( individualBooking__user=user, dateCreated=datetime.now() - timedelta(days=29)) used_but_in_future = booking_factories.UsedIndividualBookingFactory( individualBooking__user=user, dateUsed=datetime(2021, 3, 11), stock=StockFactory(beginningDatetime=datetime(2021, 3, 15)), ) cancelled_permanent_booking = booking_factories.CancelledIndividualBookingFactory( individualBooking__user=user, stock__offer__subcategoryId=subcategories. TELECHARGEMENT_LIVRE_AUDIO.id, cancellation_date=datetime(2021, 3, 10), ) cancelled = booking_factories.CancelledIndividualBookingFactory( individualBooking__user=user, cancellation_date=datetime(2021, 3, 8)) used1 = booking_factories.UsedIndividualBookingFactory( individualBooking__user=user, dateUsed=datetime(2021, 3, 1)) used2 = booking_factories.UsedIndividualBookingFactory( individualBooking__user=user, displayAsEnded=True, dateUsed=datetime(2021, 3, 2), stock__offer__url=OFFER_URL, cancellation_limit_date=datetime(2021, 3, 2), ) mediation = MediationFactory(id=111, offer=used2.stock.offer, thumbCount=1, credit="street credit") access_token = create_access_token(identity=self.identifier) test_client = TestClient(app.test_client()) test_client.auth_header = {"Authorization": f"Bearer {access_token}"} # 1: get the user # 1: get the bookings # 1: get AUTO_ACTIVATE_DIGITAL_BOOKINGS feature # 1: rollback with assert_num_queries(4): response = test_client.get("/native/v1/bookings") assert response.status_code == 200 assert [b["id"] for b in response.json["ongoing_bookings"]] == [ expire_tomorrow.id, event_booking.id, used_but_in_future.id, digital_booking.id, permanent_booking.id, ] assert response.json["ongoing_bookings"][3]["activationCode"] assert [b["id"] for b in response.json["ended_bookings"]] == [ ended_digital_booking.id, cancelled_permanent_booking.id, cancelled.id, used2.id, used1.id, ] assert response.json["ended_bookings"][3] == { "activationCode": None, "cancellationDate": None, "cancellationReason": None, "confirmationDate": "2021-03-02T00:00:00Z", "completedUrl": f"https://demo.pass/some/path?token={used2.token}&[email protected]&offerId={humanize(used2.stock.offer.id)}", "dateUsed": "2021-03-02T00:00:00Z", "expirationDate": None, "quantity": 1, "qrCodeData": None, "id": used2.id, "stock": { "beginningDatetime": None, "id": used2.stock.id, "offer": { "category": { "categoryType": "Thing", "label": "Support physique (DVD, Blu-ray...)", "name": "FILM", }, "subcategoryId": subcategories.SUPPORT_PHYSIQUE_FILM.id, "extraData": None, "id": used2.stock.offer.id, "image": { "credit": "street credit", "url": mediation.thumbUrl }, "isDigital": True, "isPermanent": False, "name": used2.stock.offer.name, "url": f"https://demo.pass/some/path?token={used2.token}&[email protected]&offerId={humanize(used2.stock.offer.id)}", "venue": { "city": "Paris", "coordinates": { "latitude": 48.87004, "longitude": 2.3785 }, "id": used2.venue.id, "name": used2.venue.name, "publicName": used2.venue.publicName, }, "withdrawalDetails": None, }, }, "token": used2.token, "totalAmount": 1000, } for booking in response.json["ongoing_bookings"]: assert booking["qrCodeData"] is not None