def test_delete_cascade_venue_should_remove_bank_informations_of_venue(): # Given venue_to_delete = offers_factories.VenueFactory() offers_factories.BankInformationFactory(venue=venue_to_delete) offers_factories.BankInformationFactory() # When delete_cascade_venue_by_id(venue_to_delete.id) # Then assert Venue.query.count() == 0 assert Offerer.query.count() == 1 assert BankInformation.query.count() == 1
def test_venues_with_rejected_and_accepted_bank_information(self): offerer = offerers_factories.OffererFactory() offers_factories.VirtualVenueFactory(managingOfferer=offerer) venue_with_rejected_bank_information = offers_factories.VenueFactory(managingOfferer=offerer) offers_factories.BankInformationFactory( venue=venue_with_rejected_bank_information, status=BankInformationStatus.REJECTED ) venue_with_rejected_bank_information = offers_factories.VenueFactory(managingOfferer=offerer) offers_factories.BankInformationFactory( venue=venue_with_rejected_bank_information, status=BankInformationStatus.ACCEPTED ) assert has_physical_venue_without_draft_or_accepted_bank_information(offerer_id=offerer.id)
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_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_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_venue_with_draft_bank_information(self): offerer = offerers_factories.OffererFactory() offers_factories.VirtualVenueFactory(managingOfferer=offerer) venue = offers_factories.VenueFactory(managingOfferer=offerer) offers_factories.BankInformationFactory(venue=venue, status=BankInformationStatus.DRAFT) assert not has_physical_venue_without_draft_or_accepted_bank_information(offerer_id=offerer.id)
def test_use_iban_and_bic_from_venue(self): booking = bookings_factories.IndividualBookingFactory() offers_factories.BankInformationFactory(venue=booking.venue, iban="iban1", bic="bic1") offers_factories.BankInformationFactory(offerer=booking.offerer, iban="iban2", bic="bic2") reimbursement = BookingReimbursement(booking, PhysicalOffersReimbursement(), Decimal(10)) batch_date = datetime.utcnow() payment = create_payment_for_booking(reimbursement, batch_date) assert payment.iban == "IBAN1" assert payment.bic == "BIC1"
def test_use_custom_reimbursement_rule_with_rate(self): booking = bookings_factories.UsedBookingFactory(amount=10, quantity=2) offerer = booking.offerer rule = payments_factories.CustomReimbursementRuleFactory( offerer=booking.offerer, rate=0.8) offers_factories.BankInformationFactory(offerer=offerer, iban="iban1", bic="bic1") cutoff = batch_date = datetime.datetime.now() generate_new_payments(cutoff, batch_date) payment = Payment.query.one() assert payment.amount == 16 # 2 (quantity) * 0.8 (rate) * 10 (amount) assert payment.customReimbursementRule == rule assert payment.reimbursementRate == Decimal("0.8")
def get_existing_pro_validated_user_with_validated_offerer_with_iban_validated_user_offerer_with_event_offer_with_no_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) offer = offers_factories.EventOfferFactory(venue=venue, isActive=True) return { "offer": get_offer_helper(offer), "offerer": get_offerer_helper(user_offerer.offerer), "user": get_pro_helper(user_offerer.user), "venue": get_venue_helper(venue), }
def test_use_custom_reimbursement_rule_with_amount(self): offer = offers_factories.DigitalOfferFactory() offers_factories.BankInformationFactory(venue=offer.venue, iban="iban1", bic="bic1") bookings_factories.UsedBookingFactory(amount=10, quantity=2, stock__offer=offer) rule = payments_factories.CustomReimbursementRuleFactory(offer=offer, amount=7) cutoff = batch_date = datetime.datetime.now() generate_new_payments(cutoff, batch_date) payment = Payment.query.one() assert payment.amount == 14 # 2 (booking.quantity) * 7 (Rule.amount) assert payment.customReimbursementRule == rule assert payment.reimbursementRate is None
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
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_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 == []
def when_user_has_rights_on_managing_offerer(self, app): # given user_offerer = offers_factories.UserOffererFactory( user__email="*****@*****.**") venue = offers_factories.VenueFactory( name="L'encre et la plume", managingOfferer=user_offerer.offerer) bank_information = offers_factories.BankInformationFactory(venue=venue) expected_serialized_venue = { "address": venue.address, "audioDisabilityCompliant": venue.audioDisabilityCompliant, "bic": bank_information.bic, "bookingEmail": venue.bookingEmail, "city": venue.city, "contact": { "email": venue.contact.email, "website": venue.contact.website, "phoneNumber": venue.contact.phone_number, "socialMedias": venue.contact.social_medias, }, "comment": venue.comment, "dateCreated": format_into_utc_date(venue.dateCreated), "dateModifiedAtLastProvider": format_into_utc_date(venue.dateModifiedAtLastProvider), "demarchesSimplifieesApplicationId": str(venue.demarchesSimplifieesApplicationId), "departementCode": venue.departementCode, "description": venue.description, "fieldsUpdated": venue.fieldsUpdated, "iban": bank_information.iban, "id": humanize(venue.id), "idAtProviders": venue.idAtProviders, "isValidated": venue.isValidated, "isVirtual": venue.isVirtual, "latitude": float(venue.latitude), "lastProviderId": venue.lastProviderId, "longitude": float(venue.longitude), "managingOfferer": { "address": venue.managingOfferer.address, "bic": venue.managingOfferer.bic, "city": venue.managingOfferer.city, "dateCreated": format_into_utc_date(venue.managingOfferer.dateCreated), "dateModifiedAtLastProvider": format_into_utc_date( venue.managingOfferer.dateModifiedAtLastProvider), "demarchesSimplifieesApplicationId": venue.managingOfferer.demarchesSimplifieesApplicationId, "fieldsUpdated": venue.managingOfferer.fieldsUpdated, "iban": venue.managingOfferer.iban, "id": humanize(venue.managingOfferer.id), "idAtProviders": venue.managingOfferer.idAtProviders, "isValidated": venue.managingOfferer.isValidated, "lastProviderId": venue.managingOfferer.lastProviderId, "name": venue.managingOfferer.name, "postalCode": venue.managingOfferer.postalCode, "siren": venue.managingOfferer.siren, }, "managingOffererId": humanize(venue.managingOffererId), "mentalDisabilityCompliant": venue.mentalDisabilityCompliant, "motorDisabilityCompliant": venue.motorDisabilityCompliant, "name": venue.name, "postalCode": venue.postalCode, "publicName": venue.publicName, "siret": venue.siret, "venueLabelId": humanize(venue.venueLabelId), "venueTypeId": humanize(venue.venueTypeId), "visualDisabilityCompliant": venue.visualDisabilityCompliant, "withdrawalDetails": None, } # when auth_request = TestClient( app.test_client()).with_session_auth(email=user_offerer.user.email) response = auth_request.get("/venues/%s" % humanize(venue.id)) # then assert response.status_code == 200 assert response.json == expected_serialized_venue
def test_returns_an_event_stock(self, app): # Given now = datetime.utcnow() beneficiary = users_factories.BeneficiaryGrant18Factory() stock = offers_factories.EventStockFactory( dateCreated=now, dateModified=now, dateModifiedAtLastProvider=now, beginningDatetime=now + timedelta(hours=1), bookingLimitDatetime=now + timedelta(hours=1), offer__dateCreated=now, offer__dateModifiedAtLastProvider=now, offer__bookingEmail="*****@*****.**", offer__name="Derrick", offer__description="Tatort, but slower", offer__durationMinutes=60, offer__mentalDisabilityCompliant=True, offer__externalTicketOfficeUrl="http://example.net", offer__product__name="Derrick", offer__product__description="Tatort, but slower", offer__product__durationMinutes=60, offer__product__dateModifiedAtLastProvider=now, offer__venue__siret="12345678912345", offer__venue__name="La petite librairie", offer__venue__dateCreated=now, offer__venue__dateModifiedAtLastProvider=now, offer__venue__bookingEmail="*****@*****.**", offer__venue__managingOfferer__dateCreated=now, offer__venue__managingOfferer__dateModifiedAtLastProvider=now, offer__venue__managingOfferer__siren="123456789", offer__venue__managingOfferer__name="Test Offerer", ) offer = stock.offer venue = offer.venue offerer = venue.managingOfferer offers_factories.BankInformationFactory(venue=venue) # 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 assert response.json == { "activeMediation": None, "ageMax": None, "ageMin": None, "bookingEmail": "*****@*****.**", "conditions": None, "dateCreated": "2020-10-15T00:00:00Z", "dateModifiedAtLastProvider": "2020-10-15T00:00:00Z", "dateRange": ["2020-10-15T01:00:00Z", "2020-10-15T01:00:00Z"], "description": "Tatort, but slower", "durationMinutes": 60, "extraData": None, "externalTicketOfficeUrl": "http://example.net", "fieldsUpdated": [], "hasBookingLimitDatetimesPassed": False, "id": humanize(stock.offer.id), "idAtProviders": None, "isActive": True, "audioDisabilityCompliant": False, "mentalDisabilityCompliant": True, "motorDisabilityCompliant": False, "visualDisabilityCompliant": False, "isBookable": True, "isDigital": False, "isDuo": False, "isEducational": False, "isEditable": True, "isEvent": True, "isNational": False, "isThing": False, "lastProvider": None, "lastProviderId": None, "mediaUrls": [], "mediations": [], "name": "Derrick", "nonHumanizedId": stock.offer.id, "product": { "ageMax": None, "ageMin": None, "conditions": None, "dateModifiedAtLastProvider": "2020-10-15T00:00:00Z", "description": "Tatort, but slower", "durationMinutes": 60, "extraData": None, "fieldsUpdated": [], "id": humanize(stock.offer.product.id), "idAtProviders": None, "isGcuCompatible": True, "isNational": False, "lastProviderId": None, "mediaUrls": [], "name": "Derrick", "owningOffererId": None, "thumbCount": 0, "url": None, }, "productId": humanize(stock.offer.product.id), "status": "ACTIVE", "stocks": [{ "beginningDatetime": "2020-10-15T01:00:00Z", "bookingLimitDatetime": "2020-10-15T01:00:00Z", "bookingsQuantity": 0, "cancellationLimitDate": "2020-10-15T00:00:00Z", "dateCreated": "2020-10-15T00:00:00Z", "dateModified": "2020-10-15T00:00:00Z", "dateModifiedAtLastProvider": "2020-10-15T00:00:00Z", "fieldsUpdated": [], "hasActivationCode": False, "id": humanize(stock.id), "idAtProviders": None, "isBookable": True, "isEventDeletable": True, "isEventExpired": False, "isSoftDeleted": False, "lastProviderId": None, "offerId": humanize(stock.offer.id), "price": 10.0, "quantity": 1000, "remainingQuantity": 1000, }], "subcategoryId": "SEANCE_CINE", "thumbUrl": None, "url": None, "venue": { "address": "1 boulevard Poissonnière", "audioDisabilityCompliant": False, "bookingEmail": "*****@*****.**", "city": "Paris", "comment": None, "dateCreated": "2020-10-15T00:00:00Z", "dateModifiedAtLastProvider": "2020-10-15T00:00:00Z", "departementCode": "75", "fieldsUpdated": [], "id": humanize(venue.id), "idAtProviders": None, "isValidated": True, "isVirtual": False, "lastProviderId": None, "latitude": 48.87004, "longitude": 2.37850, "managingOfferer": { "address": "1 boulevard Poissonnière", "city": "Paris", "dateCreated": "2020-10-15T00:00:00Z", "dateModifiedAtLastProvider": "2020-10-15T00:00:00Z", "fieldsUpdated": [], "id": humanize(offerer.id), "idAtProviders": None, "isActive": True, "isValidated": True, "lastProviderId": None, "name": "Test Offerer", "postalCode": "75000", "siren": "123456789", "thumbCount": 0, }, "managingOffererId": humanize(offerer.id), "mentalDisabilityCompliant": False, "motorDisabilityCompliant": False, "name": "La petite librairie", "postalCode": "75000", "publicName": "La petite librairie", "siret": "12345678912345", "thumbCount": 0, "venueLabelId": None, "venueTypeId": None, "visualDisabilityCompliant": False, }, "venueId": humanize(venue.id), "withdrawalDetails": None, }
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_when_user_has_rights_on_offerer(self, app): pro = users_factories.ProFactory() offerer = offers_factories.OffererFactory() offers_factories.UserOffererFactory(user=pro, offerer=offerer) venue_1 = offers_factories.VenueFactory( managingOfferer=offerer, withdrawalDetails="Venue withdrawal details") offers_factories.OfferFactory(venue=venue_1) venue_2 = offers_factories.VenueFactory( managingOfferer=offerer, withdrawalDetails="Other venue withdrawal details") offers_factories.VenueFactory( managingOfferer=offerer, withdrawalDetails="More venue withdrawal details") ApiKeyFactory(offerer=offerer, prefix="testenv_prefix") ApiKeyFactory(offerer=offerer, prefix="testenv_prefix2") offers_factories.BankInformationFactory(venue=venue_1, applicationId=2, status="REJECTED") offers_factories.BankInformationFactory(venue=venue_1, applicationId=3) offers_factories.BankInformationFactory(venue=venue_2, applicationId=4) client = TestClient(app.test_client()).with_session_auth(pro.email) n_queries = ( testing.AUTHENTICATION_QUERIES + 1 # check_user_has_access_to_offerer + 1 # Offerer api_key prefix + 1 # Offerer hasDigitalVenueAtLeastOneOffer + 1 # Offerer BankInformation + 1 # Offerer hasMissingBankInformation ) with testing.assert_num_queries(n_queries): response = client.get(f"/offerers/{humanize(offerer.id)}") expected_serialized_offerer = { "address": offerer.address, "apiKey": { "maxAllowed": 5, "prefixes": ["testenv_prefix", "testenv_prefix2"] }, "bic": None, "iban": None, "city": offerer.city, "dateCreated": format_into_utc_date(offerer.dateCreated), "dateModifiedAtLastProvider": format_into_utc_date(offerer.dateModifiedAtLastProvider), "demarchesSimplifieesApplicationId": None, "hasDigitalVenueAtLeastOneOffer": False, "fieldsUpdated": offerer.fieldsUpdated, "hasMissingBankInformation": True, "id": humanize(offerer.id), "idAtProviders": offerer.idAtProviders, "isValidated": offerer.isValidated, "lastProviderId": offerer.lastProviderId, "managedVenues": [{ "audioDisabilityCompliant": False, "address": offererVenue.address, "bookingEmail": offererVenue.bookingEmail, "city": offererVenue.city, "comment": offererVenue.comment, "departementCode": offererVenue.departementCode, "id": humanize(offererVenue.id), "isValidated": offererVenue.isValidated, "isVirtual": offererVenue.isVirtual, "managingOffererId": humanize(offererVenue.managingOffererId), "mentalDisabilityCompliant": False, "motorDisabilityCompliant": False, "name": offererVenue.name, "postalCode": offererVenue.postalCode, "publicName": offererVenue.publicName, "venueLabelId": humanize(offererVenue.venueLabelId), "venueTypeId": humanize(offererVenue.venueTypeId), "visualDisabilityCompliant": False, "withdrawalDetails": offererVenue.withdrawalDetails, } for offererVenue in offerer.managedVenues], "name": offerer.name, "postalCode": offerer.postalCode, "siren": offerer.siren, } assert response.status_code == 200 assert response.json == expected_serialized_offerer