def test_should_return_one_payment_info_with_sent_status_when_offer_educational(
            self, app):
        # Given
        now = datetime.utcnow()
        educational_booking = bookings_factories.UsedEducationalBookingFactory(
            educationalBooking__educationalRedactor__firstName="Dominique",
            educationalBooking__educationalRedactor__lastName="Leprof",
            dateUsed=now,
            token="ABCDEF",
            quantity=5,
            amount=50,
            stock__price=10,
        )

        payment = payments_factories.PaymentFactory(
            amount=50,
            reimbursementRate=1,
            booking=educational_booking,
            iban="CF13QSDFGH456789",
            transactionLabel=
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
        )
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.ERROR,
                                                detail="Iban non fourni")
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.RETRY,
                                                detail="All good")
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.SENT,
                                                detail="All good")

        # When
        payments = find_all_offerer_payments(
            educational_booking.stock.offer.venue.managingOfferer.id,
            reimbursement_period)

        # Then
        assert len(payments) == 1
        assert payments[0] == (
            None,
            None,
            "Dominique",
            "Leprof",
            "ABCDEF",
            now,
            educational_booking.quantity,
            educational_booking.amount,
            educational_booking.stock.offer.name,
            educational_booking.stock.offer.venue.managingOfferer.address,
            educational_booking.stock.offer.venue.name,
            educational_booking.stock.offer.venue.siret,
            educational_booking.stock.offer.venue.address,
            Decimal("50.00"),
            Decimal("1.00"),
            "CF13QSDFGH456789",
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
            TransactionStatus.SENT,
            "All good",
        )
Exemplo n.º 2
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
Exemplo n.º 3
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
Exemplo n.º 4
0
def test_send_payments_report_sends_two_csv_attachments_if_some_payments_are_not_processable_and_in_error(
        app):
    # given
    iban = "CF13QSDFGH456789"
    bic = "QSDFGH8Z555"
    payment1 = payments_factories.PaymentFactory(iban=iban,
                                                 bic=bic,
                                                 statuses=[])
    payments_factories.PaymentStatusFactory(payment=payment1,
                                            status=TransactionStatus.SENT)
    payment2 = payments_factories.PaymentFactory(iban=iban,
                                                 bic=bic,
                                                 statuses=[])
    payments_factories.PaymentStatusFactory(payment=payment2,
                                            status=TransactionStatus.ERROR)
    payment3 = payments_factories.PaymentFactory(iban=iban,
                                                 bic=bic,
                                                 statuses=[])
    payments_factories.PaymentStatusFactory(
        payment=payment3, status=TransactionStatus.NOT_PROCESSABLE)
    payments = [payment1, payment2, payment3]

    # when
    send_payments_report(payments, ["*****@*****.**"])

    # then
    assert len(mails_testing.outbox) == 1
    assert len(mails_testing.outbox[0].sent_data["Attachments"]) == 2
    assert mails_testing.outbox[0].sent_data["Attachments"][0][
        "ContentType"] == "text/csv"
    assert mails_testing.outbox[0].sent_data["Attachments"][1][
        "ContentType"] == "text/csv"
    def test_with_specific_batch_date(self):
        batch_date = datetime.datetime.utcnow()
        query = payment_queries.get_payments_by_status([TransactionStatus.NOT_PROCESSABLE], batch_date)

        factories.PaymentFactory()  # not the same batch date
        assert query.count() == 0

        ps = factories.PaymentStatusFactory(status=TransactionStatus.PENDING, payment__batchDate=batch_date)
        assert query.count() == 0

        factories.PaymentStatusFactory(status=TransactionStatus.NOT_PROCESSABLE, payment=ps.payment)
        assert query.all() == [ps.payment]
