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

Commit

Permalink
Stub out new PR for triggers
Browse files Browse the repository at this point in the history
  • Loading branch information
chadwhitacre committed Jun 16, 2016
1 parent cfbdaf1 commit f0d2c1c
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 12 deletions.
3 changes: 0 additions & 3 deletions defaults.env
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,6 @@ ASPEN_PROJECT_ROOT=.
ASPEN_SHOW_TRACEBACKS=yes
ASPEN_WWW_ROOT=www/

# https://github.com/benoitc/gunicorn/issues/186
GUNICORN_OPTS="--workers=1 --timeout=99999999"

# For testing Team review ticket posting
# Set your own username and an access token in local.env
TEAM_REVIEW_REPO=gratipay/test-gremlin
Expand Down
17 changes: 8 additions & 9 deletions gratipay/models/participant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ def _from_thing(cls, thing, value):
""".format(thing), (value,))

def refresh(self):
self.__dict__.update(self.__class__.from_id(self.id).__dict__)


# Session Management
# ==================
Expand Down Expand Up @@ -330,7 +333,7 @@ def clear_payment_instructions(self, cursor):
""", (self.id,))
for team in teams:
self.set_payment_instruction(team, '0.00', update_self=False, cursor=cursor)
self.set_payment_instruction(team, '0.00', cursor=cursor)


def clear_takes(self, cursor):
Expand Down Expand Up @@ -815,8 +818,7 @@ def update_avatar(self):
# Giving and Taking
# =================

def set_payment_instruction(self, team, amount, update_self=True, update_team=True,
cursor=None):
def set_payment_instruction(self, team, amount, cursor=None):
"""Given a Team instance, and amount as str, return a dict.
We INSERT instead of UPDATE, so that we have history to explore. The
Expand Down Expand Up @@ -862,12 +864,9 @@ def set_payment_instruction(self, team, amount, update_self=True, update_team=Tr
else:
self._reset_due(t_dict['team_id'], cursor=cursor)

if update_self:
# Update giving amount of participant
self.update_giving(cursor)
if update_team:
# Update receiving amount of team
team.update_receiving(cursor)
self.refresh()
team.refresh()

if team.slug == 'Gratipay':
# Update whether the participant is using Gratipay for free
self.update_is_free_rider(None if amount == 0 else False, cursor)
Expand Down
3 changes: 3 additions & 0 deletions gratipay/models/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ def _from_thing(cls, thing, value):
""".format(thing), (value,))

def refresh(self):
self.__dict__.update(self.__class__.from_id(self.id).__dict__)

@classmethod
def insert(cls, owner, **fields):
fields['slug_lower'] = fields['slug'].lower()
Expand Down
8 changes: 8 additions & 0 deletions sql/branch.sql
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,11 @@ BEGIN; -- Step 3
FOR EACH ROW EXECUTE PROCEDURE update_payment_instruction();

END;


-- https://github.com/gratipay/gratipay.com/pull/4045

\i sql/triggers/payment_instructions.sql

DROP FUNCTION update_payment_instruction();
\i sql/triggers/current_payment_instructions.sql
18 changes: 18 additions & 0 deletions sql/triggers/current_payment_instructions.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
CREATE FUNCTION update_current_payment_instructions()
RETURNS trigger AS $$
BEGIN

-- Allow updating is_funded and due via the current_payment_instructions view for convenience.
UPDATE payment_instructions
SET is_funded = NEW.is_funded
, due = NEW.due
WHERE id = NEW.id;

RETURN NULL;
END;
$$ LANGUAGE plpgsql;


CREATE TRIGGER update_current_payment_instructions
INSTEAD OF UPDATE ON current_payment_instructions
FOR EACH ROW EXECUTE PROCEDURE update_current_payment_instructions();
49 changes: 49 additions & 0 deletions sql/triggers/payment_instructions.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
CREATE FUNCTION propagate_payment_instructions_insert()
RETURNS trigger AS $$
DECLARE
is_new_giver bool;
delta_n int;
delta_amount numeric(35,2);
BEGIN
is_new_giver := ( SELECT id
FROM current_payment_instructions
WHERE participant_id=NEW.participant_id
AND team_id=NEW.team_id
AND amount > 0
) IS NULL;

delta_amount := NEW.amount;

IF NEW.amount = 0 THEN
IF is_new_giver THEN
delta_n := 0;
ELSE
delta_n := -1;
END IF;
ELSE
IF is_new_giver THEN
delta_n := 1;
ELSE
delta_n := 0;
END IF;
END IF;

UPDATE participants
SET giving = giving + delta_amount
, ngiving_to = ngiving_to + delta_n
WHERE id = NEW.participant_id;

UPDATE teams
SET receiving = receiving + delta_amount
, nreceiving_from = nreceiving_from + delta_n
WHERE id = NEW.team_id;

RETURN NEW;

END;
$$ LANGUAGE plpgsql;


CREATE TRIGGER propagate_payment_instructions_insert
BEFORE INSERT ON payment_instructions
FOR EACH ROW EXECUTE PROCEDURE propagate_payment_instructions_insert();
58 changes: 58 additions & 0 deletions tests/py/test_computed_values.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from __future__ import absolute_import, division, print_function, unicode_literals

from decimal import Decimal as D
from gratipay.testing import Harness
from gratipay.models.participant import Participant
from gratipay.models.team import Team


P = Participant.from_username
T = Team.from_slug


class Tests(Harness):

def setUp(self):
self.alice = self.make_participant('alice', claimed_time='now', last_bill_result='')
self.bob = self.make_participant('bob', claimed_time='now', last_bill_result='')
self.enterprise = self.make_team()


# g - giving

def test_g_starts_out_zero(self):
assert P('alice').giving == 0

def test_g_increases_with_payment_instruction(self):
self.alice.set_payment_instruction(self.enterprise, '1.00')
assert P('alice').giving == D('1.00')


# ngt - ngiving_to

def test_ngt_starts_out_zero(self):
assert P('alice').ngiving_to == 0

def test_ngt_increases_with_payment_instruction(self):
self.alice.set_payment_instruction(self.enterprise, '1.00')
assert P('alice').ngiving_to == 1


# r - receiving

def test_r_starts_out_zero(self):
assert T('TheEnterprise').receiving == 0

def test_r_increases_with_payment_instruction(self):
self.alice.set_payment_instruction(self.enterprise, '1.00')
assert T('TheEnterprise').receiving == D('1.00')


# nrf - nreceiving_from

def test_nrf_starts_out_zero(self):
assert T('TheEnterprise').nreceiving_from == 0

def test_nrf_increases_with_payment_instruction(self):
self.alice.set_payment_instruction(self.enterprise, '1.00')
assert T('TheEnterprise').nreceiving_from == 1

0 comments on commit f0d2c1c

Please sign in to comment.