예제 #1
0
 def test_late_manual_payment_switched_to_automatic_is_scheduled_a_week_away(self):
     # Set up a manual donation
     alice = self.make_participant('alice', email='*****@*****.**')
     bob = self.make_participant('bob')
     alice.set_tip_to(bob, EUR('0.23'), renewal_mode=1)
     alice_sdd = self.upsert_route(alice, 'stripe-sdd')
     payin, pt = self.make_payin_and_transfer(alice_sdd, bob, EUR('0.22'), status='pending')
     self.db.run("UPDATE payin_transfers SET ctime = ctime - interval '3 weeks'")
     update_payin_transfer(self.db, pt.id, pt.remote_id, 'succeeded', None)
     # At this point we should have a manual renewal scheduled in the past
     scheduled_payins = self.db.all("SELECT * FROM scheduled_payins")
     assert len(scheduled_payins) == 1
     assert scheduled_payins[0].amount is None
     assert scheduled_payins[0].automatic is False
     payment_timedelta = scheduled_payins[0].execution_date - utcnow().date()
     assert payment_timedelta.days <= -6
     # Running the scheduler again shouldn't change anything.
     old_scheduled_payins = scheduled_payins
     alice.schedule_renewals()
     scheduled_payins = self.db.all("SELECT * FROM scheduled_payins")
     assert old_scheduled_payins == scheduled_payins
     # Turn on automatic renewals. The execution date should now be in the future.
     r = self.client.PxST("/alice/giving/", {"auto_renewal": "yes"}, auth_as=alice)
     assert r.code == 302
     tip = alice.get_tip_to(bob)
     assert tip.renewal_mode == 2
     scheduled_payins = self.db.all("SELECT * FROM scheduled_payins WHERE payin IS NULL")
     assert len(scheduled_payins) == 1
     assert scheduled_payins[0].amount == EUR('10.00')
     assert scheduled_payins[0].automatic is True
     payment_timedelta = scheduled_payins[0].execution_date - utcnow().date()
     assert payment_timedelta.days in (6, 7)
     assert scheduled_payins[0].customized is True
     assert scheduled_payins[0].last_notif_ts is None
     assert scheduled_payins[0].notifs_count == 0
예제 #2
0
 def test_newly_scheduled_automatic_payments_are_at_least_a_week_away(self):
     # Set up an automatic donation funded 4 weeks ago
     alice = self.make_participant('alice', email='*****@*****.**')
     bob = self.make_participant('bob')
     alice.set_tip_to(bob, EUR('0.23'), renewal_mode=2)
     alice_sdd = self.upsert_route(alice, 'stripe-sdd')
     payin, pt = self.make_payin_and_transfer(alice_sdd,
                                              bob,
                                              EUR('0.22'),
                                              status='pending')
     self.db.run(
         "UPDATE payin_transfers SET ctime = ctime - interval '4 weeks'")
     update_payin_transfer(self.db, pt.id, pt.remote_id, 'succeeded', None)
     # At this point we should have an automatic renewal scheduled one week from now
     scheduled_payins = self.db.all("SELECT * FROM scheduled_payins")
     assert len(scheduled_payins) == 1
     assert scheduled_payins[0].amount == EUR('10.12')
     assert scheduled_payins[0].automatic is True
     payment_timedelta = scheduled_payins[0].execution_date - utcnow().date(
     )
     assert payment_timedelta.days in (6, 7)
     assert scheduled_payins[0].customized is True
     # Running the scheduler again shouldn't change anything.
     old_scheduled_payins = scheduled_payins
     alice.schedule_renewals()
     scheduled_payins = self.db.all("SELECT * FROM scheduled_payins")
     assert old_scheduled_payins == scheduled_payins
 def make_payin_and_transfer(self,
                             route,
                             tippee,
                             amount,
                             status='succeeded',
                             error=None,
                             payer_country=None,
                             unit_amount=None,
                             period=None):
     payer = route.participant
     payin = prepare_payin(self.db, payer, amount, route)
     payin = update_payin(self.db, payin.id, 'fake', status, error)
     provider = route.network.split('-', 1)[0]
     try:
         destination = resolve_destination(self.db, tippee, provider, payer,
                                           payer_country, amount)
     except MissingPaymentAccount as e:
         destination = self.add_payment_account(e.args[0], provider)
     recipient = Participant.from_id(destination.participant)
     if tippee.kind == 'group':
         context = 'team-donation'
         team = tippee.id
     else:
         context = 'personal-donation'
         team = None
     pt = prepare_payin_transfer(self.db, payin, recipient, destination,
                                 context, amount, unit_amount, period, team)
     pt = update_payin_transfer(self.db, pt.id, 'fake', status, error)
     payer.update_giving()
     tippee.update_receiving()
     if team:
         recipient.update_receiving()
     return payin, pt
