Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Commit

Permalink
make get_tip_to and set_tip_to return a dict instead of only the amount
Browse files Browse the repository at this point in the history
  • Loading branch information
Changaco authored and chadwhitacre committed Sep 10, 2014
1 parent d38fe4e commit 8c89d7b
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 50 deletions.
26 changes: 14 additions & 12 deletions gratipay/models/participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -657,17 +657,18 @@ def update_is_free_rider(self, is_free_rider, cursor=None):


def set_tip_to(self, tippee, amount, update_self=True, update_tippee=True, cursor=None):
"""Given a Participant or username, and amount as str, return a tuple.
"""Given a Participant or username, and amount as str, returns a dict.

This comment has been minimized.

Copy link
@chadwhitacre

chadwhitacre Sep 10, 2014

Contributor

Why return a dict instead of just the amount? Presumably because you want to access one of the other pieces of information in the table: id, ctime, mtime, tipper, tippee. I'm not seeing any of those used in this commit, but maybe in the next? I'll keep reading ...

We INSERT instead of UPDATE, so that we have history to explore. The
COALESCE function returns the first of its arguments that is not NULL.
The effect here is to stamp all tips with the timestamp of the first
tip from this user to that. I believe this is used to determine the
order of transfers during payday.
The tuple returned is the amount as a Decimal and a boolean indicating
whether this is the first time this tipper has tipped (we want to track
that as part of our conversion funnel).
The dict returned represents the row inserted in the tips table, with
an additional boolean indicating whether this is the first time this
tipper has tipped (we want to track that as part of our conversion
funnel).
"""
assert self.is_claimed # sanity check
Expand Down Expand Up @@ -700,12 +701,12 @@ def set_tip_to(self, tippee, amount, update_self=True, update_tippee=True, curso
), CURRENT_TIMESTAMP)
, %(tipper)s, %(tippee)s, %(amount)s
)
RETURNING ( SELECT count(*) = 0 FROM tips WHERE tipper=%(tipper)s )
AS first_time_tipper
RETURNING *
, ( SELECT count(*) = 0 FROM tips WHERE tipper=%(tipper)s ) AS first_time_tipper
"""
args = dict(tipper=self.username, tippee=tippee.username, amount=amount)
first_time_tipper = (cursor or self.db).one(NEW_TIP, args)
t = (cursor or self.db).one(NEW_TIP, args)

if update_self:
# Update giving/pledging amount of tipper
Expand All @@ -720,22 +721,23 @@ def set_tip_to(self, tippee, amount, update_self=True, update_tippee=True, curso
# Update whether the tipper is using Gratipay for free
self.update_is_free_rider(None if amount == 0 else False, cursor)

return amount, first_time_tipper
return t._asdict()


def get_tip_to(self, tippee):
"""Given two user ids, return a Decimal.
"""Given a username, returns a dict.
"""
default = dict(amount=Decimal('0.00'))
return self.db.one("""\
SELECT amount
SELECT *
FROM tips
WHERE tipper=%s
AND tippee=%s
ORDER BY mtime DESC
LIMIT 1
""", (self.username, tippee), default=Decimal('0.00'))
""", (self.username, tippee), back_as=dict, default=default)


def get_tip_distribution(self):
Expand Down Expand Up @@ -1416,7 +1418,7 @@ def to_dict(self, details=False, inquirer=None):
if inquirer.username == self.username:
my_tip = 'self'
else:
my_tip = inquirer.get_tip_to(self.username)
my_tip = inquirer.get_tip_to(self.username)['amount']
output['my_tip'] = str(my_tip)

