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

second step of 835 for payment_instructions #4061

Merged
merged 2 commits into from
Jun 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 18 additions & 11 deletions gratipay/billing/payday.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,14 +399,21 @@ def update_stats(self):

-- Participants who have either received/given money

SELECT participant, team, amount, direction FROM payments WHERE payday = %(payday)s
SELECT p.id as participant_id
, t.id as team_id
, amount
, direction
FROM payments
JOIN participants p ON p.username = payments.participant
JOIN teams t ON t.slug = payments.team
WHERE payday = %(payday)s

UNION

-- Participants who weren't charged due to amount + due < MINIMUM_CHARGE

SELECT payload->>'participant' AS participant
, payload->>'team' AS team
SELECT (payload->>'participant_id')::bigint AS participant_id
, (payload->>'team_id')::bigint AS team_id
, '0' AS amount
, 'to-team' AS direction
FROM events
Expand All @@ -427,18 +434,18 @@ def update_stats(self):
SELECT COUNT(*)
FROM current_exchange_routes r
JOIN participants p ON p.id = r.participant
WHERE p.username = payload->>'participant'
WHERE p.id = (payload->>'participant_id')::bigint
AND network = 'braintree-cc'
AND error = ''
) > 0
)

UPDATE paydays p
SET nusers = (
SELECT COUNT(DISTINCT(participant)) FROM payments_and_dues
SELECT COUNT(DISTINCT(participant_id)) FROM payments_and_dues
)
, nteams = (
SELECT COUNT(DISTINCT(team)) FROM payments_and_dues
SELECT COUNT(DISTINCT(team_id)) FROM payments_and_dues
)
, volume = (
SELECT COALESCE(sum(amount), 0) FROM payments_and_dues WHERE direction='to-team'
Expand Down Expand Up @@ -480,17 +487,17 @@ def notify_participants(self):
p = e.participant
if p.notify_charge & i == 0:
continue
username = p.username
participant_id = p.id
nteams, top_team = self.db.one("""
WITH tippees AS (
SELECT t.slug, amount
FROM ( SELECT DISTINCT ON (team) team, amount
FROM ( SELECT DISTINCT ON (team_id) team_id, amount
FROM payment_instructions
WHERE mtime < %(ts_start)s
AND participant = %(username)s
ORDER BY team, mtime DESC
AND participant_id = %(participant_id)s
ORDER BY team_id, mtime DESC
) s
JOIN teams t ON s.team = t.slug
JOIN teams t ON s.team_id = t.id
JOIN participants p ON t.owner = p.username
WHERE s.amount > 0
AND t.is_approved IS true
Expand Down
76 changes: 39 additions & 37 deletions gratipay/models/participant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,13 +322,13 @@ def clear_payment_instructions(self, cursor):
SELECT ( SELECT teams.*::teams
FROM teams
WHERE slug=team
WHERE id=team_id
) AS team
FROM current_payment_instructions
WHERE participant = %s
WHERE participant_id = %s
AND amount > 0
""", (self.username,))
""", (self.id,))
for team in teams:
self.set_payment_instruction(team, '0.00', update_self=False, cursor=cursor)

Expand Down Expand Up @@ -842,7 +842,9 @@ def set_payment_instruction(self, team, amount, update_self=True, update_team=Tr
(ctime, participant, participant_id, team, team_id, amount)
VALUES ( COALESCE (( SELECT ctime
FROM payment_instructions
WHERE (participant=%(participant)s AND team=%(team)s)
WHERE ( participant_id=%(participant_id)s
AND team_id=%(team_id)s
)
LIMIT 1
), CURRENT_TIMESTAMP)
, %(participant)s, %(participant_id)s, %(team)s, %(team_id)s, %(amount)s
Expand All @@ -857,9 +859,9 @@ def set_payment_instruction(self, team, amount, update_self=True, update_team=Tr

if amount > 0:
# Carry over any existing due
self._update_due(t_dict['team'], t_dict['id'], cursor)
self._update_due(t_dict['team_id'], t_dict['id'], cursor)
else:
self._reset_due(t_dict['team'], cursor=cursor)
self._reset_due(t_dict['team_id'], cursor=cursor)

if update_self:
# Update giving amount of participant
Expand All @@ -882,12 +884,12 @@ def get_payment_instruction(self, team):
SELECT *
FROM payment_instructions
WHERE participant=%s
AND team=%s
WHERE participant_id=%s
AND team_id=%s
ORDER BY mtime DESC
LIMIT 1
""", (self.username, team.slug), back_as=dict, default=default)
""", (self.id, team.id), back_as=dict, default=default)


def get_due(self, team):
Expand All @@ -897,10 +899,10 @@ def get_due(self, team):
SELECT due
FROM current_payment_instructions
WHERE participant = %s
AND team = %s
WHERE participant_id = %s
AND team_id = %s
""", (self.username, team.slug))
""", (self.id, team.id))


def get_giving_for_profile(self):
Expand All @@ -910,26 +912,26 @@ def get_giving_for_profile(self):
GIVING = """\
SELECT * FROM (
SELECT DISTINCT ON (pi.team)
pi.team AS team_slug
SELECT DISTINCT ON (pi.team_id)
t.slug AS team_slug
, pi.amount
, pi.due
, pi.ctime
, pi.mtime
, t.name AS team_name
FROM payment_instructions pi
JOIN teams t ON pi.team = t.slug
WHERE participant = %s
JOIN teams t ON pi.team_id = t.id
WHERE participant_id = %s
AND t.is_approved is true
AND t.is_closed is not true
ORDER BY pi.team
ORDER BY pi.team_id
, pi.mtime DESC
) AS foo
ORDER BY amount DESC
, team_slug
"""
giving = self.db.all(GIVING, (self.username,))
giving = self.db.all(GIVING, (self.id,))


# Compute the totals.
Expand Down Expand Up @@ -963,7 +965,7 @@ def update_giving_and_teams(self):
with self.db.get_cursor() as cursor:
updated_giving = self.update_giving(cursor)
for payment_instruction in updated_giving:
Team.from_slug(payment_instruction.team).update_receiving(cursor)
Team.from_id(payment_instruction.team_id).update_receiving(cursor)


def update_giving(self, cursor=None):
Expand All @@ -972,32 +974,32 @@ def update_giving(self, cursor=None):
updated = (cursor or self.db).all("""
UPDATE payment_instructions
SET is_funded = %(has_credit_card)s
WHERE participant = %(username)s
WHERE participant_id = %(participant_id)s
AND is_funded <> %(has_credit_card)s
RETURNING *
""", dict(username=self.username, has_credit_card=has_credit_card))
""", dict(participant_id=self.id, has_credit_card=has_credit_card))

