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

Commit

Permalink
Start implementing cacheroonies in triggers
Browse files Browse the repository at this point in the history
  • Loading branch information
chadwhitacre committed May 12, 2016
1 parent 7463aa3 commit 3fb940a
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 8 deletions.
14 changes: 6 additions & 8 deletions gratipay/models/participant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1042,15 +1042,13 @@ def _reset_due(self, team, except_for=-1, cursor=None):
AND p.id != %(id)s
""", dict(username=self.username,team=team,id=except_for))

def update_taking(self, cursor=None):
(cursor or self.db).run("""
UPDATE participants
SET taking=COALESCE((SELECT sum(receiving) FROM teams WHERE owner=%(username)s), 0)
, ntaking_from=COALESCE((SELECT count(*) FROM teams WHERE owner=%(username)s), 0)
WHERE username=%(username)s

""", dict(username=self.username))
def update_taking(self, cursor=None):
# Update logic happens down in a Postgres trigger. We just need to refresh.
taking, ntaking_from = (cursor or self.db).one("""\
SELECT taking, ntaking_from FROM participants WHERE id=%s
""", (self.id,))
self.set_attributes(taking=taking, ntaking_from=ntaking_from)


def update_is_free_rider(self, is_free_rider, cursor=None):
Expand Down
2 changes: 2 additions & 0 deletions gratipay/models/team/mixins/takes.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ def set_ntakes_for(self, participant, ntakes, recorder=None):
, 'recorder_id': recorder.id
})

participant.update_taking(cursor)

self.set_attributes( ntakes_claimed=nclaimed
, ntakes_unclaimed=nunclaimed
, ndistributing_to=ndistributing_to
Expand Down
102 changes: 102 additions & 0 deletions sql/branch.sql
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,105 @@ BEGIN;
ALTER TABLE teams ADD CONSTRAINT ntakes_sum CHECK (ntakes = ntakes_claimed + ntakes_unclaimed);

END;


CREATE FUNCTION propagate_takes_insert()
RETURNS trigger AS $$
DECLARE
is_new_member bool;
team_ntakes bigint;
team_receiving numeric(35,2);

delta_n int;
delta_amount numeric(35,2);

old_taking numeric(35,2);
old_ntaking_from int;
old_ntakes bigint;
old_amount numeric(35,2);

new_amount numeric(35,2);
BEGIN
is_new_member := ( SELECT id
FROM memberships
WHERE participant_id=NEW.participant_id
AND team_id=NEW.team_id
) IS NULL;

team_ntakes := (SELECT ntakes FROM teams WHERE id=NEW.team_id);
team_receiving := (SELECT receiving FROM teams WHERE id=NEW.team_id);
new_amount := (NEW.ntakes::numeric / team_ntakes::numeric) * team_receiving;
new_amount := round(new_amount, 2);

IF is_new_member THEN

-- They're being added to a team.

IF NEW.ntakes = 0 THEN
RAISE 'How did you get here?'; -- They are leaving a team they're not on!
ELSE
delta_n := 1;
delta_amount := new_amount;
END IF;
ELSE

-- They're leaving a team or changing their take.

old_ntaking_from := (SELECT ntaking_from FROM participants WHERE id=NEW.participant_id);
old_taking := (SELECT taking FROM participants WHERE id=NEW.participant_id);
old_ntakes := ( SELECT ntakes
FROM memberships
WHERE team_id=NEW.team_id
AND participant_id=NEW.participant_id
);
old_amount := (old_ntakes / team_ntakes) * team_receiving;
old_amount := round(old_amount, 2);

IF NEW.ntakes = 0 THEN

-- They're leaving a team.

delta_n := -1;

IF old_ntaking_from = 1 THEN

-- They're leaving their *last* team; use their entire old
-- taking amount as the delta to avoid rounding errors.

delta_amount := -old_taking;

ELSE

-- They're leaving a team, but it's not their last; use an
-- estimate of the value of their take.

delta_amount := -old_amount;

END IF;
ELSE

-- They're changing their takes.

delta_n := 0;
delta_amount := new_amount - old_amount;

END IF;
END IF;

UPDATE participants
SET ntaking_from = ntaking_from + delta_n
, taking = taking + delta_amount
WHERE id = NEW.participant_id;

UPDATE teams
SET ndistributing_to = ndistributing_to + delta_n
, distributing = distributing + delta_amount
WHERE id = NEW.team_id;

RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER propagate_takes_insert
BEFORE INSERT ON takes
FOR EACH ROW EXECUTE PROCEDURE propagate_takes_insert();
10 changes: 10 additions & 0 deletions tests/py/test_team_takes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
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.mixins.takes import BadMember
Expand Down Expand Up @@ -32,6 +34,9 @@ def setUp(self):
self.bruiser.store_identity_info(self.TT, 'nothing-enforced', {'name': 'Bruiser'})
self.bruiser.set_identity_verification(self.TT, True)

self.bob = self.make_participant('bob', claimed_time='now', last_bill_result='')
self.bob.set_payment_instruction(self.enterprise, '99.00')

@property
def last_event(self):
return self.db.one("SELECT * FROM events ORDER BY ts DESC LIMIT 1")
Expand Down Expand Up @@ -127,6 +132,11 @@ def test_snf_lets_someone_else_be_the_recorder(self):
assert self.enterprise.set_ntakes_for(self.crusher, 537, self.picard) == 537
assert self.last_take.recorder_id == self.picard.id

def test_snf_updates_taking_on_member(self):
self.crusher.ntaking_from == 0
self.enterprise.set_ntakes_for(self.crusher, 537)
assert self.crusher.taking == D('53.16')
assert self.crusher.ntaking_from == 1


def assert_bad_member(self, member, reason):
Expand Down

0 comments on commit 3fb940a

Please sign in to comment.