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
Пример #2
0
    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])
Пример #9
0
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
Пример #11
0
    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
Пример #13
0
    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
Пример #15
0
    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
Пример #16
0
    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
Пример #17
0
    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
Пример #19
0
    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
Пример #20
0
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
Пример #21
0
    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
Пример #25
0
    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
Пример #26
0
    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
Пример #27
0
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
Пример #28
0
    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