r = (cursor or self.db).one("""
WITH pi AS (
SELECT amount
FROM current_payment_instructions cpi
JOIN teams t ON t.slug = cpi.team
WHERE participant = %(username)s
JOIN teams t ON t.id = cpi.team_id
WHERE participant_id = %(participant_id)s
AND amount > 0
AND is_funded
AND t.is_approved
)
UPDATE participants p
SET giving = COALESCE((SELECT sum(amount) FROM pi), 0)
, ngiving_to = COALESCE((SELECT count(amount) FROM pi), 0)
WHERE p.username=%(username)s
WHERE p.id=%(participant_id)s
RETURNING giving, ngiving_to
""", dict(username=self.username))
""", dict(participant_id=self.id))
self.set_attributes(giving=r.giving, ngiving_to=r.ngiving_to)

return updated

def _update_due(self, team, id, cursor=None):
def _update_due(self, team_id, id, cursor=None):
"""Transfer existing due value to newly inserted record
"""
# Copy due to new record
Expand All @@ -1006,33 +1008,33 @@ def _update_due(self, team, id, cursor=None):
SET due = COALESCE((
SELECT due
FROM payment_instructions s
WHERE participant=%(username)s
AND team = %(team)s
WHERE participant_id = %(participant_id)s
AND team_id = %(team_id)s
AND due > 0
), 0)
WHERE p.id = %(id)s
""", dict(username=self.username,team=team,id=id))
""", dict(participant_id=self.id, team_id=team_id, id=id))

# Reset older due values to 0
self._reset_due(team, except_for=id, cursor=cursor)
self._reset_due(team_id, except_for=id, cursor=cursor)
(cursor or self.db).run("""
UPDATE payment_instructions p
SET due = 0
WHERE participant = %(username)s
AND team = %(team)s
WHERE participant_id = %(participant_id)s
AND team_id = %(team_id)s
AND due > 0
AND p.id != %(id)s
""", dict(username=self.username,team=team,id=id))
""", dict(participant_id=self.id, team_id=team_id, id=id))

