def test_query_performance(self, app, db_session, assert_num_queries):
        # Given
        now = datetime.utcnow()
        pro = users_factories.UserFactory(isBeneficiary=False)
        stock_1 = offers_factories.ThingStockFactory(
            dateCreated=now,
            dateModified=now,
            dateModifiedAtLastProvider=now,
            bookingLimitDatetime=now,
        )
        offer = stock_1.offer
        stock_2 = offers_factories.ThingStockFactory(
            dateCreated=now,
            dateModified=now,
            dateModifiedAtLastProvider=now,
            bookingLimitDatetime=now,
            offer=offer)
        bookings_factories.BookingFactory(stock=stock_1)
        bookings_factories.BookingFactory(stock=stock_1)
        bookings_factories.BookingFactory(stock=stock_2)
        offers_factories.UserOffererFactory(
            user=pro, offerer=offer.venue.managingOfferer)
        client = TestClient(app.test_client()).with_auth(email=pro.email)
        check_user_has_rights_queries = 2
        get_stock_queries = 1
        offer_id = offer.id

        # When
        with assert_num_queries(testing.AUTHENTICATION_QUERIES +
                                check_user_has_rights_queries +
                                get_stock_queries):
            response = client.get(f"/offers/{humanize(offer_id)}/stocks")

        # Then
        assert response.status_code == 200
    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_records_new_payment_lines_in_database(self):
        # Given
        cutoff = datetime.datetime.now()
        before_cutoff = cutoff - datetime.timedelta(days=1)

        beneficiary = users_factories.BeneficiaryGrant18Factory(
            email="*****@*****.**")
        offerer = offers_factories.OffererFactory()
        offer = offers_factories.ThingOfferFactory(
            venue__managingOfferer=offerer)
        paying_stock = offers_factories.ThingStockFactory(offer=offer)
        free_stock = offers_factories.ThingStockFactory(offer=offer, price=0)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock,
                                              dateUsed=before_cutoff)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock,
                                              dateUsed=before_cutoff)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=free_stock,
                                              dateUsed=before_cutoff)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=free_stock,
                                              dateUsed=before_cutoff)
        bookings_factories.UsedBookingFactory(user=beneficiary,
                                              stock=paying_stock,
                                              dateUsed=cutoff)

        payment_message = payments_factories.PaymentMessageFactory(
            name="ABCD123")
        payments_factories.PaymentFactory(paymentMessage=payment_message)

        initial_payment_count = Payment.query.count()

        # When
        n_queries = 1  # get_venue_ids_to_reimburse()
        n_queries += 1  # fetch custom reimbursement rules
        n_queries += 1  # find_bookings_eligible_for_payment_for_venue()
        n_queries += 1  # insert payments
        n_queries += 1  # release savepoint (commit)
        n_queries += 1  # insert PENDING payment statuses
        n_queries += 1  # release savepoint (commit)
        n_queries += 1  # insert NOT_PROCESSABLE payment statuses
        n_queries += 1  # release savepoint (commit)
        with assert_num_queries(n_queries):
            generate_new_payments(cutoff, batch_date=datetime.datetime.now())

        # Then
        assert Payment.query.count() - initial_payment_count == 2
    def test_should_not_create_educational_booking_when_offer_is_not_an_event(
            self):
        # Given
        educational_institution = educational_factories.EducationalInstitutionFactory(
        )
        educational_factories.EducationalYearFactory()
        educational_redactor = educational_factories.EducationalRedactorFactory(
            email="*****@*****.**")
        stock = offers_factories.ThingStockFactory(
            beginningDatetime=datetime.datetime(2021, 5, 15),
            offer__isEducational=True)
        redactor_informations = AuthenticatedInformation(
            email=educational_redactor.email,
            civility=educational_redactor.civility,
            firstname=educational_redactor.firstName,
            lastname=educational_redactor.lastName,
            uai=educational_institution.institutionId,
        )

        # When
        with pytest.raises(exceptions.OfferIsNotEvent) as error:
            educational_api.book_educational_offer(
                redactor_informations=redactor_informations,
                stock_id=stock.id,
            )

        # Then
        assert error.value.errors == {
            "offer":
            [f"L'offre {stock.offer.id} n'est pas une offre évènementielle"]
        }

        saved_bookings = EducationalBooking.query.join(Booking).filter(
            Booking.stockId == stock.id).all()
        assert len(saved_bookings) == 0