Exemplo n.º 6
0
def test_send_payments_report_sends_one_csv_attachment_if_some_payments_are_not_processable():
    # given
    batch_date = datetime.datetime.now()
    payments = payments_factories.PaymentFactory.create_batch(3, statuses=[], batchDate=batch_date)
    payments_factories.PaymentStatusFactory(payment=payments[0], status=TransactionStatus.UNDER_REVIEW)
    payments_factories.PaymentStatusFactory(payment=payments[1], status=TransactionStatus.ERROR)
    payments_factories.PaymentStatusFactory(payment=payments[2], status=TransactionStatus.NOT_PROCESSABLE)

    # when
    send_payments_report(batch_date, ["*****@*****.**"])

    # then
    assert len(mails_testing.outbox) == 1
    assert len(mails_testing.outbox[0].sent_data["Attachments"]) == 1
    assert mails_testing.outbox[0].sent_data["Attachments"][0]["ContentType"] == "text/csv"
    def test_should_return_payments_from_multiple_venues(self, app):
        # Given
        offerer = OffererFactory()
        payments_factories.PaymentStatusFactory(
            payment__booking__stock__offer__venue__managingOfferer=offerer,
            status=TransactionStatus.SENT)
        payments_factories.PaymentStatusFactory(
            payment__booking__stock__offer__venue__managingOfferer=offerer,
            status=TransactionStatus.SENT)

        # When
        payments = find_all_offerer_payments(offerer.id, reimbursement_period)

        # Then
        assert len(payments) == 2
def test_with_reimbursement_period_filter(app):
    beginning_date_iso_format = (date.today() - timedelta(days=2)).isoformat()
    ending_date_iso_format = (date.today() + timedelta(days=2)).isoformat()
    user_offerer = offers_factories.UserOffererFactory()
    offerer = user_offerer.offerer
    pro = user_offerer.user
    payments_factories.PaymentStatusFactory(
        payment__booking__stock__offer__venue__managingOfferer=offerer,
        status=TransactionStatus.SENT,
        payment__transactionLabel=
        "pass Culture Pro - remboursement 1ère quinzaine 06-21",
        date=date.today() - timedelta(days=2),
    )
    payments_factories.PaymentStatusFactory(
        payment__booking__stock__offer__venue__managingOfferer=offerer,
        status=TransactionStatus.SENT,
        payment__transactionLabel=
        "pass Culture Pro - remboursement 1ère quinzaine 06-21",
        date=date.today() - timedelta(days=3),
    )
    payments_factories.PaymentStatusFactory(
        payment__booking__stock__offer__venue__managingOfferer=offerer,
        status=TransactionStatus.SENT,
        payment__transactionLabel=
        "pass Culture Pro - remboursement 1ère quinzaine 06-21",
        date=date.today() + timedelta(days=2),
    )
    payments_factories.PaymentStatusFactory(
        payment__booking__stock__offer__venue__managingOfferer=offerer,
        status=TransactionStatus.SENT,
        payment__transactionLabel=
        "pass Culture Pro - remboursement 1ère quinzaine 06-21",
        date=date.today() + timedelta(days=3),
    )

    # When
    client = TestClient(app.test_client()).with_session_auth(pro.email)
    response = client.get(
        f"/reimbursements/csv?reimbursementPeriodBeginningDate={beginning_date_iso_format}&reimbursementPeriodEndingDate={ending_date_iso_format}"
    )

    # Then
    assert response.status_code == 200
    assert response.headers["Content-type"] == "text/csv; charset=utf-8;"
    assert response.headers[
        "Content-Disposition"] == "attachment; filename=remboursements_pass_culture.csv"
    rows = response.data.decode("utf-8").splitlines()
    assert len(rows) == 1 + 2  # header + payments
Exemplo n.º 9
0
def test_send_payments_report_sends_two_csv_attachments_if_no_payments_are_in_error_or_sent(
        app):
    # given
    iban = "CF13QSDFGH456789"
    bic = "QSDFGH8Z555"
    payment1 = payments_factories.PaymentFactory(iban=iban,
                                                 bic=bic,
                                                 statuses=[])
    payment2 = payments_factories.PaymentFactory(iban=iban,
                                                 bic=bic,
                                                 statuses=[])
    for payment in (payment1, payment2):
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.SENT)
    payments = [payment1, payment2]

    # when
    send_payments_report(payments, ["*****@*****.**"])

    # then
    assert len(mails_testing.outbox) == 1
    assert len(mails_testing.outbox[0].sent_data["Attachments"]) == 2
    assert mails_testing.outbox[0].sent_data["Attachments"][0][
        "ContentType"] == "text/csv"
    assert mails_testing.outbox[0].sent_data["Attachments"][1][
        "ContentType"] == "text/csv"
