def should_book_an_offer_even_if_physical_offer_capping_is_exeeded( self, mocked_redis, app): # Given product = offers_factories.DigitalProductFactory() stock1 = offers_factories.StockFactory( price=200, offer__type=str(ThingType.AUDIOVISUEL), offer__product=product, ) booking = bookings_factories.BookingFactory(stock=stock1) user = booking.user stock2 = offers_factories.StockFactory( price=200, offer__type=str(ThingType.AUDIOVISUEL), offer__product=product, ) # When create_booking_for_user_on_specific_stock_bypassing_capping_limits( user.id, stock2.id) # Then assert Booking.query.filter_by(stockId=stock2.id).one() is not None mocked_redis.add_offer_id.assert_called_once_with( client=app.redis_client, offer_id=stock2.offer.id)
def test_no_need_when_booking_is_autovalidated(self): # Given offer = offers_factories.OfferFactory( venue__name="Lieu de l'offreur", venue__managingOfferer__name="Théâtre du coin", product=offers_factories.DigitalProductFactory( name="Super événement", url="http://example.com"), ) digital_stock = offers_factories.StockWithActivationCodesFactory() first_activation_code = digital_stock.activationCodes[0] booking = bookings_factories.UsedIndividualBookingFactory( individualBooking__user__email="*****@*****.**", individualBooking__user__firstName="John", individualBooking__user__lastName="Doe", stock__offer=offer, activationCode=first_activation_code, dateCreated=datetime(2018, 1, 1), ) # When email_data = retrieve_data_for_offerer_booking_recap_email( booking.individualBooking) # Then expected = get_expected_base_email_data( booking, date="", heure="", is_event=0, is_booking_autovalidated=1, must_use_token_for_payment=0, offer_type="VOD", contremarque=booking.token, ) assert email_data == expected
def test_should_return_thing_data_when_booking_is_on_an_online_offer(self): # Given stock = offers_factories.ThingStockFactory( offer__product=offers_factories.DigitalProductFactory()) booking = bookings_factories.IndividualBookingFactory( stock=stock, individualBooking__user__firstName="Georges", individualBooking__user__lastName="Georges", ) # When mailjet_data = retrieve_data_to_warn_user_after_pro_booking_cancellation( booking) # Then assert mailjet_data == { "MJ-TemplateID": 1116690, "MJ-TemplateLanguage": True, "Vars": { "event_date": "", "event_hour": "", "is_event": 0, "is_free_offer": 0, "is_online": 1, "is_thing": 0, "offer_name": booking.stock.offer.name, "offer_price": "10.00", "offerer_name": booking.offerer.name, "user_first_name": "Georges", "user_last_name": "Georges", "venue_name": booking.venue.name, }, }
def test_should_return_thing_data_when_booking_is_on_an_online_offer(self): # Given stock = offers_factories.ThingStockFactory( offer__product=offers_factories.DigitalProductFactory()) booking = bookings_factories.BookingFactory(stock=stock) # When mailjet_data = retrieve_data_to_warn_beneficiary_after_pro_booking_cancellation( booking) # Then assert mailjet_data == { "MJ-TemplateID": 1116690, "MJ-TemplateLanguage": True, "Vars": { "can_book_again": 1, "event_date": "", "event_hour": "", "is_event": 0, "is_free_offer": 0, "is_online": 1, "is_thing": 0, "offer_name": booking.stock.offer.name, "offer_price": "10.00", "offerer_name": booking.stock.offer.venue.managingOfferer.name, "user_first_name": "Jeanne", "venue_name": booking.stock.offer.venue.name, }, }
def test_digital_limit_on_uncapped_type(self): beneficiary = self._get_beneficiary() product = offers_factories.DigitalProductFactory(type=str(ThingType.OEUVRE_ART)) offer = offers_factories.OfferFactory(product=product) factories.BookingFactory(user=beneficiary, stock__price=190, stock__offer=offer) # should not raise because OEUVRE_ART is not capped validation.check_expenses_limits(beneficiary, 11, offer)
def test_booking_on_digital_offer_without_activation_stock(self): offer = offers_factories.OfferFactory(product=offers_factories.DigitalProductFactory()) stock = offers_factories.StockFactory(price=10, dnBookedQuantity=5, offer=offer) beneficiary = users_factories.BeneficiaryGrant18Factory() booking = api.book_offer(beneficiary=beneficiary, stock_id=stock.id, quantity=1) assert not booking.isUsed assert booking.status is not BookingStatus.USED
def test_success_if_digital_product_and_virtual_venue(self): venue = factories.VirtualVenueFactory() user_offerer = factories.UserOffererFactory(offerer=venue.managingOfferer) product = factories.DigitalProductFactory() data = offers_serialize.PostOfferBodyModel( venueId=humanize(venue.id), productId=humanize(product.id), ) api.create_offer(data, user_offerer.user) # should not fail
def test_raise_if_booking_was_automatically_used_for_digital_offer_with_activation_code(self): offer = offers_factories.OfferFactory(product=offers_factories.DigitalProductFactory()) digital_stock = offers_factories.StockWithActivationCodesFactory() first_activation_code = digital_stock.activationCodes[0] booking = booking_factories.UsedIndividualBookingFactory( stock__offer=offer, activationCode=first_activation_code ) with pytest.raises(api_errors.ForbiddenError): api.mark_as_unused(booking) assert booking.isUsed assert booking.status is BookingStatus.USED
def test_digital_limit_on_uncapped_type(self): beneficiary = self._get_beneficiary() product = offers_factories.DigitalProductFactory( subcategoryId=subcategories.OEUVRE_ART.id) offer = offers_factories.OfferFactory(product=product) factories.IndividualBookingFactory(individualBooking__user=beneficiary, stock__price=190, stock__offer=offer) # should not raise because OEUVRE_ART is not capped validation.check_expenses_limits(beneficiary, 11, offer)
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 test_fail_if_digital_product_and_physical_venue(self): venue = factories.VenueFactory() user_offerer = factories.UserOffererFactory(offerer=venue.managingOfferer) product = factories.DigitalProductFactory() data = offers_serialize.PostOfferBodyModel( venueId=humanize(venue.id), productId=humanize(product.id), ) with pytest.raises(api_errors.ApiErrors) as error: api.create_offer(data, user_offerer.user) err = 'Une offre numérique doit obligatoirement être associée au lieu "Offre numérique"' assert error.value.errors["venue"] == [err]
def test_with_virtual_offer(self): # Given author = users_factories.ProFactory() offer = offers_factories.EventOfferFactory( author=author, product=offers_factories.DigitalProductFactory( name="Les lièvres pas malins"), venue=offers_factories.VirtualVenueFactory(), ) # When email = make_offer_creation_notification_email(offer) # Then assert email[ "Subject"] == "[Création d’offre - numérique] Les lièvres pas malins"
def test_relevancy(self): rule = reimbursement.DigitalThingsReimbursement() assert rule.is_relevant(create_digital_booking()) digital_book_booking = create_digital_booking( product_subcategory_id=subcategories.LIVRE_PAPIER.id) assert not rule.is_relevant(digital_book_booking) cinema_card_booking = create_digital_booking( product_subcategory_id=subcategories.CINE_VENTE_DISTANCE.id) assert not rule.is_relevant(cinema_card_booking) assert not rule.is_relevant(create_non_digital_thing_booking()) assert not rule.is_relevant(create_event_booking()) assert not rule.is_relevant( bookings_factories.EducationalBookingFactory( stock__offer__product=offers_factories.DigitalProductFactory()) )
def test_digital_limit(self): beneficiary = self._get_beneficiary() product = offers_factories.DigitalProductFactory(type=str(ThingType.AUDIOVISUEL)) offer = offers_factories.OfferFactory(product=product) factories.BookingFactory( user=beneficiary, stock__price=90, stock__offer=offer, ) validation.check_expenses_limits(beneficiary, 10, offer) # should not raise with pytest.raises(exceptions.DigitalExpenseLimitHasBeenReached) as error: validation.check_expenses_limits(beneficiary, 11, offer) assert error.value.errors["global"] == [ "Le plafond de 100 € pour les offres numériques ne vous permet pas de réserver cette offre." ]
def create_digital_booking(quantity=1, price=10, user=None, product_subcategory_id=None): user = user or users_factories.BeneficiaryGrant18Factory() product_kwargs = {} if product_subcategory_id: product_kwargs = {"subcategoryId": product_subcategory_id} product = offers_factories.DigitalProductFactory(**product_kwargs) stock = offers_factories.StockFactory( price=price, offer=offers_factories.ThingOfferFactory(product=product), ) return bookings_factories.UsedBookingFactory(user=user, stock=stock, quantity=quantity, dateUsed=datetime.now())
def test_hide_cancellation_policy_on_bookings_with_activation_code(self): offer = offers_factories.OfferFactory( venue__name="Lieu de l'offreur", venue__managingOfferer__name="Théâtre du coin", product=offers_factories.DigitalProductFactory(name="Super offre numérique", url="http://example.com"), ) digital_stock = offers_factories.StockWithActivationCodesFactory() first_activation_code = digital_stock.activationCodes[0] booking = bookings_factories.UsedIndividualBookingFactory( stock__offer=offer, activationCode=first_activation_code, dateCreated=datetime(2018, 1, 1), ) mediation = offers_factories.MediationFactory(offer=booking.stock.offer) email_data = retrieve_data_for_beneficiary_booking_confirmation_email(booking.individualBooking) expected = get_expected_base_email_data( booking, mediation, all_but_not_virtual_thing=0, all_things_not_virtual_thing=0, event_date="", event_hour="", is_event=0, is_single_event=0, offer_name="Super offre numérique", offer_price="10.00 €", offer_token=booking.activationCode.code, can_expire=0, is_digital_booking_with_activation_code_and_no_expiration_date=1, has_offer_url=1, digital_offer_url="http://example.com", user_first_name="Jeanne", venue_address="1 boulevard Poissonnière", venue_city="Paris", venue_postal_code="75000", booking_date="1 janvier 2018", booking_hour="01h00", expiration_delay="", ) assert email_data == expected
def test_digital_limit(self): beneficiary = self._get_beneficiary() product = offers_factories.DigitalProductFactory( subcategoryId=subcategories.VOD.id) offer = offers_factories.OfferFactory(product=product) factories.IndividualBookingFactory( individualBooking__user=beneficiary, stock__price=190, stock__offer=offer, ) validation.check_expenses_limits(beneficiary, 10, offer) # should not raise with pytest.raises( exceptions.DigitalExpenseLimitHasBeenReached) as error: validation.check_expenses_limits(beneficiary, 11, offer) assert error.value.errors["global"] == [ "Le plafond de 200 € pour les offres numériques ne vous permet pas de réserver cette offre." ]
def test_mark_as_unused_digital_offer(self): offer = offers_factories.OfferFactory(product=offers_factories.DigitalProductFactory()) booking = booking_factories.UsedIndividualBookingFactory(stock__offer=offer) api.mark_as_unused(booking) assert not booking.isUsed assert booking.status is not BookingStatus.USED