def _reset_due(self, team, except_for=-1, cursor=None):
def _reset_due(self, team_id, except_for=-1, cursor=None):
(cursor or self.db).run("""
UPDATE payment_instructions p
SET due = 0
WHERE participant = %(username)s
AND team = %(team)s
WHERE participant_id = %(participant_id)s
AND team_id = %(team_id)s
AND due > 0
AND p.id != %(id)s
""", dict(username=self.username,team=team,id=except_for))
""", dict(participant_id=self.id, team_id=team_id, id=except_for))

def update_taking(self, cursor=None):
(cursor or self.db).run("""
Expand Down
42 changes: 21 additions & 21 deletions gratipay/models/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,15 @@ def get_payment_distribution(self):
SQL = """
SELECT amount
, count(amount) AS nreceiving_from
FROM ( SELECT DISTINCT ON (participant)
FROM ( SELECT DISTINCT ON (participant_id)
amount
, participant
, participant_id
FROM payment_instructions
JOIN participants p ON p.username = participant
WHERE team=%s
JOIN participants p ON p.id = participant_id
WHERE team_id=%s
AND is_funded
AND p.is_suspicious IS NOT true
ORDER BY participant
ORDER BY participant_id
, mtime DESC
) AS foo
WHERE amount > 0
Expand All @@ -132,7 +132,7 @@ def get_payment_distribution(self):

npatrons = 0.0 # float to trigger float division
total_amount = Decimal('0.00')
for rec in self.db.all(SQL, (self.slug,)):
for rec in self.db.all(SQL, (self.id,)):
tip_amounts.append([ rec.amount
, rec.nreceiving_from
, rec.amount * rec.nreceiving_from
Expand Down Expand Up @@ -180,7 +180,7 @@ def get_dues(self):
WITH our_cpi AS (
SELECT due, is_funded
FROM current_payment_instructions cpi
WHERE team=%(slug)s
WHERE team_id=%(team_id)s
)
SELECT (
SELECT COALESCE(SUM(due), 0)
Expand All @@ -192,7 +192,7 @@ def get_dues(self):
FROM our_cpi
WHERE NOT is_funded
) AS unfunded
""", {'slug': self.slug})
""", {'team_id': self.id})

return rec.funded, rec.unfunded

Expand All @@ -201,16 +201,16 @@ def get_upcoming_payment(self):
return self.db.one("""
SELECT COALESCE(SUM(amount + due), 0)
FROM current_payment_instructions cpi
JOIN participants p ON cpi.participant = p.username
WHERE team = %(slug)s
AND is_funded -- Check whether the payment is funded
AND ( -- Check whether the user will hit the minimum charge
JOIN participants p ON cpi.participant_id = p.id
WHERE team_id = %(team_id)s
AND is_funded -- Check whether the payment is funded
AND ( -- Check whether the user will hit the minimum charge
SELECT SUM(amount + due)
FROM current_payment_instructions cpi2
WHERE cpi2.participant = p.username
WHERE cpi2.participant_id = p.id
AND cpi2.is_funded
) >= %(mcharge)s
""", {'slug': self.slug, 'mcharge': MINIMUM_CHARGE})
""", {'team_id': self.id, 'mcharge': MINIMUM_CHARGE})


def create_github_review_issue(self):
Expand Down Expand Up @@ -257,8 +257,8 @@ def update_receiving(self, cursor=None):
WITH our_receiving AS (
SELECT amount
FROM current_payment_instructions
JOIN participants p ON p.username = participant
WHERE team = %(slug)s
JOIN participants p ON p.id = participant_id
WHERE team_id = %(team_id)s
AND p.is_suspicious IS NOT true
AND amount > 0
AND is_funded
Expand All @@ -268,9 +268,9 @@ def update_receiving(self, cursor=None):
, nreceiving_from = COALESCE((SELECT count(*) FROM our_receiving), 0)
, distributing = COALESCE((SELECT sum(amount) FROM our_receiving), 0)
, ndistributing_to = 1
WHERE t.slug = %(slug)s
WHERE t.id = %(team_id)s
RETURNING receiving, nreceiving_from, distributing, ndistributing_to
""", dict(slug=self.slug))
""", dict(team_id=self.id))


# This next step is easy for now since we don't have payroll.
Expand Down Expand Up @@ -316,7 +316,7 @@ def migrate_tips(self):
payment_instructions = self.db.all("""
SELECT pi.*
FROM payment_instructions pi
JOIN teams t ON t.slug = pi.team
JOIN teams t ON t.id = pi.team_id
WHERE t.owner = %s
AND pi.ctime < t.ctime
""", (self.owner, ))
Expand Down Expand Up @@ -413,14 +413,14 @@ def migrate_all_tips(db, print=print):

"""
teams = db.all("""
SELECT distinct ON (t.slug) t.*::teams
SELECT distinct ON (t.id) t.*::teams
FROM teams t
JOIN tips ON t.owner = tips.tippee -- Only fetch teams whose owners had tips under Gratipay 1.0
WHERE t.is_approved IS TRUE -- Only fetch approved teams
AND NOT EXISTS ( -- Make sure tips haven't been migrated for any teams with same owner
SELECT 1
FROM payment_instructions pi
JOIN teams t2 ON t2.slug = pi.team
JOIN teams t2 ON t2.id = pi.team_id
WHERE t2.owner = t.owner
AND pi.ctime < t2.ctime
)
Expand Down
Loading