Exemplo n.º 10
0
def test_generate_reimbursement_details_csv():
    # given
    payment = PaymentFactory(
        booking__stock__offer__name='Mon titre ; un peu "spécial"',
        booking__stock__offer__venue__name='Mon lieu ; un peu "spécial"',
        booking__stock__offer__venue__siret="siret-1234",
        booking__token="0E2722",
        booking__amount=10.5,
        booking__quantity=2,
        booking__dateUsed=datetime(2021, 1, 1, 12, 0),
        iban="iban-1234",
        transactionLabel=
        "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
    )
    payments_factories.PaymentStatusFactory(payment=payment,
                                            status=TransactionStatus.SENT)
    offerer = payment.booking.offerer
    reimbursement_details = find_all_offerer_reimbursement_details(
        offerer.id, reimbursement_period)

    # when
    csv = generate_reimbursement_details_csv(reimbursement_details)

    # then
    rows = csv.splitlines()
    assert (
        rows[0] ==
        '"Année";"Virement";"Créditeur";"SIRET créditeur";"Adresse créditeur";"IBAN";"Raison sociale du lieu";"Nom de l\'offre";"Nom utilisateur";"Prénom utilisateur";"Contremarque";"Date de validation de la réservation";"Montant de la réservation";"Barème";"Montant remboursé";"Statut du remboursement"'
    )
    assert (
        rows[1] ==
        '"2019";"Juillet : remboursement 1ère quinzaine";"Mon lieu ; un peu ""spécial""";"siret-1234";"1 boulevard Poissonnière";"iban-1234";"Mon lieu ; un peu ""spécial""";"Mon titre ; un peu ""spécial""";"Doux";"Jeanne";"0E2722";"2021-01-01 12:00:00";"21,00";"100%";"21,00";"Remboursement envoyé"'
    )
def test_admin_can_access_reimbursements_data_with_venue_filter(app, client):
    # Given
    beginning_date = date.today() - timedelta(days=2)
    ending_date = date.today() + timedelta(days=2)
    admin = users_factories.AdminFactory()
    user_offerer = offers_factories.UserOffererFactory()
    offerer = user_offerer.offerer
    status = payments_factories.PaymentStatusFactory(
        payment__booking__stock__offer__venue__managingOfferer=offerer,
        status=TransactionStatus.SENT,
        payment__transactionLabel=
        "pass Culture Pro - remboursement 1ère quinzaine 06-21",
        date=date.today(),
    )
    venue = status.payment.booking.venue

    # When
    admin_client = client.with_session_auth(admin.email)
    response = admin_client.get(
        "/reimbursements/csv?venueId={}&reimbursementPeriodBeginningDate={}&reimbursementPeriodEndingDate={}"
        .format(humanize(venue.id), beginning_date.isoformat(),
                ending_date.isoformat()))

    # Then
    assert response.status_code == 200
    assert response.headers["Content-type"] == "text/csv; charset=utf-8;"
    assert response.headers[
        "Content-Disposition"] == "attachment; filename=remboursements_pass_culture.csv"
    rows = response.data.decode("utf-8").splitlines()
    assert len(rows) == 2  # header + payments