Example #5
0
    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
Example #6
0
    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
Example #7
0
    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,
            },
        }
Example #8
0
    def test_should_return_thing_data_when_booking_is_on_a_thing(self):
        # Given
        stock = offers_factories.ThingStockFactory()
        booking = bookings_factories.IndividualBookingFactory(
            stock=stock,
            individualBooking__user__firstName="Georges",
            individualBooking__user__lastName="Doux",
        )

        # 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": 0,
                "is_thing": 1,
                "offer_name": booking.stock.offer.name,
                "offer_price": "10.00",
                "offerer_name": booking.offerer.name,
                "user_first_name": "Georges",
                "user_last_name": "Doux",
                "venue_name": booking.venue.name,
            },
        }
    def test_should_not_allow_booking_when_educational_offer_is_not_an_event(
            self, test_data, app):
        # Given
        _, educational_institution, educational_redactor = test_data
        stock = offer_factories.ThingStockFactory(offer__isEducational=True,
                                                  beginningDatetime=stock_date)
        adage_jwt_fake_valid_token = _create_adage_valid_token_with_email(
            email=educational_redactor.email,
            uai=educational_institution.institutionId)
        test_client = TestClient(app.test_client())
        test_client.auth_header = {
            "Authorization": f"Bearer {adage_jwt_fake_valid_token}"
        }

        # When
        response = test_client.post(
            "/adage-iframe/bookings",
            json={
                "stockId": stock.id,
            },
        )

        # Then
        assert response.status_code == 400
        assert response.json == {"offer": "L'offre n'est pas un évènement"}
Example #10
0
    def test_do_not_update_if_thing_product(self):
        booking_factories.IndividualBookingFactory(stock=offers_factories.ThingStockFactory())

        api.auto_mark_as_used_after_event()

        booking = Booking.query.first()
        assert not booking.isUsed
        assert booking.status is not BookingStatus.USED
        assert not booking.dateUsed
    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
Example #12
0
    def test_returns_a_thing_stock_without_activation_codes(self, app):
        # Given
        now = datetime.utcnow()
        pro = users_factories.ProFactory()
        stock = offers_factories.ThingStockFactory(
            dateCreated=now,
            dateModified=now,
            dateModifiedAtLastProvider=now,
            bookingLimitDatetime=now,
        )
        stock_on_other_offer = offers_factories.ThingStockFactory(
            offer__venue=stock.offer.venue)
        offers_factories.UserOffererFactory(
            user=pro, offerer=stock.offer.venue.managingOfferer)
        client = TestClient(
            app.test_client()).with_session_auth(email=pro.email)

        # When
        response = client.get(f"/offers/{humanize(stock.offer.id)}/stocks")

        # Then
        assert response.status_code == 200
        assert stock_on_other_offer.id not in [
            stock["id"] for stock in response.json["stocks"]
        ]
        assert response.json == {
            "stocks": [{
                "hasActivationCodes": False,
                "activationCodesExpirationDatetime": None,
                "beginningDatetime": None,
                "bookingLimitDatetime": "2019-10-15T00:00:00Z",
                "bookingsQuantity": 0,
                "dateCreated": "2019-10-15T00:00:00Z",
                "dateModified": "2019-10-15T00:00:00Z",
                "id": humanize(stock.id),
                "isEventDeletable": True,
                "isEventExpired": False,
                "offerId": humanize(stock.offer.id),
                "price": 10.0,
                "quantity": 1000,
            }],
        }
Example #13
0
    def test_should_return_mailjet_data_on_thing_offer(
            self, mock_is_offer_active, mock_build_pc_pro_offer_link):
        # Given
        stock = offers_factories.ThingStockFactory()
        booking1 = bookings_factories.CancelledIndividualBookingFactory(
            stock=stock, quantity=2)
        booking2 = bookings_factories.IndividualBookingFactory(stock=stock,
                                                               quantity=1)

        # When
        mailjet_data = retrieve_offerer_booking_recap_email_data_after_user_cancellation(
            booking1)

        # Then
        venue = stock.offer.venue
        assert mailjet_data == {
            "MJ-TemplateID": 780015,
            "MJ-TemplateLanguage": True,
            "Vars": {
                "departement":
                venue.departementCode,
                "nom_offre":
                stock.offer.name,
                "lien_offre_pcpro":
                "http://pc_pro.com/offer_link",
                "nom_lieu":
                venue.name,
                "prix":
                f"{stock.price}",
                "is_event":
                0,
                "date":
                "",
                "heure":
                "",
                "quantite":
                booking1.quantity,
                "user_name":
                booking1.publicName,
                "user_email":
                booking1.email,
                "is_active":
                0,
                "nombre_resa":
                1,
                "users": [{
                    "contremarque": booking2.token,
                    "email": booking2.email,
                    "firstName": booking2.firstName,
                    "lastName": booking2.lastName,
                }],
            },
        }