# Key: elsewhere
Expand Down
2 changes: 1 addition & 1 deletion templates/participant.tip.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ <h2>{{ _("Your Weekly Pledge") if path.decoded.startswith('/on/') else _("Your W

{% else %}

{% set my_tip = format_decimal(user.participant.get_tip_to(participant.username)) %}
{% set my_tip = format_decimal(user.participant.get_tip_to(participant.username)['amount']) %}
{% set tippee = participant.username %}
<h2>{{ _("Your Weekly Pledge") if path.decoded.startswith('/on/') else _("Your Weekly Gift") }}</h2>
{% include "templates/my-tip.html" %}
Expand Down
2 changes: 1 addition & 1 deletion tests/py/test_close.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_close_closes(self):

alice.close('downstream')

assert carl.get_tip_to('alice') == 0
assert carl.get_tip_to('alice')['amount'] == 0
assert alice.balance == 0

def test_close_raises_for_unknown_disbursement_strategy(self):
Expand Down
28 changes: 16 additions & 12 deletions tests/py/test_participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def test_bob_has_two_dollars_in_tips(self):

def test_alice_gives_to_bob_now(self):
expected = Decimal('1.00')
actual = self.alice.get_tip_to('bob')
actual = self.alice.get_tip_to('bob')['amount']
assert actual == expected

def test_deadbeef_is_archived(self):
Expand All @@ -101,12 +101,12 @@ def test_deadbeef_is_archived(self):

def test_alice_doesnt_gives_to_deadbeef_anymore(self):
expected = Decimal('0.00')
actual = self.alice.get_tip_to('deadbeef')
actual = self.alice.get_tip_to('deadbeef')['amount']
assert actual == expected

def test_alice_doesnt_give_to_whatever_deadbeef_was_archived_as_either(self):
expected = Decimal('0.00')
actual = self.alice.get_tip_to(self.deadbeef_archived.username)
actual = self.alice.get_tip_to(self.deadbeef_archived.username)['amount']
assert actual == expected

def test_there_is_no_more_deadbeef(self):
Expand Down Expand Up @@ -235,15 +235,15 @@ def test_alice_ends_up_tipping_bob_two_dollars(self):
self.alice.set_tip_to(self.carl, '1.00')
self.bob.take_over(('twitter', str(self.carl.id)), have_confirmation=True)
expected = Decimal('2.00')
actual = self.alice.get_tip_to('bob')
actual = self.alice.get_tip_to('bob')['amount']
assert actual == expected

def test_bob_ends_up_tipping_alice_two_dollars(self):
self.bob.set_tip_to(self.alice, '1.00')
self.carl.set_tip_to(self.alice, '1.00')
self.bob.take_over(('twitter', str(self.carl.id)), have_confirmation=True)
expected = Decimal('2.00')
actual = self.bob.get_tip_to('alice')
actual = self.bob.get_tip_to('alice')['amount']
assert actual == expected

def test_ctime_comes_from_the_older_tip(self):
Expand Down Expand Up @@ -374,13 +374,13 @@ def test_getting_tips_actually_made(self):
user2 = self.make_participant('user2')
self.participant.set_as_claimed()
self.participant.set_tip_to(user2, expected)
actual = self.participant.get_tip_to('user2')
actual = self.participant.get_tip_to('user2')['amount']
assert actual == expected

def test_getting_tips_not_made(self):
expected = Decimal('0.00')
self.make_participant('user2')
actual = self.participant.get_tip_to('user2')
actual = self.participant.get_tip_to('user2')['amount']
assert actual == expected


Expand Down Expand Up @@ -423,21 +423,25 @@ def test_stt_sets_tip_to(self):
bob = self.make_participant('bob')
alice.set_tip_to(bob, '1.00')

actual = alice.get_tip_to('bob')
actual = alice.get_tip_to('bob')['amount']
assert actual == Decimal('1.00')

def test_stt_returns_a_Decimal_and_a_boolean(self):
def test_stt_returns_a_dict(self):
alice = self.make_participant('alice', claimed_time='now', last_bill_result='')
bob = self.make_participant('bob')
actual = alice.set_tip_to(bob, '1.00')
assert actual == (Decimal('1.00'), True)
assert isinstance(actual, dict)
assert isinstance(actual['amount'], Decimal)
assert actual['amount'] == 1
assert actual['first_time_tipper'] is True

def test_stt_returns_False_for_second_time_tipper(self):
alice = self.make_participant('alice', claimed_time='now', last_bill_result='')
bob = self.make_participant('bob')
alice.set_tip_to(bob, '1.00')
actual = alice.set_tip_to(bob, '2.00')
assert actual == (Decimal('2.00'), False)
assert actual['amount'] == 2
assert actual['first_time_tipper'] is False

def test_stt_doesnt_allow_self_tipping(self):
alice = self.make_participant('alice', claimed_time='now', last_bill_result='')
Expand All @@ -452,7 +456,7 @@ def test_stt_allows_higher_tip_to_plural_receiver(self):
alice = self.make_participant('alice', claimed_time='now', last_bill_result='')
bob = self.make_participant('bob', number='plural')
actual = alice.set_tip_to(bob, '1000.00')
assert actual == (Decimal('1000.00'), True)
assert actual['amount'] == 1000

def test_stt_still_caps_tips_to_plural_receivers(self):
alice = self.make_participant('alice', claimed_time='now', last_bill_result='')
Expand Down
38 changes: 19 additions & 19 deletions www/%username/tip.json.spt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ from aspen import Response
from babel.numbers import NumberFormatError
from gratipay.exceptions import BadAmount, UserDoesntAcceptTips
from gratipay.models.participant import Participant
from gratipay.utils import get_participant

[-----------------------------------------------------------------------------]

Expand All @@ -18,41 +19,40 @@ if not user.ANON:
# accounts.

tipper = user.participant
tippee = Participant.from_username(path['username'])
tippee = get_participant(request, restrict=False)


# Get and maybe set amount.
# =========================

first_time_tipper = None
if tippee == tipper:
amount = None
elif POST and 'amount' in body:
if POST and 'amount' in body and tippee != tipper:
try:
amount, first_time_tipper = tipper.set_tip_to( tippee
, parse_decimal(body['amount'])
)
out = tipper.set_tip_to(tippee, parse_decimal(body['amount']))
except (InvalidOperation, ValueError, BadAmount, NumberFormatError):
raise Response(400, "bad amount")
except UserDoesntAcceptTips:
raise Response(400, "user doesn't accept tips")
else:
amount = tipper.get_tip_to(tippee.username)
out = tipper.get_tip_to(tippee.username)

amount = out['amount']
total_giving = tipper.giving
total_receiving = tipper.receiving
total_receiving_tippee = tippee.receiving

out = { "amount": str(amount)
, "total_giving": str(total_giving)
, "total_giving_l": format_currency(total_giving, 'USD')
, "total_receiving": str(total_receiving)
, "total_receiving_l": format_currency(total_receiving, 'USD')
, "total_receiving_tippee": str(total_receiving_tippee)
, "total_receiving_tippee_l": format_currency(total_receiving_tippee, 'USD')
}
if first_time_tipper is not None:
out["first_time"] = first_time_tipper
out["amount"] = str(amount)
out["amount_l"] = format_currency(amount, 'USD')
out["total_giving"] = str(total_giving)
out["total_giving_l"] = format_currency(total_giving, 'USD')
out["total_receiving"] = str(total_receiving)
out["total_receiving_l"] = format_currency(total_receiving, 'USD')
out["total_receiving_tippee"] = str(total_receiving_tippee)
out["total_receiving_tippee_l"] = format_currency(total_receiving_tippee, 'USD')
if 'ctime' in out:
out["ctime"] = str(out['ctime'])
out["mtime"] = str(out['mtime'])
else:
out["ctime"] = out["mtime"] = None


[---] application/json via json_dump
Expand Down
4 changes: 2 additions & 2 deletions www/%username/tips.json.spt
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ if POST:
try:
if tip['platform'] != 'gratipay':
raise BadPlatform
amount = participant.set_tip_to(tip['username'], parse_decimal(tip['amount']))
amount = participant.set_tip_to(tip['username'], parse_decimal(tip['amount']))['amount']
except Exception, exc:
amount = "error"
one['error'] = exc.__class__.__name__
one['amount'] = str(amount[0])
one['amount'] = str(amount)
out.append(one)

if qs.get('also_prune', 'false').lower() in ('true', '1', 'yes'):
Expand Down
2 changes: 1 addition & 1 deletion www/%username/widget.html.spt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ if user.ANON:
elif user.participant == participant:
button_text = "You!"
else:
button_text = user.participant.get_tip_to(participant.username)
button_text = user.participant.get_tip_to(participant.username)['amount']
if button_text == 0:
button_text = "Gratipay"
response.headers['X-Frame-Options'] = "ALLOWALL"
Expand Down
2 changes: 1 addition & 1 deletion www/about/pricing.spt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ title = "Pricing"

{% if not user.ANON %}
{% set p = user.participant %}
{% set payment = p.get_tip_to('Gratipay') %}
{% set payment = p.get_tip_to('Gratipay')['amount'] %}

<div class="payment">
{% if payment > 0 %}
Expand Down
2 changes: 1 addition & 1 deletion www/on/%platform/%user_name/%endpoint.json.spt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ if not user.ANON:
if user.participant.username == participant.username:
my_tip = "self"
else:
my_tip = user.participant.get_tip_to(participant.username)
my_tip = user.participant.get_tip_to(participant.username)['amount']
out["my_tip"] = str(my_tip)


Expand Down

0 comments on commit 8c89d7b

Please sign in to comment.