Exemplo n.º 12
0
    def test_reimbursementDetail_as_csv_individual_booking(self, app):
        # given
        payment = PaymentFactory(
            transactionLabel=
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
            booking__amount=10.5,
            booking__quantity=2,
        )
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.SENT)

        payments_info = find_all_offerer_payments(payment.booking.offerer.id,
                                                  reimbursement_period)

        # when
        raw_csv = ReimbursementDetails(payments_info[0]).as_csv_row()

        # then
        assert raw_csv[0] == "2019"
        assert raw_csv[1] == "Juillet : remboursement 1ère quinzaine"
        assert raw_csv[2] == payment.booking.venue.name
        assert raw_csv[3] == payment.booking.venue.siret
        assert raw_csv[4] == payment.booking.venue.address
        assert raw_csv[5] == payment.iban
        assert raw_csv[6] == payment.booking.venue.name
        assert raw_csv[7] == payment.booking.stock.offer.name
        assert raw_csv[8] == "Doux"
        assert raw_csv[9] == "Jeanne"
        assert raw_csv[10] == payment.booking.token
        assert raw_csv[11] == payment.booking.dateUsed
        assert raw_csv[12] == "21,00"
        assert raw_csv[13] == f"{int(payment.reimbursementRate * 100)}%"
        assert raw_csv[14] == "21,00"
        assert raw_csv[15] == "Remboursement envoyé"
    def test_without_batch_date(self):
        p1 = factories.PaymentFactory()
        p2 = factories.PaymentFactory()

        query = payment_queries.get_payments_by_status([TransactionStatus.PENDING])
        assert set(query.all()) == {p1, p2}

        factories.PaymentStatusFactory(status=TransactionStatus.NOT_PROCESSABLE, payment=p2)
        query = payment_queries.get_payments_by_status([TransactionStatus.PENDING])
        assert query.all() == [p1]
        query = payment_queries.get_payments_by_status([TransactionStatus.NOT_PROCESSABLE])
        assert query.all() == [p2]
    def test_mark_payments_as_sent(self, app, db_session):
        # Given
        payment1 = payment_factories.PaymentFactory(statuses=[], transactionLabel="transaction_label")
        payment2 = payment_factories.PaymentFactory(statuses=[], transactionLabel="transaction_label")
        payment3 = payment_factories.PaymentFactory(statuses=[], transactionLabel="transaction_label")
        payment4 = payment_factories.PaymentFactory(statuses=[], transactionLabel="transaction_label")
        no_status_under_review_payment = payment_factories.PaymentFactory(
            statuses=[], transactionLabel="transaction_label"
        )
        wrong_transaction_label_payment = payment_factories.PaymentFactory(
            statuses=[], transactionLabel="wrong_transaction_label"
        )
        expected_payments_to_be_marked_as_sent = [payment1, payment2, payment3, payment4]
        expected_payments_not_to_be_marked_as_sent = [no_status_under_review_payment, wrong_transaction_label_payment]
        payment_factories.PaymentStatusFactory(payment=payment1, status=TransactionStatus.UNDER_REVIEW)
        payment_factories.PaymentStatusFactory(payment=payment1, status=TransactionStatus.PENDING)
        payment_factories.PaymentStatusFactory(payment=payment2, status=TransactionStatus.UNDER_REVIEW)
        payment_factories.PaymentStatusFactory(payment=payment3, status=TransactionStatus.UNDER_REVIEW)
        payment_factories.PaymentStatusFactory(payment=payment4, status=TransactionStatus.UNDER_REVIEW)
        payment_factories.PaymentStatusFactory(payment=no_status_under_review_payment, status=TransactionStatus.PENDING)

        # When
        mark_payments_as_sent("transaction_label", 2)

        # Then
        assert PaymentStatus.query.count() == 6 + 4
        payments_statuses_sent = PaymentStatus.query.filter(PaymentStatus.status == TransactionStatus.SENT).all()
        assert len(payments_statuses_sent) == 4
        assert set(status.payment for status in payments_statuses_sent) == set(expected_payments_to_be_marked_as_sent)
        for payment in expected_payments_to_be_marked_as_sent:
            assert payment.booking.status == BookingStatus.REIMBURSED
            assert payment.booking.reimbursementDate == payment.currentStatus.date
        for payment in expected_payments_not_to_be_marked_as_sent:
            assert payment.booking.status != BookingStatus.REIMBURSED
            assert payment.booking.reimbursementDate is None
def test_get_payment_count_by_status():
    batch_date = datetime.datetime.now()
    other_date = datetime.datetime.now()

    count = payment_queries.get_payment_count_by_status(batch_date)
    assert count == {}

    factories.PaymentStatusFactory(status=TransactionStatus.NOT_PROCESSABLE, payment__batchDate=other_date)
    count = payment_queries.get_payment_count_by_status(batch_date)
    assert count == {}

    ps = factories.PaymentStatusFactory(status=TransactionStatus.NOT_PROCESSABLE, payment__batchDate=batch_date)
    count = payment_queries.get_payment_count_by_status(batch_date)
    assert count == {"NOT_PROCESSABLE": 1}

    factories.PaymentStatusFactory(status=TransactionStatus.NOT_PROCESSABLE, payment__batchDate=batch_date)
    count = payment_queries.get_payment_count_by_status(batch_date)
    assert count == {"NOT_PROCESSABLE": 2}

    factories.PaymentStatusFactory(status=TransactionStatus.PENDING, payment=ps.payment)
    count = payment_queries.get_payment_count_by_status(batch_date)
    assert count == {"NOT_PROCESSABLE": 1, "PENDING": 1}