Example #14
0
    def test_should_return_true_when_stock_is_unlimited(self, app):
        # Given
        stock = offers_factories.ThingStockFactory(offer__isActive=True,
                                                   price=0,
                                                   quantity=None)
        bookings_factories.IndividualBookingFactory(stock=stock, quantity=2)

        # When
        is_active = _is_offer_active_for_recap(stock)

        # Then
        assert is_active
Example #15
0
    def test_do_not_update_if_thing_product(self):
        # Given
        stock = offers_factories.ThingStockFactory()
        bookings_factories.BookingFactory(stock=stock)

        # When
        update_booking_used_after_stock_occurrence()

        # Then
        booking = Booking.query.first()
        assert not booking.isUsed
        assert not booking.dateUsed
Example #16
0
    def test_quantity_update_with_cancellations_exceed_quantity(self):
        # Given
        stock = factories.ThingStockFactory(quantity=2)
        bookings_factories.CancelledBookingFactory(stock=stock)
        bookings_factories.CancelledBookingFactory(stock=stock)
        bookings_factories.BookingFactory(stock=stock)
        bookings_factories.BookingFactory(stock=stock)

        # When
        stock.quantity = 3
        repository.save(stock)

        # Then
        assert Stock.query.get(stock.id).quantity == 3
    def test_should_not_return_payments_to_retry_if_no_bank_information(self, app):
        # Given
        product = offers_factories.ThingProductFactory(name="Lire un livre", isNational=True)
        venue = offers_factories.VenueFactory(postalCode="34000", departementCode="34")
        offer = offers_factories.ThingOfferFactory(product=product, venue=venue)
        stock = offers_factories.ThingStockFactory(offer=offer, price=0, quantity=2)
        booking = bookings_factories.UsedIndividualBookingFactory(stock=stock, quantity=2)
        payment = factories.PaymentFactory(booking=booking, amount=10)
        factories.PaymentStatusFactory(payment=payment, status=TransactionStatus.NOT_PROCESSABLE)

        # When
        payments_to_retry = payment_queries.find_not_processable_with_bank_information()

        # Then
        assert payments_to_retry == []
Example #18
0
    def test_should_return_false_when_stock_is_unlimited_but_booking_date_is_past(
            self, app):
        # Given
        stock = offers_factories.ThingStockFactory(
            offer__isActive=True,
            price=0,
            quantity=None,
            bookingLimitDatetime=datetime.now() - timedelta(days=6))
        bookings_factories.IndividualBookingFactory(stock=stock, quantity=2)

        # When
        is_active = _is_offer_active_for_recap(stock)

        # Then
        assert not is_active
    def test_does_not_return_soft_deleted_stock(self, app):
        # Given
        pro = users_factories.UserFactory(isBeneficiary=False)
        stock = offers_factories.ThingStockFactory(isSoftDeleted=True)
        offers_factories.UserOffererFactory(
            user=pro, offerer=stock.offer.venue.managingOfferer)
        client = TestClient(app.test_client()).with_auth(email=pro.email)

        # When
        response = client.get(f"/offers/{humanize(stock.offer.id)}/stocks")

        # Then
        assert response.status_code == 200
        assert response.json == {
            "stocks": [],
        }
Example #20
0
    def test_returns_a_thing_stock(self, app):
        # Given
        beneficiary = users_factories.UserFactory()
        stock = offers_factories.ThingStockFactory()
        offer = stock.offer

        # When
        client = TestClient(
            app.test_client()).with_auth(email=beneficiary.email)
        response = client.get(f"/offers/{humanize(offer.id)}")

        # Then
        assert response.status_code == 200
        data = response.json
        assert data["stocks"][0]["cancellationLimitDate"] is None
        assert data["offerType"]["canExpire"] is True
