Beispiel #1
0
 def test_stt_doesnt_allow_self_tipping(self):
     alice = self.make_participant('alice')
     with pytest.raises(NoSelfTipping):
         alice.set_tip_to(alice, EUR('10.00'))
Beispiel #2
0
 def test_payout_quarantine(self, gba):
     self.make_exchange('mango-cc', 39, 0, self.homer)
     gba.return_value = self.bank_account
     with mock.patch.multiple(transactions, QUARANTINE='1 month'):
         with self.assertRaises(NotEnoughWithdrawableMoney):
             payout(self.db, self.homer_route, EUR('32.00'))
 def test_parsing_currency_amount(self):
     expected = EUR('1.23')
     actual = self.db.one("SELECT %s", (expected, ))
     assert expected == actual
Beispiel #4
0
 def test_record_exchange_fails_if_negative_balance(self):
     with pytest.raises(NegativeBalance):
         record_exchange(self.db, self.homer_route, EUR("-10.00"),
                         EUR("0.41"), EUR(0), self.homer, 'pre')
Beispiel #5
0
 def test_payout_no_route(self):
     self.make_exchange('mango-cc', 20, 0, self.david)
     with self.assertRaises(AssertionError):
         payout(self.db, None, EUR('1.00'))
Beispiel #6
0
 def test_upcharge_at_target(self):
     actual = upcharge_card(PAYIN_CARD_TARGET['EUR'])
     expected = (EUR('94.19'), EUR('2.19'), EUR('0.32'))
     assert actual == expected
     assert actual[1] / actual[0] < EUR('0.024')  # less than 2.4% fee
Beispiel #7
0
 def test_skim_credit(self):
     actual = skim_credit(EUR('10.00'), self.bank_account)
     assert actual == (EUR('10.00'), EUR('0.00'), EUR('0.00'))
Beispiel #8
0
 def test_schedule_renewals_finds_partial_matches(self):
     """
     This test is designed to hit the `find_partial_match` function inside
     `Participant.schedule_renewals`.
     """
     alice = self.make_participant('alice', email='*****@*****.**')
     bob = self.make_participant('bob', email='*****@*****.**')
     team = self.make_participant('team',
                                  kind='group',
                                  email='*****@*****.**')
     team.add_member(bob)
     alice.set_tip_to(bob, EUR('1.00'), renewal_mode=2)
     alice.set_tip_to(team, EUR('1.50'), renewal_mode=2)
     alice_card = self.upsert_route(alice,
                                    'stripe-card',
                                    address='pm_card_visa')
     self.make_payin_and_transfer(alice_card, bob, EUR('2.00'))
     self.make_payin_and_transfer(alice_card, team, EUR('3.00'))
     new_schedule = alice.schedule_renewals()
     next_payday = compute_next_payday_date()
     expected_transfers = [{
         'tippee_id': bob.id,
         'tippee_username': '******',
         'amount': EUR('2.00'),
     }, {
         'tippee_id': team.id,
         'tippee_username': '******',
         'amount': EUR('3.00'),
     }]
     assert len(new_schedule) == 1
     assert new_schedule[0].amount == EUR('5.00')
     assert new_schedule[0].transfers == expected_transfers
     expected_renewal_date = next_payday + timedelta(weeks=1)
     assert new_schedule[0].execution_date == expected_renewal_date
     assert new_schedule[0].automatic is True
     # Trigger the initial "upcoming charge" notification
     self.db.run(
         "UPDATE scheduled_payins SET ctime = ctime - interval '12 hours'")
     send_upcoming_debit_notifications()
     emails = self.get_emails()
     assert len(emails) == 1
     assert emails[0]['to'][0] == 'alice <*****@*****.**>'
     assert emails[0][
         'subject'] == 'Liberapay donation renewal: upcoming debit of €5.00'
     sp = self.db.one("SELECT * FROM scheduled_payins WHERE payin IS NULL")
     assert sp.notifs_count == 1
     # Tweak the amount of the first donation. The renewal shouldn't be
     # pushed back and the payer shouldn't be notified.
     alice.set_tip_to(bob, EUR('0.50'))
     new_schedule = alice.schedule_renewals()
     assert len(new_schedule) == 1
     assert new_schedule[0].amount == EUR('5.00')
     assert new_schedule[0].transfers == expected_transfers
     assert new_schedule[0].execution_date == expected_renewal_date
     assert new_schedule[0].automatic is True
     emails = self.get_emails()
     assert not emails
     # Stop the second donation. The renewal should be rescheduled and the
     # payer should be notified of that change.
     alice.stop_tip_to(team)
     new_schedule = alice.schedule_renewals()
     assert len(new_schedule) == 1
     assert new_schedule[0].amount == EUR('2.00')
     assert new_schedule[0].transfers == [expected_transfers[0]]
     previous_renewal_date = expected_renewal_date
     expected_renewal_date = next_payday + timedelta(weeks=3)
     assert new_schedule[0].execution_date == expected_renewal_date
     assert new_schedule[0].automatic is True
     emails = self.get_emails()
     assert len(emails) == 1
     assert emails[0]['to'][0] == 'alice <*****@*****.**>'
     assert emails[0][
         'subject'] == 'Liberapay donation renewal: your upcoming payment has changed'
     expected_sentence = LOCALE_EN.format(
         "The payment of €5.00 scheduled for {old_date} has been replaced by "
         "a payment of €2.00 on {new_date}.",
         old_date=previous_renewal_date,
         new_date=expected_renewal_date)
     assert expected_sentence in emails[0]['text']