예제 #4
0
 def make_payin_and_transfer(self,
                             route,
                             tippee,
                             amount,
                             provider,
                             status='succeeded',
                             error=None,
                             payer_country=None,
                             unit_amount=None,
                             period=None):
     payer = route.participant
     payin = prepare_payin(self.db, payer, amount, route)
     payin = update_payin(self.db, payin.id, 'fake', status, error)
     destination = resolve_destination(self.db, tippee, provider, payer,
                                       payer_country, amount)
     recipient = Participant.from_id(destination.participant)
     if tippee.kind == 'group':
         context = 'team-donation'
         team = tippee
     else:
         context = 'personal-donation'
         team = None
     pt = prepare_payin_transfer(self.db, payin, recipient, destination,
                                 context, amount, unit_amount, period,
                                 team.id)
     pt = update_payin_transfer(self.db, pt.id, 'fake', status, error)
     return payin, pt
예제 #5
0
 def make_payin_and_transfer(
     self, route, tippee, amount,
     status='succeeded', error=None, payer_country=None,
     unit_amount=None, period=None
 ):
     payer = route.participant
     payin = prepare_payin(self.db, payer, amount, route)
     payin = update_payin(self.db, payin.id, 'fake', status, error)
     provider = route.network.split('-', 1)[0]
     try:
         destination = resolve_destination(
             self.db, tippee, provider, payer, payer_country, amount
         )
     except MissingPaymentAccount as e:
         destination = self.add_payment_account(e.args[0], provider)
     recipient = Participant.from_id(destination.participant)
     if tippee.kind == 'group':
         context = 'team-donation'
         team = tippee.id
     else:
         context = 'personal-donation'
         team = None
     pt = prepare_payin_transfer(
         self.db, payin, recipient, destination, context, amount,
         unit_amount, period, team
     )
     pt = update_payin_transfer(self.db, pt.id, 'fake', status, error)
     payer.update_giving()
     tippee.update_receiving()
     if team:
         recipient.update_receiving()
     return payin, pt
예제 #6
0
 def make_payin_and_transfers(
     self, route, amount, transfers,
     status='succeeded', error=None, payer_country=None, fee=None,
     remote_id='fake',
 ):
     payer = route.participant
     payin = prepare_payin(self.db, payer, amount, route)
     provider = route.network.split('-', 1)[0]
     for tippee, pt_amount, opt in transfers:
         tip = opt.get('tip')
         if tip:
             assert tip.tipper == payer.id
             assert tip.tippee == tippee.id
         else:
             tip = self.db.one("""
                 SELECT *
                   FROM current_tips
                  WHERE tipper = %s
                    AND tippee = %s
             """, (payer.id, tippee.id))
             assert tip
         for i in range(100):
             try:
                 prepare_donation(
                     self.db, payin, tip, tippee, provider, payer, payer_country, pt_amount
                 )
             except MissingPaymentAccount as e:
                 if i > 95:
                     # Infinite loop?
                     raise
                 recipient = e.args[0]
                 if recipient.kind == 'group':
                     raise
                 self.add_payment_account(recipient, provider)
             else:
                 break
     payin = update_payin(self.db, payin.id, remote_id, status, error, fee=fee)
     net_amount = payin.amount - (fee or 0)
     adjust_payin_transfers(self.db, payin, net_amount)
     payin_transfers = self.db.all("""
         SELECT *
           FROM payin_transfers
          WHERE payin = %s
       ORDER BY ctime
     """, (payin.id,))
     for tippee, pt_amount, opt in transfers:
         for i, pt in enumerate(payin_transfers):
             payin_transfers[i] = update_payin_transfer(
                 self.db, pt.id, opt.get('remote_id', 'fake'),
                 opt.get('status', status), opt.get('error', error)
             )
             if pt.team:
                 Participant.from_id(pt.recipient).update_receiving()
         tippee.update_receiving()
     payer.update_giving()
     return payin, payin_transfers