Exemplo n.º 16
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_return_payments_filtered_by_venue(self, app):
        # Given
        offerer = OffererFactory()
        venue_1 = VenueFactory(managingOfferer=offerer)
        venue_2 = VenueFactory(managingOfferer=offerer)

        payment_1 = payments_factories.PaymentFactory(
            booking__stock__offer__venue=venue_1)
        payments_factories.PaymentStatusFactory(payment=payment_1,
                                                status=TransactionStatus.SENT)
        payment_2 = payments_factories.PaymentFactory(
            booking__stock__offer__venue=venue_2)
        payments_factories.PaymentStatusFactory(payment=payment_2,
                                                status=TransactionStatus.SENT)

        # When
        payments = find_all_offerer_payments(offerer.id, reimbursement_period,
                                             venue_1.id)

        # Then
        assert len(payments) == 1
        assert payment_1.booking.token in payments[0]
        assert venue_1.name in payments[0]
    def test_should_return_payments_filtered_by_payment_date(self, app):
        # Given
        tomorrow_at_nine = datetime.combine(
            tomorrow, datetime.min.time()) + timedelta(hours=9)
        offerer = OffererFactory()
        venue_1 = VenueFactory(managingOfferer=offerer)
        payment_1 = payments_factories.PaymentFactory(
            booking__stock__offer__venue=venue_1)
        payments_factories.PaymentStatusFactory(date=tomorrow_at_nine,
                                                payment=payment_1,
                                                status=TransactionStatus.SENT)
        payment_2 = payments_factories.PaymentFactory(
            booking__stock__offer__venue=venue_1)
        payments_factories.PaymentStatusFactory(date=in_two_days,
                                                payment=payment_2,
                                                status=TransactionStatus.SENT)

        # When
        payments = find_all_offerer_payments(offerer.id, (today, tomorrow))

        # Then
        assert len(payments) == 1
        assert payment_1.booking.token in payments[0]
        assert venue_1.name in payments[0]
    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 == []
Exemplo n.º 20
0
def test_find_all_offerer_reimbursement_details():
    offerer = offers_factories.OffererFactory()
    venue1 = offers_factories.VenueFactory(managingOfferer=offerer)
    venue2 = offers_factories.VenueFactory(managingOfferer=offerer)
    educational_booking = booking_factories.UsedEducationalBookingFactory(
        stock__offer__venue=venue2)
    label = ("pass Culture Pro - remboursement 1ère quinzaine 07-2019", )
    payment_1 = payments_factories.PaymentFactory(
        booking__stock__offer__venue=venue1, transactionLabel=label)
    payment_2 = payments_factories.PaymentFactory(
        booking__stock__offer__venue=venue2, transactionLabel=label)
    payment_3 = payments_factories.PaymentFactory(booking=educational_booking,
                                                  transactionLabel=label)
    payments_factories.PaymentStatusFactory(payment=payment_1,
                                            status=TransactionStatus.SENT)
    payments_factories.PaymentStatusFactory(payment=payment_2,
                                            status=TransactionStatus.SENT)
    payments_factories.PaymentStatusFactory(payment=payment_3,
                                            status=TransactionStatus.SENT)

    reimbursement_details = find_all_offerer_reimbursement_details(
        offerer.id, reimbursement_period)

    assert len(reimbursement_details) == 3
Exemplo n.º 21
0
def test_send_payment_details_does_not_send_anything_if_all_payment_have_error_status(
        app):
    # given
    iban = "CF13QSDFGH456789"
    bic = "AZERTY9Q666"
    payment = payments_factories.PaymentFactory(iban=iban,
                                                bic=bic,
                                                statuses=[])
    payments_factories.PaymentStatusFactory(payment=payment,
                                            status=TransactionStatus.ERROR)

    # when
    send_payments_details([payment], ["*****@*****.**"])

    # then
    assert not mails_testing.outbox
    def test_should_not_return_payment_info_with_error_status(self, app):
        # Given
        booking = bookings_factories.UsedBookingFactory()
        offerer = booking.offerer
        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 = find_all_offerer_payments(offerer.id, reimbursement_period)

        # Then
        assert len(payments) == 0