Beispiel #9
0
 def test_get_tip_distribution_handles_no_tips(self):
     expected = ([], 0.0, EUR('0.00'))
     actual = self.alice.get_tip_distribution()
     assert actual == expected
Beispiel #10
0
 def test_pledging_isnt_giving(self):
     alice = self.make_participant('alice', balance=EUR(100))
     bob = self.make_elsewhere('github', 58946, 'bob').participant
     alice.set_tip_to(bob, EUR('3.00'))
     assert alice.giving == EUR('0.00')
Beispiel #11
0
 def test_cross_tip_doesnt_become_self_tip(self):
     alice = self.make_participant('alice', elsewhere='twitter')
     bob = self.make_elsewhere('twitter', 2, 'bob')
     alice.set_tip_to(bob.participant, EUR('1.00'))
     alice.take_over(bob, have_confirmation=True)
     self.db.self_check()
Beispiel #12
0
 def test_cant_pledge_to_locked_accounts(self):
     alice = self.make_participant('alice')
     bob = self.make_stub(goal=EUR(-1))
     with self.assertRaises(UserDoesntAcceptTips):
         alice.set_tip_to(bob, EUR('3.00'))
Beispiel #13
0
    def test_only_funded_tips_count(self):
        alice = self.make_participant('alice')
        bob = self.make_participant('bob')
        carl = self.make_participant('carl')
        dana = self.make_participant('dana')
        alice_card = self.upsert_route(alice, 'stripe-card')
        alice.set_tip_to(dana, EUR('3.00'))
        self.make_payin_and_transfer(alice_card, dana, EUR('15.00'))
        alice.set_tip_to(bob, EUR('6.00'))
        self.make_payin_and_transfer(alice_card, bob, EUR('30.00'))
        bob.set_tip_to(alice, EUR('5.00'))
        bob.set_tip_to(dana, EUR('2.00'))
        carl.set_tip_to(dana, EUR('2.08'))

        assert alice.giving == EUR('9.00')
        assert alice.receiving == EUR('0.00')
        assert bob.giving == EUR('0.00')
        assert bob.receiving == EUR('6.00')
        assert carl.giving == EUR('0.00')
        assert carl.receiving == EUR('0.00')
        assert dana.receiving == EUR('3.00')
        assert dana.npatrons == 1

        funded_tips = self.db.all(
            "SELECT amount FROM tips WHERE is_funded ORDER BY id")
        assert funded_tips == [3, 6]
Beispiel #14
0
 def test_stt_fails_to_tip_unknown_people(self):
     alice = self.make_participant('alice')
     with pytest.raises(NoTippee):
         alice.set_tip_to('bob', EUR('1.00'))
Beispiel #15
0
 def test_upcharge_full_in_rounded_case(self):
     actual = upcharge_card(EUR('5.00'))
     expected = upcharge_card(PAYIN_CARD_MIN['EUR'])
     assert actual == expected
Beispiel #16
0
 def test_get_tip_distribution_handles_multiple_tips(self):
     self.alice.set_tip_to(self.bob, EUR('1.00'))
     self.make_payin_and_transfer(self.alice_card, self.bob, EUR('8.00'))
     carl = self.make_participant('carl')
     carl_card = self.upsert_route(carl, 'stripe-card')
     carl.set_tip_to(self.bob, EUR('3.00'))
     self.make_payin_and_transfer(carl_card, self.bob, EUR('3.00'))
     expected = ([
         [EUR('1.00'), 1, EUR('1.00'), EUR('1.00'), 0.5, Decimal('0.25')],
         [EUR('3.00'), 1, EUR('3.00'), EUR('3.00'), 0.5, Decimal('0.75')]
     ], 2, EUR('4.00'))
     actual = self.bob.get_tip_distribution()
     assert actual == expected