예제 #7
0
 def make_payin_and_transfers(
     self,
     route,
     amount,
     transfers,
     status='succeeded',
     error=None,
     payer_country=None,
     remote_id='fake',
 ):
     payer = route.participant
     payin = prepare_payin(self.db, payer, amount, route)
     payin = update_payin(self.db, payin.id, remote_id, status, error)
     provider = route.network.split('-', 1)[0]
     payin_transfers = []
     for tippee, pt_amount, opt in transfers:
         try:
             destination = resolve_destination(self.db, tippee, provider,
                                               payer, payer_country,
                                               pt_amount)
         except MissingPaymentAccount as e:
             destination = self.add_payment_account(e.args[0], provider)
         recipient = Participant.from_id(destination.participant)
         if tippee.kind == 'group':
             context = 'team-donation'
             team = tippee.id
         else:
             context = 'personal-donation'
             team = None
         pt = prepare_payin_transfer(self.db, payin, recipient, destination,
                                     context, pt_amount,
                                     opt.get('unit_amount'),
                                     opt.get('period'), team)
         pt = update_payin_transfer(self.db, pt.id,
                                    opt.get('remote_id', 'fake'),
                                    opt.get('status', status),
                                    opt.get('error', error))
         payin_transfers.append(pt)
         tippee.update_receiving()
         if team:
             recipient.update_receiving()
     payer.update_giving()
     return payin, payin_transfers
예제 #8
0
 def make_payin_and_transfers(
     self,
     route,
     amount,
     transfers,
     status='succeeded',
     error=None,
     payer_country=None,
     fee=None,
     remote_id='fake',
 ):
     payer = route.participant
     provider = route.network.split('-', 1)[0]
     proto_transfers = []
     net_amount = 0
     for tippee, pt_amount, opt in transfers:
         net_amount += pt_amount
         tip = opt.get('tip')
         if tip:
             assert tip.tipper == payer.id
             assert tip.tippee == tippee.id
         else:
             tip = self.db.one(
                 """
                 SELECT *
                   FROM current_tips
                  WHERE tipper = %s
                    AND tippee = %s
             """, (payer.id, tippee.id))
             assert tip
         for i in range(100):
             try:
                 proto_transfers.extend(
                     resolve_tip(self.db, tip, tippee, provider, payer,
                                 payer_country, pt_amount))
             except MissingPaymentAccount as e:
                 if i > 95:
                     # Infinite loop?
                     raise
                 recipient = e.args[0]
                 if recipient.kind == 'group':
                     raise
                 self.add_payment_account(recipient, provider)
             else:
                 break
     payin, payin_transfers = prepare_payin(self.db, payer, amount, route,
                                            proto_transfers)
     del proto_transfers
     payin = update_payin(self.db,
                          payin.id,
                          remote_id,
                          status,
                          error,
                          fee=fee)
     if len(payin_transfers) > 1:
         adjust_payin_transfers(self.db, payin, net_amount)
     else:
         pt = payin_transfers[0]
         # Call `update_payin_transfer` twice to uncover bugs
         pt = update_payin_transfer(self.db,
                                    pt.id,
                                    None,
                                    pt.status,
                                    None,
                                    amount=net_amount)
         pt = update_payin_transfer(self.db, pt.id, None, pt.status, None)
         assert pt.amount == net_amount
     payin_transfers = self.db.all(
         """
         SELECT *
           FROM payin_transfers
          WHERE payin = %s
       ORDER BY ctime
     """, (payin.id, ))
     fallback_remote_id = 'fake' if payin.status == 'succeeded' else None
     options_by_tippee = {
         tippee.id: opt
         for tippee, pt_amount, opt in transfers
     }
     for i, pt in enumerate(payin_transfers):
         opt = options_by_tippee[pt.team or pt.recipient]
         payin_transfers[i] = update_payin_transfer(
             self.db, pt.id, opt.get('remote_id', fallback_remote_id),
             opt.get('status', status), opt.get('error', error))
         if pt.team:
             Participant.from_id(pt.recipient).update_receiving()
     for tippee, pt_amount, opt in transfers:
         tippee.update_receiving()
     payer.update_giving()
     # Call `update_payin` again to uncover bugs
     payin = update_payin(self.db, payin.id, remote_id, status, error)
     return payin, payin_transfers