Exemplo n.º 23
0
    def test_reimbursementDetail_with_custom_rule_as_csv(self, app):
        # given
        payment = PaymentWithCustomRuleFactory(
            transactionLabel=
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
            booking__amount=10.5,
            booking__quantity=2,
        )
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.SENT)

        payments_info = find_all_offerer_payments(payment.booking.offererId,
                                                  reimbursement_period)

        # when
        raw_csv = ReimbursementDetails(payments_info[0]).as_csv_row()

        # then
        assert raw_csv[13] == ""
    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 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 == []
def test_admin_cannot_access_reimbursements_data_without_venue_filter(
        app, client):
    # Given
    beginning_date = date.today() - timedelta(days=2)
    ending_date = date.today() + timedelta(days=2)
    admin = users_factories.AdminFactory()
    user_offerer = offers_factories.UserOffererFactory()
    offerer = user_offerer.offerer
    payments_factories.PaymentStatusFactory(
        payment__booking__stock__offer__venue__managingOfferer=offerer,
        status=TransactionStatus.SENT,
        payment__transactionLabel=
        "pass Culture Pro - remboursement 1ère quinzaine 06-21",
        date=date.today(),
    )

    # When
    admin_client = client.with_session_auth(admin.email)
    response = admin_client.get(
        "/reimbursements/csv?reimbursementPeriodBeginningDate={}&reimbursementPeriodEndingDate={}"
        .format(beginning_date.isoformat(), ending_date.isoformat()))

    # Then
    assert response.status_code == 400