Example #21
0
    def test_returns_a_thing_stock(self, app):
        # Given
        beneficiary = users_factories.BeneficiaryGrant18Factory()
        stock = offers_factories.ThingStockFactory()
        offer = stock.offer
        offer.subcategoryId = subcategories.LIVRE_PAPIER.id
        repository.save(offer)

        # When
        client = TestClient(
            app.test_client()).with_session_auth(email=beneficiary.email)
        response = client.get(f"/offers/{humanize(offer.id)}")

        # Then
        assert response.status_code == 200
        data = response.json
        assert data["stocks"][0]["cancellationLimitDate"] is None
        assert data["subcategoryId"] == "LIVRE_PAPIER"
    def test_should_return_one_payment_info_with_error_status(self, app):
        # Given
        stock = offers_factories.ThingStockFactory(price=10)
        now = datetime.utcnow()
        booking = bookings_factories.UsedIndividualBookingFactory(
            stock=stock, dateUsed=now, token="ABCDEF")
        payment = payments_factories.PaymentFactory(
            booking=booking,
            transactionLabel=
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019")
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.ERROR,
                                                detail="Iban non fourni")

        # When
        payments = legacy_find_all_offerer_payments(
            stock.offer.venue.managingOfferer.id)

        # Then
        assert len(payments) == 1
        assert payments[0] == (
            "Doux",
            "Jeanne",
            None,
            None,
            "ABCDEF",
            now,
            1,
            Decimal("10.00"),
            stock.offer.name,
            "1 boulevard Poissonnière",
            stock.offer.venue.name,
            stock.offer.venue.siret,
            "1 boulevard Poissonnière",
            Decimal("10.00"),
            Decimal("1.00"),
            "CF13QSDFGH456789",
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
            TransactionStatus.ERROR,
            "Iban non fourni",
        )
    def test_should_return_payment_to_retry_if_bank_information_linked_to_offerer_and_current_status_is_not_processable(
        self, app
    ):
        # Given
        user_offerer = offers_factories.UserOffererFactory()
        product = offers_factories.ThingProductFactory(name="Lire un livre", isNational=True)
        venue = offers_factories.VenueFactory(
            managingOfferer=user_offerer.offerer, postalCode="34000", departementCode="34"
        )
        offer = offers_factories.ThingOfferFactory(product=product, venue=venue)
        stock = offers_factories.ThingStockFactory(offer=offer, price=0)
        booking = bookings_factories.UsedIndividualBookingFactory(stock=stock)
        not_processable_payment = factories.PaymentFactory(booking=booking, amount=10)
        factories.PaymentStatusFactory(payment=not_processable_payment, status=TransactionStatus.NOT_PROCESSABLE)
        offers_factories.BankInformationFactory(offerer=user_offerer.offerer)

        # When
        payments_to_retry = payment_queries.find_not_processable_with_bank_information()

        # Then
        assert not_processable_payment in payments_to_retry
def get_existing_pro_validated_user_with_validated_offerer_with_iban_validated_user_offerer_with_thing_offer_with_stock(
):
    user_offerer = offers_factories.UserOffererFactory(
        validationToken=None,
        offerer__validationToken=None,
        user__validationToken=None,
    )
    offers_factories.BankInformationFactory(offerer=user_offerer.offerer)
    venue = offers_factories.VirtualVenueFactory(
        managingOfferer=user_offerer.offerer)
    venue = offers_factories.VenueFactory(managingOfferer=user_offerer.offerer)
    offer = offers_factories.ThingOfferFactory(venue=venue, isActive=True)
    stock = offers_factories.ThingStockFactory(offer=offer)

    return {
        "offer": get_offer_helper(offer),
        "offerer": get_offerer_helper(user_offerer.offerer),
        "stock": get_stock_helper(stock),
        "user": get_pro_helper(user_offerer.user),
        "venue": get_venue_helper(venue),
    }