Beispiel #17
0
 def test_upcharge_at_min(self):
     actual = upcharge_card(PAYIN_CARD_MIN['EUR'])
     expected = (EUR('15.54'), EUR('0.54'), EUR('0.08'))
     assert actual == expected
     assert actual[1] / actual[0] < EUR('0.035')  # less than 3.5% fee
Beispiel #18
0
 def test_get_tip_distribution_ignores_old_or_nonfunded_tip(self):
     self.alice.set_tip_to(self.bob, EUR('3.00'))  # funded
     self.alice.set_tip_to(self.bob, EUR('100.00'))  # not funded
     expected = ([], 0, EUR('0.00'))
     actual = self.bob.get_tip_distribution()
     assert actual == expected
Beispiel #19
0
 def test_upcharge_at_min_minus_one_cent(self):
     actual = upcharge_card(PAYIN_CARD_MIN['EUR'] - EUR('0.01'))
     expected = upcharge_card(PAYIN_CARD_MIN['EUR'])
     assert actual == expected
Beispiel #20
0
 def test_payout_during_payday(self):
     self.make_exchange('mango-cc', 200, 0, self.homer)
     Payday.start()
     with self.assertRaises(PaydayIsRunning):
         payout(self.db, self.homer_route, EUR('97.35'))
Beispiel #21
0
 def test_skim_credit_outside_sepa(self):
     actual = skim_credit(EUR('10.00'), self.bank_account_outside_sepa)
     assert actual == (EUR('7.07'), EUR('2.93'), EUR('0.43'))
Beispiel #22
0
 def test_charge_bad_card(self):
     self.janet_route.set_attributes(address='-1')
     exchange = charge(self.db, self.janet_route, EUR('10.00'),
                       'http://localhost/')
     assert exchange.note.startswith(
         'The value -1 is not valid (CardId) | Error ID: ')
Beispiel #23
0
 def test_payout_amount_under_minimum(self, gba):
     self.make_exchange('mango-cc', 8, 0, self.homer)
     gba.return_value = self.bank_account_outside_sepa
     with self.assertRaises(FeeExceedsAmount):
         payout(self.db, self.homer_route, EUR('0.10'))
Beispiel #24
0
 def test_charge_no_card(self):
     with self.assertRaises(AssertionError):
         charge(self.db, None, EUR('10.00'), 'http://localhost/')
Beispiel #25
0
 def test_payout_invalidated_bank_account(self):
     self.make_exchange('mango-cc', 20, 0, self.homer)
     self.homer_route.invalidate()
     with self.assertRaises(AssertionError):
         payout(self.db, self.homer_route, EUR('10.00'))
Beispiel #26
0
 def test_direct_debit_form(self):
     path = b'/janet/wallet/payin/direct-debit'
     self.janet.set_tip_to(self.david, EUR('10.00'))
     r = self.client.GET(path, auth_as=self.janet)
     assert r.code == 200
Beispiel #27
0
 def test_close_raises_for_unknown_disbursement_strategy(self):
     alice = self.make_participant('alice', balance=EUR('0.00'))
     with pytest.raises(alice.UnknownDisbursementStrategy):
         alice.close('cheese')
Beispiel #28
0
 def test_upcharge_basically_works(self):
     actual = upcharge_card(EUR('20.00'))
     expected = (EUR('20.65'), EUR('0.65'), EUR('0.10'))
     assert actual == expected
 def test_sorting(self):
     amounts = [JPY('130'), EUR('99.58'), Money('79', 'KRW'), USD('35.52')]
     expected = sorted(amounts, key=lambda m: -m.convert('EUR').amount)
     actual = self.db.all("SELECT x FROM unnest(%s) x ORDER BY x DESC",
                          (amounts, ))
     assert expected == actual
Beispiel #30
0
 def test_stt_sets_tip_to(self):
     alice = self.make_participant('alice')
     bob = self.make_stub()
     alice.set_tip_to(bob, EUR('1.00'))
     actual = alice.get_tip_to(bob).amount
     assert actual == EUR('1.00')