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

Fix fake payday depth #2988

Merged
merged 8 commits into from
Dec 5, 2014
Merged
Show file tree
Hide file tree
Changes from 5 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
39 changes: 33 additions & 6 deletions fake_payday.sql
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,45 @@ CREATE TRIGGER fake_take AFTER INSERT ON temp_takes
FOR EACH ROW EXECUTE PROCEDURE fake_take();


-- Create a function to settle whole tip graph

CREATE OR REPLACE FUNCTION settle_tip_graph() RETURNS void AS $$
DECLARE
count integer NOT NULL DEFAULT 0;
i integer := 0;
BEGIN
LOOP
i := i + 1;
WITH updated_rows AS (
UPDATE temp_tips
SET is_funded = true
WHERE is_funded IS NOT true
RETURNING *
)
SELECT COUNT(*) FROM updated_rows INTO count;
IF (count = 0) THEN
EXIT;
END IF;
IF (i > 50) THEN
RAISE 'Reached the maximum number of iterations';
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;


-- Start fake payday

-- Step 1: tips that are backed by a credit card
-- Step 1: tips
UPDATE temp_tips t
SET is_funded = true
FROM temp_participants p
WHERE p.username = t.tipper
AND p.credit_card_ok;

-- Step 2: tips that are covered by the user's balance
UPDATE temp_tips t
SET is_funded = true
WHERE is_funded IS NOT true;
SELECT settle_tip_graph();

-- Step 3: team takes
-- Step 2: team takes
INSERT INTO temp_takes
SELECT team, member, amount
FROM current_takes t
Expand All @@ -139,6 +163,9 @@ INSERT INTO temp_takes
AND t.member IN (SELECT username FROM temp_participants)
ORDER BY ctime DESC;

-- Step 3: tips again
SELECT settle_tip_graph();

-- Step 4: update the real tables
UPDATE tips t
SET is_funded = tt.is_funded
Expand Down
2 changes: 2 additions & 0 deletions gratipay/models/_mixin_team.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ def __set_take_for(self, member, amount, recorder, cursor=None):
new_takes = self.compute_actual_takes(cursor)
# Update receiving amounts in the participants table
self.update_taking(old_takes, new_takes, cursor, member)
# Update is_funded on member's tips
member.update_giving(cursor)

def update_taking(self, old_takes, new_takes, cursor=None, member=None):
"""Update `taking` amounts based on the difference between `old_takes`
Expand Down
2 changes: 1 addition & 1 deletion gratipay/models/participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ def update_giving(self, cursor=None):
AND p2.is_suspicious IS NOT true
ORDER BY p2.claimed_time IS NULL, t.ctime ASC
""", (self.username,))
fake_balance = self.balance + self.receiving - self.taking
fake_balance = self.balance + self.receiving
for tip in tips:
if tip.amount > fake_balance:
is_funded = False
Expand Down
42 changes: 22 additions & 20 deletions tests/py/test_billing_payday.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,39 +101,41 @@ def test_update_cached_amounts(self):
bob = self.make_participant('bob', claimed_time='now', last_bill_result=None)
carl = self.make_participant('carl', claimed_time='now', last_bill_result="Fail!")
dana = self.make_participant('dana', claimed_time='now')
emma = self.make_elsewhere('github', 58946, 'emma').participant
emma = self.make_participant('emma', claimed_time='now')
michael = self.make_elsewhere('github', 58946, 'michael').participant
roy = self.make_elsewhere('github', 58947, 'roy', is_locked=True).participant
alice.set_tip_to(dana, '3.00')
alice.set_tip_to(bob, '6.00')
alice.set_tip_to(emma, '1.00')
alice.set_tip_to(team, '4.00')
alice.set_tip_to(roy, '10.00')
bob.set_tip_to(alice, '5.00')
bob.set_tip_to(dana, '2.00')
carl.set_tip_to(dana, '2.08')
alice.set_tip_to(bob, '50.00')
alice.set_tip_to(team, '10.00')
alice.set_tip_to(michael, '30.00')
alice.set_tip_to(roy, '70.00')
team.add_member(bob)
team.set_take_for(bob, D('1.00'), bob)

bob.set_tip_to(dana, '51.00')
dana.set_tip_to(emma, '5.00')
emma.set_tip_to(bob, '20.00') # Unfunded
carl.set_tip_to(dana, '30.00') # Unfunded
def check():
alice = Participant.from_username('alice')
bob = Participant.from_username('bob')
carl = Participant.from_username('carl')
dana = Participant.from_username('dana')
emma = AccountElsewhere.from_user_name('github','emma').participant
assert alice.giving == D('13.00')
assert alice.pledging == D('1.00')
assert alice.receiving == D('5.00')
assert bob.giving == D('5.00')
assert bob.receiving == D('7.00')
emma = Participant.from_username('emma')
michael = AccountElsewhere.from_user_name('github','michael').participant
assert alice.giving == D('60.00')
assert alice.pledging == D('30.00')
assert bob.receiving == D('51.00')
assert bob.giving == D('51.00')
assert bob.taking == D('1.00')
assert carl.giving == D('0.00')
assert carl.receiving == D('0.00')
assert dana.receiving == D('3.00')
assert dana.giving == D('5.00')
assert dana.receiving == D('51.00')
assert dana.npatrons == 1
assert emma.receiving == D('1.00')
assert emma.receiving == D('5.00')
assert emma.npatrons == 1
assert michael.receiving == D('30.00')
assert michael.npatrons == 1
funded_tips = self.db.all("SELECT amount FROM tips WHERE is_funded ORDER BY id")
assert funded_tips == [3, 6, 1, 4, 10, 5]
assert funded_tips == [50, 10, 30, 70, 51, 5]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you change so many things in this test ? From reading the diff I can't tell what you're trying to do.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test was kinda messy because we had added stuff over time to check for various situations. I didn't want to add one more participant into the equation, so I spent some time on restructuring to make sure that we check for all the following cases:

  • tips from previously failing CCs are not funded
  • payday goes beyond 2 steps
  • team takes are included in the calculations
  • make sure funds are not transferred to closed accounts


# Pre-test check
check()
Expand Down