Exemplo n.º 28
0
def test_generate_and_send_payments():
    # Comments below indicate what `generate_and_send_payments()` will
    # do, no what the setup does.
    cutoff = datetime.datetime.now()
    before_cutoff = cutoff - datetime.timedelta(days=1)

    # 1 new payment + 1 retried payment for venue 1
    venue1 = offers_factories.VenueFactory(name="venue1")
    offers_factories.BankInformationFactory(venue=venue1)
    booking11 = bookings_factories.UsedBookingFactory(
        dateUsed=before_cutoff, stock__offer__venue=venue1)
    booking12 = bookings_factories.UsedBookingFactory(
        dateUsed=before_cutoff, stock__offer__venue=venue1)
    payment12 = payments_factories.PaymentFactory(booking=booking12)
    payments_factories.PaymentStatusFactory(payment=payment12,
                                            status=TransactionStatus.ERROR)
    payment13 = payments_factories.PaymentFactory(
        booking__stock__offer__venue=venue1)
    payments_factories.PaymentStatusFactory(payment=payment13,
                                            status=TransactionStatus.SENT)
    bookings_factories.BookingFactory(stock__offer__venue=venue1)

    # 1 new payment for venue 2
    venue2 = offers_factories.VenueFactory(name="venue2")
    offers_factories.BankInformationFactory(offerer=venue2.managingOfferer)
    booking2 = bookings_factories.UsedBookingFactory(
        dateUsed=before_cutoff, stock__offer__venue=venue2)

    # 0 payment for venue 3 (existing booking has already been reimbursed)
    payment3 = payments_factories.PaymentFactory()
    payments_factories.PaymentStatusFactory(payment=payment3,
                                            status=TransactionStatus.SENT)

    # 1 new payment (not processable) for venue 4 (no IBAN nor BIC)
    venue4 = offers_factories.VenueFactory()
    booking4 = bookings_factories.UsedBookingFactory(
        dateUsed=before_cutoff, stock__offer__venue=venue4)

    # 0 payment for venue 5 (booking is not used)
    venue5 = offers_factories.VenueFactory()
    bookings_factories.BookingFactory(stock__offer__venue=venue5)

    # 0 payment for venue 6 (booking has been used after cutoff)
    venue6 = offers_factories.VenueFactory(name="venue2")
    offers_factories.BankInformationFactory(offerer=venue6.managingOfferer)
    bookings_factories.UsedBookingFactory(dateUsed=cutoff,
                                          stock__offer__venue=venue2)

    # 1 new payment for digital venue
    virtual_venue = offers_factories.VirtualVenueFactory()
    offers_factories.BankInformationFactory(
        offerer=virtual_venue.managingOfferer)
    digital_reimbursable_offer = offers_factories.DigitalOfferFactory(
        venue=virtual_venue,
        subcategoryId=subcategories.CINE_VENTE_DISTANCE.id)
    digital_booking = bookings_factories.UsedBookingFactory(
        dateUsed=before_cutoff, stock__offer=digital_reimbursable_offer)

    last_payment_id = Payment.query.with_entities(func.max(
        Payment.id)).scalar()
    last_status_id = PaymentStatus.query.with_entities(
        func.max(PaymentStatus.id)).scalar()

    generate_and_send_payments(cutoff)

    # Check new payments and statuses
    new_payments = Payment.query.filter(Payment.id > last_payment_id).all()
    assert set(p.booking for p in new_payments) == {
        booking11, booking2, booking4, digital_booking
    }

    new_statuses = (PaymentStatus.query.filter(
        PaymentStatus.id > last_status_id).join(
            PaymentStatus.payment).order_by(Payment.bookingId))
    assert set((s.payment.booking, s.status) for s in new_statuses) == {
        (booking11, TransactionStatus.PENDING),
        (booking11, TransactionStatus.UNDER_REVIEW),
        (booking12, TransactionStatus.UNDER_REVIEW),
        (booking2, TransactionStatus.PENDING),
        (booking2, TransactionStatus.UNDER_REVIEW),
        (booking4, TransactionStatus.NOT_PROCESSABLE),
        (digital_booking, TransactionStatus.PENDING),
        (digital_booking, TransactionStatus.UNDER_REVIEW),
    }

    # Check "transaction" e-mail
    email = mails_testing.outbox[0]
    subject = email.sent_data["Subject"].split("-")[0].strip()  # ignore date
    assert subject == "Virements XML pass Culture Pro"
    xml = base64.b64decode(
        email.sent_data["Attachments"][0]["Content"]).decode("utf-8")
    assert "<NbOfTxs>4</NbOfTxs>" in xml
    assert "<CtrlSum>40.00</CtrlSum>" in xml
    assert xml.count("<EndToEndId>") == 4

    # Check "report" e-mail
    email = mails_testing.outbox[1]
    subject = email.sent_data["Subject"].split("-")[0].strip()  # ignore date
    assert subject == "Récapitulatif des paiements pass Culture Pro"
    html = email.sent_data["Html-part"]
    assert "Nombre total de paiements : 5" in html
    assert "NOT_PROCESSABLE : 1" in html
    assert "UNDER_REVIEW : 4" in html

    # Check "details" e-mail
    email = mails_testing.outbox[2]
    subject = email.sent_data["Subject"].split("-")[0].strip()  # ignore date
    assert subject == "Détails des paiements pass Culture Pro"
    zip_data = base64.b64decode(email.sent_data["Attachments"][0]["Content"])
    with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
        csv = zf.open(zf.namelist()[0]).read().decode("utf-8")
    rows = csv.splitlines()
    assert len(rows) == 5  # header + 4 payments

    # Check "wallet balance" e-mail
    email = mails_testing.outbox[3]
    subject = email.sent_data["Subject"].split("-")[0].strip()  # ignore date
    assert subject == "Soldes des utilisateurs pass Culture"
    zip_data = base64.b64decode(email.sent_data["Attachments"][0]["Content"])
    with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
        csv = zf.open(zf.namelist()[0]).read().decode("utf-8")
    rows = csv.splitlines()
    assert len(rows) == users_models.User.query.count() + 1  # + header
    def test_should_return_last_matching_status_based_on_date_for_each_payment(
            self, app):
        # Given
        beneficiary = users_factories.BeneficiaryGrant18Factory(
            lastName="User", firstName="Plus")
        stock = offers_factories.ThingStockFactory(
            offer__name="Test Book",
            offer__venue__managingOfferer__address="7 rue du livre",
            offer__venue__name="La petite librairie",
            offer__venue__address="123 rue de Paris",
            offer__venue__siret=12345678912345,
            price=10,
        )
        now = datetime.utcnow()
        booking1 = bookings_factories.UsedIndividualBookingFactory(
            individualBooking__user=beneficiary,
            stock=stock,
            dateUsed=now,
            token="ABCDEF")
        booking2 = bookings_factories.UsedIndividualBookingFactory(
            individualBooking__user=beneficiary,
            stock=stock,
            dateUsed=now,
            token="ABCDFE")

        payment = payments_factories.PaymentFactory(
            amount=50,
            reimbursementRate=0.5,
            booking=booking1,
            iban="CF13QSDFGH456789",
            transactionLabel=
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
        )
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.RETRY,
                                                detail="Retry")
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.SENT,
                                                detail="All good")

        payment2 = payments_factories.PaymentFactory(
            amount=75,
            reimbursementRate=0.5,
            booking=booking2,
            iban="CF13QSDFGH456789",
            transactionLabel=
            "pass Culture Pro - remboursement 2ème quinzaine 07-2019",
        )
        payments_factories.PaymentStatusFactory(payment=payment2,
                                                status=TransactionStatus.ERROR,
                                                detail="Iban non fourni")
        payments_factories.PaymentStatusFactory(payment=payment2,
                                                status=TransactionStatus.SENT,
                                                detail="All realy good")

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

        # Then
        assert len(payments) == 2
        assert payments[0] == (
            "User",
            "Plus",
            None,
            None,
            "ABCDFE",
            now,
            1,
            Decimal("10.00"),
            "Test Book",
            "7 rue du livre",
            "La petite librairie",
            "12345678912345",
            "123 rue de Paris",
            Decimal("75.00"),
            Decimal("0.50"),
            "CF13QSDFGH456789",
            "pass Culture Pro - remboursement 2ème quinzaine 07-2019",
            TransactionStatus.SENT,
            "All realy good",
        )
        assert payments[1] == (
            "User",
            "Plus",
            None,
            None,
            "ABCDEF",
            now,
            1,
            Decimal("10.00"),
            "Test Book",
            "7 rue du livre",
            "La petite librairie",
            "12345678912345",
            "123 rue de Paris",
            Decimal("50.00"),
            Decimal("0.50"),
            "CF13QSDFGH456789",
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
            TransactionStatus.SENT,
            "All good",
        )
    def test_should_return_one_payment_info_with_sent_status(self, app):
        # Given
        beneficiary = users_factories.BeneficiaryGrant18Factory(
            lastName="User", firstName="Plus")
        stock = offers_factories.ThingStockFactory(
            offer__name="Test Book",
            offer__venue__managingOfferer__address="7 rue du livre",
            offer__venue__name="La petite librairie",
            offer__venue__address="123 rue de Paris",
            offer__venue__siret=12345678912345,
            price=10,
        )
        now = datetime.utcnow()
        booking = bookings_factories.UsedIndividualBookingFactory(
            individualBooking__user=beneficiary,
            stock=stock,
            dateUsed=now,
            token="ABCDEF")

        payment = payments_factories.PaymentFactory(
            amount=50,
            reimbursementRate=0.5,
            booking=booking,
            iban="CF13QSDFGH456789",
            transactionLabel=
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
        )
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.ERROR,
                                                detail="Iban non fourni")
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.RETRY,
                                                detail="All good")
        payments_factories.PaymentStatusFactory(payment=payment,
                                                status=TransactionStatus.SENT,
                                                detail="All good")

        # When
        payments = find_all_offerer_payments(
            stock.offer.venue.managingOfferer.id, reimbursement_period)

        # Then
        assert len(payments) == 1
        expected_elements = (
            "User",
            "Plus",
            "ABCDEF",
            now,
            1,
            Decimal("10.00"),
            "Test Book",
            "7 rue du livre",
            "La petite librairie",
            "12345678912345",
            "123 rue de Paris",
            Decimal("50.00"),
            Decimal("0.50"),
            "CF13QSDFGH456789",
            "pass Culture Pro - remboursement 1ère quinzaine 07-2019",
            TransactionStatus.SENT,
            "All good",
        )

        assert set(expected_elements).issubset(set(payments[0]))