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", )
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
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
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]
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
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"
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
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}
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 == []
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
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
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
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]))