def should_only_cancel_old_thing_that_can_expire_bookings_before_start_date( self, app) -> None: now = datetime.utcnow() two_months_ago = now - timedelta(days=60) guitar = ProductFactory( subcategoryId=subcategories.ACHAT_INSTRUMENT.id, ) old_guitar_booking = booking_factories.IndividualBookingFactory( stock__offer__product=guitar, dateCreated=two_months_ago) disc = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE.id) old_disc_booking = booking_factories.IndividualBookingFactory( stock__offer__product=disc, dateCreated=two_months_ago) vod = ProductFactory(subcategoryId=subcategories.VOD.id) old_vod_booking = booking_factories.IndividualBookingFactory( stock__offer__product=vod, dateCreated=two_months_ago) handle_expired_bookings.cancel_expired_individual_bookings() assert old_guitar_booking.isCancelled assert old_guitar_booking.status is BookingStatus.CANCELLED assert old_guitar_booking.cancellationDate.timestamp( ) == pytest.approx(datetime.utcnow().timestamp(), rel=1) assert old_guitar_booking.cancellationReason == BookingCancellationReasons.EXPIRED assert old_disc_booking.isCancelled assert old_disc_booking.status is BookingStatus.CANCELLED assert old_disc_booking.cancellationDate.timestamp() == pytest.approx( datetime.utcnow().timestamp(), rel=1) assert old_disc_booking.cancellationReason == BookingCancellationReasons.EXPIRED assert not old_vod_booking.isCancelled assert old_vod_booking.status is not BookingStatus.CANCELLED assert not old_vod_booking.cancellationDate assert not old_vod_booking.cancellationReason
def should_only_cancel_old_thing_that_can_expire_bookings_before_start_date( self, app) -> None: now = datetime.utcnow() two_months_ago = now - timedelta(days=60) guitar = ProductFactory(type=str(offer_type.ThingType.INSTRUMENT)) old_guitar_booking = BookingFactory(stock__offer__product=guitar, dateCreated=two_months_ago) disc = ProductFactory(type=str(offer_type.ThingType.MUSIQUE)) old_disc_booking = BookingFactory(stock__offer__product=disc, dateCreated=two_months_ago) audio_book = ProductFactory(type=str(offer_type.ThingType.LIVRE_AUDIO)) old_audio_book_booking = BookingFactory( stock__offer__product=audio_book, dateCreated=two_months_ago) handle_expired_bookings.cancel_expired_bookings() assert old_guitar_booking.isCancelled assert old_guitar_booking.cancellationDate.timestamp( ) == pytest.approx(datetime.utcnow().timestamp(), rel=1) assert old_guitar_booking.cancellationReason == BookingCancellationReasons.EXPIRED assert old_disc_booking.isCancelled assert old_disc_booking.cancellationDate.timestamp() == pytest.approx( datetime.utcnow().timestamp(), rel=1) assert old_disc_booking.cancellationReason == BookingCancellationReasons.EXPIRED assert not old_audio_book_booking.isCancelled assert not old_audio_book_booking.cancellationDate assert not old_audio_book_booking.cancellationReason
def should_call_email_service_for_individual_bookings_which_will_expire_in_7_days( self, mocked_email_recap, app) -> None: # Given now = date.today() booking_date_23_days_ago = now - timedelta(days=23) booking_date_22_days_ago = now - timedelta(days=22) dvd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) expire_in_7_days_dvd_individual_booking = IndividualBookingFactory( stock__offer__product=dvd, dateCreated=booking_date_23_days_ago, isCancelled=False, ) non_expired_cd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE.id) dont_expire_in_7_days_cd_individual_booking = IndividualBookingFactory( stock__offer__product=non_expired_cd, dateCreated=booking_date_22_days_ago, isCancelled=False, ) repository.save(dont_expire_in_7_days_cd_individual_booking) # When notify_users_of_soon_to_be_expired_individual_bookings() # Then mocked_email_recap.assert_called_once_with( expire_in_7_days_dvd_individual_booking.individualBooking.user, [expire_in_7_days_dvd_individual_booking])
def test_should_cancel_old_thing_that_can_expire_booking(self, app) -> None: now = datetime.utcnow() eleven_days_ago = now - timedelta(days=11) two_months_ago = now - timedelta(days=60) book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id) old_book_booking = booking_factories.IndividualBookingFactory( stock__offer__product=book, dateCreated=eleven_days_ago) dvd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) old_dvd_booking = booking_factories.IndividualBookingFactory( stock__offer__product=dvd, dateCreated=two_months_ago) handle_expired_bookings.cancel_expired_individual_bookings() assert old_book_booking.isCancelled assert old_book_booking.status is BookingStatus.CANCELLED assert old_book_booking.cancellationDate.timestamp() == pytest.approx( datetime.utcnow().timestamp(), rel=1) assert old_book_booking.cancellationReason == BookingCancellationReasons.EXPIRED assert old_book_booking.stock.dnBookedQuantity == 0 assert old_dvd_booking.isCancelled assert old_dvd_booking.status is BookingStatus.CANCELLED assert old_dvd_booking.cancellationDate.timestamp() == pytest.approx( datetime.utcnow().timestamp(), rel=1) assert old_dvd_booking.cancellationReason == BookingCancellationReasons.EXPIRED assert old_dvd_booking.stock.dnBookedQuantity == 0
def test_should_mark_products_as_compatible_via_isbn(self): product = ProductFactory(id=1, extraData={"isbn": "ABCDEFG"}, isGcuCompatible=False) product_1 = ProductFactory(id=2, extraData={"isbn": "HIJKLMN"}, isGcuCompatible=False) product_2 = ProductFactory(id=3, extraData={"isbn": "VWXYZ"}, isGcuCompatible=False) product_3 = ProductFactory(id=4, extraData={"isbn": "HFGDS"}, isGcuCompatible=False) isbns_list = ["ABCDEFG", "HIJKLMN", "OPQRSTU", "HFGDS"] queries = 2 # update; commit with assert_num_queries(queries): bulk_update_is_gcu_compatible_via_isbns(isbns_list, 4, is_compatible=True) assert product.isGcuCompatible assert product_1.isGcuCompatible assert not product_2.isGcuCompatible assert product_3.isGcuCompatible
def test_handle_expired_bookings_should_cancel_expired_individual_and_educational_bookings( self, app) -> None: # Given now = datetime.utcnow() yesterday = now - timedelta(days=1) two_months_ago = now - timedelta(days=60) tomorrow = now + timedelta(days=1) expired_pending_educational_booking: Booking = booking_factories.PendingEducationalBookingFactory( educationalBooking__confirmationLimitDate=yesterday) non_expired_pending_educational_booking: Booking = booking_factories.PendingEducationalBookingFactory( educationalBooking__confirmationLimitDate=tomorrow) dvd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) expired_individual_booking = booking_factories.IndividualBookingFactory( stock__offer__product=dvd, dateCreated=two_months_ago) book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id) book_individual_recent_booking = booking_factories.IndividualBookingFactory( stock__offer__product=book) # When handle_expired_bookings.handle_expired_bookings() # Then assert expired_pending_educational_booking.status == BookingStatus.CANCELLED assert expired_individual_booking.status == BookingStatus.CANCELLED assert book_individual_recent_booking.status != BookingStatus.CANCELLED assert non_expired_pending_educational_booking.status == BookingStatus.PENDING
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])])
def should_call_email_service_for_bookings_which_will_expire_in_7_days( self, mocked_email_recap, app) -> None: # Given now = date.today() booking_date_23_days_ago = now - timedelta(days=23) booking_date_22_days_ago = now - timedelta(days=22) dvd = ProductFactory(type=str(offer_type.ThingType.AUDIOVISUEL)) expire_in_7_days_dvd_booking = BookingFactory( stock__offer__product=dvd, dateCreated=booking_date_23_days_ago, isCancelled=False, ) non_expired_cd = ProductFactory(type=str(offer_type.ThingType.MUSIQUE)) dont_expire_in_7_days_cd_booking = BookingFactory( stock__offer__product=non_expired_cd, dateCreated=booking_date_22_days_ago, isCancelled=False, ) repository.save(dont_expire_in_7_days_cd_booking) # When notify_users_of_soon_to_be_expired_bookings() # Then mocked_email_recap.assert_called_once_with( expire_in_7_days_dvd_booking.user, [expire_in_7_days_dvd_booking])
def test_should_send_email_to_offerer_when_expired_bookings_cancelled( self, app): now = datetime.utcnow() amnesiac_user = users_factories.UserFactory(email="*****@*****.**", firstName="Dory") long_ago = now - timedelta(days=31) dvd = ProductFactory(type=str(offer_type.ThingType.AUDIOVISUEL)) expired_today_dvd_booking = BookingFactory( stock__offer__product=dvd, stock__offer__name="Memento", stock__offer__venue__name="Mnémosyne", dateCreated=long_ago, isCancelled=True, cancellationReason=BookingCancellationReasons.EXPIRED, user=amnesiac_user, ) cd = ProductFactory(type=str(offer_type.ThingType.MUSIQUE)) expired_today_cd_booking = BookingFactory( stock__offer__product=cd, stock__offer__name="Random Access Memories", stock__offer__venue__name="Virgin Megastore", dateCreated=long_ago, isCancelled=True, cancellationReason=BookingCancellationReasons.EXPIRED, user=amnesiac_user, ) email_data = build_expired_bookings_recap_email_data_for_beneficiary( amnesiac_user, [expired_today_dvd_booking, expired_today_cd_booking], ) assert email_data == { "FromEmail": "*****@*****.**", "Mj-TemplateID": 1951103, "Mj-TemplateLanguage": True, "To": "*****@*****.**", "Vars": { "user_firstName": "Dory", "bookings": [ { "offer_name": "Memento", "venue_name": "Mnémosyne" }, { "offer_name": "Random Access Memories", "venue_name": "Virgin Megastore" }, ], "env": "-development", }, }
def test_should_send_two_emails_to_beneficiary_when_they_book_and_other_things_have_soon_to_be_expired_bookings( self, build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary ): # given now = datetime.utcnow() user = users_factories.BeneficiaryGrant18Factory( email="*****@*****.**") created_5_days_ago = now - timedelta(days=5) created_23_days_ago = now - timedelta(days=23) book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id) soon_to_be_expired_book_booking = booking_factories.IndividualBookingFactory( stock__offer__product=book, stock__offer__name="Fondation", stock__offer__venue__name="Première Fondation", dateCreated=created_5_days_ago, user=user, ) cd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE.id) soon_to_be_expired_cd_booking = booking_factories.IndividualBookingFactory( stock__offer__product=cd, stock__offer__name="Fondation et Empire", stock__offer__venue__name="Seconde Fondation", dateCreated=created_23_days_ago, user=user, ) # when send_soon_to_be_expired_individual_bookings_recap_email_to_beneficiary( user, [soon_to_be_expired_book_booking, soon_to_be_expired_cd_booking]) # then call1 = call(beneficiary=user, bookings=[soon_to_be_expired_book_booking], days_before_cancel=5, days_from_booking=5) call2 = call(beneficiary=user, bookings=[soon_to_be_expired_cd_booking], days_before_cancel=7, days_from_booking=23) calls = [call1, call2] build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary.assert_has_calls( calls, any_order=False) assert build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary.call_count == 2 assert len(mails_testing.outbox) == 2 # test number of emails sent assert mails_testing.outbox[0].sent_data["MJ-TemplateID"] == 12345 assert mails_testing.outbox[1].sent_data["MJ-TemplateID"] == 12345
def should_notify_of_todays_expired_bookings(self, mocked_send_email_recap, mocked_send_raw_email, app, caplog) -> None: caplog.set_level(logging.INFO) now = datetime.utcnow() yesterday = now - timedelta(days=1) long_ago = now - timedelta(days=31) very_long_ago = now - timedelta(days=32) dvd = ProductFactory(type=str(offer_type.ThingType.AUDIOVISUEL)) expired_today_dvd_booking = BookingFactory( stock__offer__product=dvd, dateCreated=long_ago, isCancelled=True, cancellationReason=BookingCancellationReasons.EXPIRED, ) cd = ProductFactory(type=str(offer_type.ThingType.MUSIQUE)) expired_today_cd_booking = BookingFactory( stock__offer__product=cd, dateCreated=long_ago, isCancelled=True, cancellationReason=BookingCancellationReasons.EXPIRED, ) painting = ProductFactory(type=str(offer_type.ThingType.OEUVRE_ART)) expired_yesterday_painting_booking = BookingFactory( stock__offer__product=painting, dateCreated=very_long_ago, isCancelled=True, cancellationReason=BookingCancellationReasons.EXPIRED, ) expired_yesterday_painting_booking.cancellationDate = yesterday repository.save(expired_yesterday_painting_booking) handle_expired_bookings.notify_offerers_of_expired_bookings() assert ( caplog.records[1].message == f"[notify_users_of_expired_bookings] 2 Offerers have been notified: [{expired_today_dvd_booking.stock.offer.venue.managingOfferer}," f" {expired_today_cd_booking.stock.offer.venue.managingOfferer}]") assert str(expired_yesterday_painting_booking) not in caplog.text assert mocked_send_email_recap.call_args_list[0][0] == ( expired_today_dvd_booking.stock.offer.venue.managingOfferer, [expired_today_dvd_booking], mocked_send_raw_email, ) assert mocked_send_email_recap.call_args_list[1][0] == ( expired_today_cd_booking.stock.offer.venue.managingOfferer, [expired_today_cd_booking], mocked_send_raw_email, )
def should_not_call_email_service_for_educational_bookings_which_will_expire_in_7_days( self, mocked_email_recap, app) -> None: """ No email should be sent to educational booking users. As of september 2021, EAC offers are only of event type so not concerned with expiring bookings. But in case an EAC offer becomes compatible with thing type offers We want a test to cover this behavior """ # Given now = date.today() booking_date_23_days_ago = now - timedelta(days=23) dvd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) EducationalBookingFactory( stock__offer__product=dvd, dateCreated=booking_date_23_days_ago, isCancelled=False, ) # When notify_users_of_soon_to_be_expired_individual_bookings() # Then assert not mocked_email_recap.called
def test_should_set_isGcuCompatible_and_isSynchronizationCompatible_at_false_in_product_and_deactivate_offer_when_bookings_related_to_offer( self, app): # Given isbn = "1111111111111" beneficiary = users_factories.BeneficiaryGrant18Factory() offerer = create_offerer(siren="775671464") venue = create_venue(offerer, name="Librairie Titelive", siret="77567146400110") product = ProductFactory( idAtProviders=isbn, isGcuCompatible=True, isSynchronizationCompatible=True, subcategoryId=subcategories.LIVRE_PAPIER.id, ) offer = create_offer_with_thing_product(venue, product=product, is_active=True) stock = create_stock(offer=offer, price=0) create_booking(user=beneficiary, is_cancelled=True, stock=stock) # When with pytest.raises(ProductWithBookingsException): delete_unwanted_existing_product("1111111111111") # Then offer = Offer.query.one() assert offer.isActive is False assert Product.query.one() == product assert not product.isGcuCompatible assert not product.isSynchronizationCompatible
def test_should_send_email_to_beneficiary_when_they_have_soon_to_be_expired_bookings( self, build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary ): # given now = datetime.utcnow() user = users_factories.BeneficiaryGrant18Factory( email="*****@*****.**") created_23_days_ago = now - timedelta(days=23) dvd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) soon_to_be_expired_dvd_booking = booking_factories.IndividualBookingFactory( stock__offer__product=dvd, stock__offer__name="Fondation", stock__offer__venue__name="Première Fondation", dateCreated=created_23_days_ago, user=user, ) cd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE.id) soon_to_be_expired_cd_booking = booking_factories.IndividualBookingFactory( stock__offer__product=cd, stock__offer__name="Fondation et Empire", stock__offer__venue__name="Seconde Fondation", dateCreated=created_23_days_ago, user=user, ) # when send_soon_to_be_expired_individual_bookings_recap_email_to_beneficiary( user, [soon_to_be_expired_cd_booking, soon_to_be_expired_dvd_booking]) # then build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary.assert_called_once_with( beneficiary=user, bookings=[ soon_to_be_expired_cd_booking, soon_to_be_expired_dvd_booking ], days_before_cancel=7, days_from_booking=23, ) assert len(mails_testing.outbox) == 1 # test number of emails sent assert mails_testing.outbox[0].sent_data["MJ-TemplateID"] == 12345
def test_can_be_synchronized_product_not_cgu_compatible_and_sync_compatible( self): product = ProductFactory(isGcuCompatible=False, isSynchronizationCompatible=True) assert not product.can_be_synchronized assert Product.query.filter(Product.can_be_synchronized).count() == 0 assert Product.query.filter(not_( Product.can_be_synchronized)).one() == product
def should_not_cancel_new_thing_that_can_expire_booking(self, app) -> None: book = ProductFactory(type=str(offer_type.ThingType.LIVRE_EDITION)) book_booking = BookingFactory(stock__offer__product=book) handle_expired_bookings.cancel_expired_bookings() assert not book_booking.isCancelled assert not book_booking.cancellationDate assert not book_booking.cancellationReason
def test_should_send_email_to_beneficiary_when_they_have_soon_to_be_expired_bookings( self, build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary ): # given now = datetime.utcnow() user = users_factories.UserFactory(email="*****@*****.**", isBeneficiary=True, isAdmin=False) created_23_days_ago = now - timedelta(days=23) dvd = ProductFactory(type=str(offer_type.ThingType.AUDIOVISUEL)) soon_to_be_expired_dvd_booking = BookingFactory( stock__offer__product=dvd, stock__offer__name="Fondation", stock__offer__venue__name="Première Fondation", dateCreated=created_23_days_ago, user=user, ) cd = ProductFactory(type=str(offer_type.ThingType.MUSIQUE)) soon_to_be_expired_cd_booking = BookingFactory( stock__offer__product=cd, stock__offer__name="Fondation et Empire", stock__offer__venue__name="Seconde Fondation", dateCreated=created_23_days_ago, user=user, ) mocked_send_email = Mock() # when send_soon_to_be_expired_bookings_recap_email_to_beneficiary( user, [soon_to_be_expired_cd_booking, soon_to_be_expired_dvd_booking], mocked_send_email) # then build_soon_to_be_expired_bookings_recap_email_data_for_beneficiary.assert_called_once_with( user, [soon_to_be_expired_cd_booking, soon_to_be_expired_dvd_booking]) mocked_send_email.assert_called_once_with( data={"MJ-TemplateID": 12345})
def should_not_cancel_new_thing_that_can_expire_booking(self, app) -> None: book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id) book_booking = booking_factories.BookingFactory( stock__offer__product=book) handle_expired_bookings.cancel_expired_individual_bookings() assert not book_booking.isCancelled assert book_booking.status is not BookingStatus.CANCELLED assert not book_booking.cancellationDate assert not book_booking.cancellationReason
def test_should_not_return_not_synchronization_compatible_product( self, app): valid_isbn = "1111111111111" ProductFactory( idAtProviders=valid_isbn, subcategoryId=subcategories.LIVRE_PAPIER.id, isSynchronizationCompatible=False, ) existing_product = find_active_book_product_by_isbn(valid_isbn) assert existing_product is None
def test_should_mark_synchronized_offers_and_products_as_not_synchronization_compatible_via_isbn( ): product_1 = ProductFactory(id=1, extraData={"isbn": "5555555555555"}) product_2 = ProductFactory(id=2, extraData={"isbn": "6666666666666"}) product_3 = ProductFactory(id=3, extraData={"isbn": "2222222222222"}) product_4 = ProductFactory(id=4, extraData={"isbn": "7777777777777"}) isbns_list = [ "5555555555555", "6666666666666", "8888888888888", "7777777777777" ] queries = 1 # update product queries += 1 # commit with assert_num_queries(queries): bulk_update_is_synchronization_compatible_via_isbns( isbns_list, is_synchronization_compatible=False, batch_size=4) assert not product_1.isSynchronizationCompatible assert not product_2.isSynchronizationCompatible assert product_3.isSynchronizationCompatible assert not product_4.isSynchronizationCompatible
def test_should_delete_nothing_when_product_not_found(self, app): # Given isbn = "1111111111111" ProductFactory(idAtProviders=isbn, isSynchronizationCompatible=False, subcategoryId=subcategories.LIVRE_PAPIER.id) # When delete_unwanted_existing_product(isbn) # Then assert Product.query.count() == 1
def test_should_notify_of_todays_expired_individual_bookings( self, mocked_send_email_recap, app) -> None: now = datetime.utcnow() yesterday = now - timedelta(days=1) long_ago = now - timedelta(days=31) very_long_ago = now - timedelta(days=32) dvd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) expired_today_dvd_booking = booking_factories.CancelledIndividualBookingFactory( stock__offer__product=dvd, dateCreated=long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, ) cd = ProductFactory( subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE.id) expired_today_cd_booking = booking_factories.CancelledIndividualBookingFactory( stock__offer__product=cd, dateCreated=long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, ) painting = ProductFactory(subcategoryId=subcategories.OEUVRE_ART.id) _expired_yesterday_booking = booking_factories.CancelledIndividualBookingFactory( stock__offer__product=painting, dateCreated=very_long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, cancellationDate=yesterday, ) handle_expired_bookings.notify_offerers_of_expired_individual_bookings( ) assert mocked_send_email_recap.call_count == 2 assert mocked_send_email_recap.call_args_list[0][0] == ( expired_today_dvd_booking.offerer, [expired_today_dvd_booking.individualBooking.booking], ) assert mocked_send_email_recap.call_args_list[1][0] == ( expired_today_cd_booking.offerer, [expired_today_cd_booking.individualBooking.booking], )
def test_should_send_email_to_beneficiary_when_expired_bookings_cancelled(): now = datetime.utcnow() amnesiac_user = users_factories.UserFactory(email="*****@*****.**", firstName="Dory") long_ago = now - timedelta(days=31) dvd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id) expired_today_dvd_booking = CancelledBookingFactory( stock__offer__product=dvd, stock__offer__name="Memento", stock__offer__venue__name="Mnémosyne", dateCreated=long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, user=amnesiac_user, ) cd = ProductFactory(subcategoryId=subcategories.SUPPORT_PHYSIQUE_MUSIQUE.id) expired_today_cd_booking = CancelledBookingFactory( stock__offer__product=cd, stock__offer__name="Random Access Memories", stock__offer__venue__name="Virgin Megastore", dateCreated=long_ago, cancellationReason=BookingCancellationReasons.EXPIRED, user=amnesiac_user, ) email_data = build_expired_bookings_recap_email_data_for_beneficiary( amnesiac_user, [expired_today_dvd_booking, expired_today_cd_booking], 30 ) assert email_data == { "Mj-TemplateID": 3095107, "Mj-TemplateLanguage": True, "Vars": { "user_firstName": "Dory", "bookings": [ {"offer_name": "Memento", "venue_name": "Mnémosyne"}, {"offer_name": "Random Access Memories", "venue_name": "Virgin Megastore"}, ], "withdrawal_period": 30, }, }
def should_not_update_cancelled_old_thing_that_can_expire_booking( self, app) -> None: book = ProductFactory(subcategoryId=subcategories.LIVRE_PAPIER.id) old_book_booking = booking_factories.CancelledIndividualBookingFactory( stock__offer__product=book) initial_cancellation_date = old_book_booking.cancellationDate handle_expired_bookings.cancel_expired_individual_bookings() assert old_book_booking.isCancelled assert old_book_booking.status is BookingStatus.CANCELLED assert old_book_booking.cancellationDate == initial_cancellation_date assert old_book_booking.cancellationReason == BookingCancellationReasons.BENEFICIARY
def should_not_cancel_old_event_booking(self, app) -> None: two_months_ago = datetime.utcnow() - timedelta(days=60) tomorrow = datetime.utcnow() + timedelta(days=1) concert = ProductFactory(type=str(offer_type.EventType.MUSIQUE)) old_concert_booking = BookingFactory(dateCreated=two_months_ago, stock__beginningDatetime=tomorrow, stock__offer__product=concert) handle_expired_bookings.cancel_expired_bookings() assert not old_concert_booking.isCancelled assert not old_concert_booking.cancellationDate assert not old_concert_booking.cancellationReason
def should_cancel_old_thing_that_can_expire_booking(self, app) -> None: now = datetime.utcnow() two_months_ago = now - timedelta(days=60) book = ProductFactory(type=str(offer_type.ThingType.LIVRE_EDITION)) old_book_booking = BookingFactory(stock__offer__product=book, dateCreated=two_months_ago) handle_expired_bookings.cancel_expired_bookings() assert old_book_booking.isCancelled assert old_book_booking.cancellationDate.timestamp() == pytest.approx( datetime.utcnow().timestamp(), rel=1) assert old_book_booking.cancellationReason == BookingCancellationReasons.EXPIRED
def test_should_mark_products_as_synchronization_compatible_via_isbn(): product_1 = ProductFactory(id=1, extraData={"isbn": "5555555555555"}, isSynchronizationCompatible=False) product_2 = ProductFactory(id=2, extraData={"isbn": "6666666666666"}, isSynchronizationCompatible=False) product_3 = ProductFactory(id=3, extraData={"isbn": "2222222222222"}, isSynchronizationCompatible=False) product_4 = ProductFactory(id=4, extraData={"isbn": "7777777777777"}, isSynchronizationCompatible=True) isbns_list = ["5555555555555", "8888888888888", "2222222222222"] bulk_update_is_synchronization_compatible_via_isbns( isbns_list, is_synchronization_compatible=True, batch_size=3) assert product_1.isSynchronizationCompatible assert not product_2.isSynchronizationCompatible assert product_3.isSynchronizationCompatible assert product_4.isSynchronizationCompatible
def should_not_cancel_old_thing_that_cannot_expire_booking(self, app) -> None: two_months_ago = datetime.utcnow() - timedelta(days=60) press_subscription = ProductFactory( type=str(offer_type.ThingType.PRESSE_ABO)) old_press_subscription_booking = BookingFactory( stock__offer__product=press_subscription, dateCreated=two_months_ago) handle_expired_bookings.cancel_expired_bookings() assert not old_press_subscription_booking.isCancelled assert not old_press_subscription_booking.cancellationDate assert not old_press_subscription_booking.cancellationReason
def should_not_cancel_old_thing_that_cannot_expire_booking(self, app) -> None: two_months_ago = datetime.utcnow() - timedelta(days=60) press_subscription = ProductFactory( subcategoryId=subcategories.ABO_PRESSE_EN_LIGNE.id) old_press_subscription_booking = booking_factories.BookingFactory( stock__offer__product=press_subscription, dateCreated=two_months_ago) handle_expired_bookings.cancel_expired_individual_bookings() assert not old_press_subscription_booking.isCancelled assert old_press_subscription_booking.status is not BookingStatus.CANCELLED assert not old_press_subscription_booking.cancellationDate assert not old_press_subscription_booking.cancellationReason
def should_not_cancel_old_event_booking(self, app) -> None: two_months_ago = datetime.utcnow() - timedelta(days=60) tomorrow = datetime.utcnow() + timedelta(days=1) concert = ProductFactory(subcategoryId=subcategories.CONCERT.id, ) old_concert_booking = booking_factories.BookingFactory( dateCreated=two_months_ago, stock__beginningDatetime=tomorrow, stock__offer__product=concert) handle_expired_bookings.cancel_expired_individual_bookings() assert not old_concert_booking.isCancelled assert old_concert_booking.status is not BookingStatus.CANCELLED assert not old_concert_booking.cancellationDate assert not old_concert_booking.cancellationReason