Example #25
0
    def test_make_offerer_driven_cancellation_email_for_offerer_thing_and_already_existing_booking(
            self, app):
        # Given
        stock = offers_factories.ThingStockFactory(price=0, quantity=10)
        booking = bookings_factories.IndividualBookingFactory(stock=stock,
                                                              token="12346")

        booking2 = bookings_factories.IndividualBookingFactory(stock=stock,
                                                               token="12345")
        ongoing_bookings = [booking2]

        # When
        with patch("pcapi.utils.mailing.find_ongoing_bookings_by_stock",
                   return_value=ongoing_bookings):
            email = make_offerer_driven_cancellation_email_for_offerer(booking)

        # Then
        venue = stock.offer.venue
        email_html = BeautifulSoup(email["Html-part"], "html.parser")
        html_action = str(email_html.find("p", {"id": "action"}))
        html_recap = email_html.find("p", {"id": "recap"}).text
        html_recap_table = email_html.find("table", {"id": "recap-table"}).text
        assert "Vous venez d'annuler" in html_action
        assert booking.publicName in html_action
        assert booking.email in html_action
        assert f"pour {stock.offer.product.name}" in html_recap
        assert f"proposé par {venue.name}" in html_recap
        assert venue.address in html_recap
        assert venue.city in html_recap
        assert venue.postalCode in html_recap
        assert booking2.firstName in html_recap_table
        assert booking2.email in html_recap_table
        assert booking.token not in html_recap_table
        assert booking2.token not in html_recap_table
        assert (
            email["Subject"] ==
            f"Confirmation de votre annulation de réservation pour {stock.offer.product.name}, proposé par {venue.name}"
        )
Example #26
0
    def test_should_set_not_processable_payments_to_retry_and_update_payments_bic_and_iban_using_offerer_information(
        self, make_transaction_label_stub
    ):
        # 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(
            amount=10,
            booking=booking,
            bic="QSDFGH8Z555",
            iban="CF13QSDFGH456789",
            transactionLabel="My old transaction label",
        )
        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()
        new_transaction_label = "My new transaction label"
        make_transaction_label_stub.return_value = new_transaction_label

        # 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 == "FR7611808009101234567890147"
        assert queried_not_processable_payment.bic == "CCBPFRPPVER"
        assert queried_not_processable_payment.batchDate == new_batch_date
        assert queried_not_processable_payment.transactionLabel == new_transaction_label
        assert queried_not_processable_payment.currentStatus.status == TransactionStatus.RETRY
        assert queried_sent_payment.currentStatus.status == TransactionStatus.SENT
    def test_should_not_return_payment_to_retry_if_bank_information_status_is_not_accepted(self, app):
        # Given
        user_offerer = offers_factories.UserOffererFactory()
        product = offers_factories.ThingProductFactory(name="Lire un livre", isNational=True)
        venue = offers_factories.VenueFactory(
            managingOfferer=user_offerer.offerer, postalCode="34000", departementCode="34"
        )
        offer = offers_factories.ThingOfferFactory(product=product, venue=venue)
        stock = offers_factories.ThingStockFactory(offer=offer, price=0)
        booking = bookings_factories.UsedIndividualBookingFactory(stock=stock)
        not_processable_payment = factories.PaymentFactory(
            booking=booking, amount=10, iban="CF13QSDFGH456789", bic="QSDFGH8Z555"
        )
        factories.PaymentStatusFactory(payment=not_processable_payment, status=TransactionStatus.NOT_PROCESSABLE)
        offers_factories.BankInformationFactory(
            offerer=user_offerer.offerer, iban=None, bic=None, status=BankInformationStatus.DRAFT
        )

        # When
        payments_to_retry = payment_queries.find_not_processable_with_bank_information()

        # Then
        assert payments_to_retry == []
Example #28
0
def test_should_return_thing_specific_data_for_email_when_offer_is_a_thing():
    stock = offers_factories.ThingStockFactory(
        price=23.99,
        offer__product__subcategoryId=subcategories.SUPPORT_PHYSIQUE_FILM.id,
        offer__name="Super bien culturel",
    )
    booking = bookings_factories.IndividualBookingFactory(stock=stock, dateCreated=datetime.utcnow())
    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_things_not_virtual_thing=1,
        event_date="",
        event_hour="",
        is_event=0,
        is_single_event=0,
        offer_name="Super bien culturel",
        can_expire=1,
        expiration_delay=30,
    )
    assert email_data == expected
Example #29
0
 def test_is_deletable_when_stock_is_not_an_event(self):
     stock = factories.ThingStockFactory()
     assert stock.isEventDeletable
Example #30
0
 def test_is_not_expired_when_stock_is_not_an_event(self):
     stock = factories.ThingStockFactory()
     assert not stock.isEventExpired