We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Cannot close (delete) my account
I works for a while but then I see an "Application Error" page from Heroku. Ostensibly the operation takes too long and Heroku kills the request.

Cannot close (delete) my account
I works for a while but then I see an "Application Error" page from Heroku. Ostensibly the operation takes too long and Heroku kills the request.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gratipay/models/_mixin_team.py`
Content:
```
1 """Teams on Gratipay are plural participants with members.
2 """
3 from collections import OrderedDict
4 from decimal import Decimal
5 
6 from aspen.utils import typecheck
7 
8 
9 class MemberLimitReached(Exception): pass
10 
11 class StubParticipantAdded(Exception): pass
12 
13 class MixinTeam(object):
14     """This class provides methods for working with a Participant as a Team.
15 
16     :param Participant participant: the underlying :py:class:`~gratipay.participant.Participant` object for this team
17 
18     """
19 
20     # XXX These were all written with the ORM and need to be converted.
21 
22     def __init__(self, participant):
23         self.participant = participant
24 
25     def show_as_team(self, user):
26         """Return a boolean, whether to show this participant as a team.
27         """
28         if not self.IS_PLURAL:
29             return False
30         if user.ADMIN:
31             return True
32         if not self.get_current_takes():
33             if self == user.participant:
34                 return True
35             return False
36         return True
37 
38     def add_member(self, member):
39         """Add a member to this team.
40         """
41         assert self.IS_PLURAL
42         if len(self.get_current_takes()) == 149:
43             raise MemberLimitReached
44         if not member.is_claimed:
45             raise StubParticipantAdded
46         self.__set_take_for(member, Decimal('0.01'), self)
47 
48     def remove_member(self, member):
49         """Remove a member from this team.
50         """
51         assert self.IS_PLURAL
52         self.__set_take_for(member, Decimal('0.00'), self)
53 
54     def remove_all_members(self, cursor=None):
55         (cursor or self.db).run("""
56             INSERT INTO takes (ctime, member, team, amount, recorder) (
57                 SELECT ctime, member, %(username)s, 0.00, %(username)s
58                   FROM current_takes
59                  WHERE team=%(username)s
60                    AND amount > 0
61             );
62         """, dict(username=self.username))
63 
64     def member_of(self, team):
65         """Given a Participant object, return a boolean.
66         """
67         assert team.IS_PLURAL
68         for take in team.get_current_takes():
69             if take['member'] == self.username:
70                 return True
71         return False
72 
73     def get_take_last_week_for(self, member):
74         """Get the user's nominal take last week. Used in throttling.
75         """
76         assert self.IS_PLURAL
77         membername = member.username if hasattr(member, 'username') \
78                                                         else member['username']
79         return self.db.one("""
80 
81             SELECT amount
82               FROM takes
83              WHERE team=%s AND member=%s
84                AND mtime < (
85                        SELECT ts_start
86                          FROM paydays
87                         WHERE ts_end > ts_start
88                      ORDER BY ts_start DESC LIMIT 1
89                    )
90           ORDER BY mtime DESC LIMIT 1
91 
92         """, (self.username, membername), default=Decimal('0.00'))
93 
94     def get_take_for(self, member):
95         """Return a Decimal representation of the take for this member, or 0.
96         """
97         assert self.IS_PLURAL
98         return self.db.one( "SELECT amount FROM current_takes "
99                             "WHERE member=%s AND team=%s"
100                           , (member.username, self.username)
101                           , default=Decimal('0.00')
102                            )
103 
104     def compute_max_this_week(self, last_week):
105         """2x last week's take, but at least a dollar.
106         """
107         return max(last_week * Decimal('2'), Decimal('1.00'))
108 
109     def set_take_for(self, member, take, recorder, cursor=None):
110         """Sets member's take from the team pool.
111         """
112         assert self.IS_PLURAL
113 
114         # lazy import to avoid circular import
115         from gratipay.security.user import User
116         from gratipay.models.participant import Participant
117 
118         typecheck( member, Participant
119                  , take, Decimal
120                  , recorder, (Participant, User)
121                   )
122 
123         last_week = self.get_take_last_week_for(member)
124         max_this_week = self.compute_max_this_week(last_week)
125         if take > max_this_week:
126             take = max_this_week
127 
128         self.__set_take_for(member, take, recorder, cursor)
129         return take
130 
131     def __set_take_for(self, member, amount, recorder, cursor=None):
132         assert self.IS_PLURAL
133         # XXX Factored out for testing purposes only! :O Use .set_take_for.
134         with self.db.get_cursor(cursor) as cursor:
135             # Lock to avoid race conditions
136             cursor.run("LOCK TABLE takes IN EXCLUSIVE MODE")
137             # Compute the current takes
138             old_takes = self.compute_actual_takes(cursor)
139             # Insert the new take
140             cursor.run("""
141 
142                 INSERT INTO takes (ctime, member, team, amount, recorder)
143                  VALUES ( COALESCE (( SELECT ctime
144                                         FROM takes
145                                        WHERE member=%(member)s
146                                          AND team=%(team)s
147                                        LIMIT 1
148                                      ), CURRENT_TIMESTAMP)
149                         , %(member)s
150                         , %(team)s
151                         , %(amount)s
152                         , %(recorder)s
153                          )
154 
155             """, dict(member=member.username, team=self.username, amount=amount,
156                       recorder=recorder.username))
157             # Compute the new takes
158             new_takes = self.compute_actual_takes(cursor)
159             # Update receiving amounts in the participants table
160             self.update_taking(old_takes, new_takes, cursor, member)
161             # Update is_funded on member's tips
162             member.update_giving(cursor)
163 
164     def update_taking(self, old_takes, new_takes, cursor=None, member=None):
165         """Update `taking` amounts based on the difference between `old_takes`
166         and `new_takes`.
167         """
168         for username in set(old_takes.keys()).union(new_takes.keys()):
169             if username == self.username:
170                 continue
171             old = old_takes.get(username, {}).get('actual_amount', Decimal(0))
172             new = new_takes.get(username, {}).get('actual_amount', Decimal(0))
173             diff = new - old
174             if diff != 0:
175                 r = (self.db or cursor).one("""
176                     UPDATE participants
177                        SET taking = (taking + %(diff)s)
178                          , receiving = (receiving + %(diff)s)
179                      WHERE username=%(username)s
180                  RETURNING taking, receiving
181                 """, dict(username=username, diff=diff))
182                 if member and username == member.username:
183                     member.set_attributes(**r._asdict())
184 
185     def get_current_takes(self, cursor=None):
186         """Return a list of member takes for a team.
187         """
188         assert self.IS_PLURAL
189         TAKES = """
190             SELECT member, amount, ctime, mtime
191               FROM current_takes
192              WHERE team=%(team)s
193           ORDER BY ctime DESC
194         """
195         records = (cursor or self.db).all(TAKES, dict(team=self.username))
196         return [r._asdict() for r in records]
197 
198     def get_team_take(self, cursor=None):
199         """Return a single take for a team, the team itself's take.
200         """
201         assert self.IS_PLURAL
202         TAKE = "SELECT sum(amount) FROM current_takes WHERE team=%s"
203         total_take = (cursor or self.db).one(TAKE, (self.username,), default=0)
204         team_take = max(self.receiving - total_take, 0)
205         membership = { "ctime": None
206                      , "mtime": None
207                      , "member": self.username
208                      , "amount": team_take
209                       }
210         return membership
211 
212     def compute_actual_takes(self, cursor=None):
213         """Get the takes, compute the actual amounts, and return an OrderedDict.
214         """
215         actual_takes = OrderedDict()
216         nominal_takes = self.get_current_takes(cursor=cursor)
217         nominal_takes.append(self.get_team_take(cursor=cursor))
218         budget = balance = self.balance + self.receiving - self.giving
219         for take in nominal_takes:
220             nominal_amount = take['nominal_amount'] = take.pop('amount')
221             actual_amount = take['actual_amount'] = min(nominal_amount, balance)
222             if take['member'] != self.username:
223                 balance -= actual_amount
224             take['balance'] = balance
225             take['percentage'] = (actual_amount / budget) if budget > 0 else 0
226             actual_takes[take['member']] = take
227         return actual_takes
228 
229     def get_members(self, current_participant):
230         """Return a list of member dicts.
231         """
232         assert self.IS_PLURAL
233         takes = self.compute_actual_takes()
234         members = []
235         for take in takes.values():
236             member = {}
237             member['username'] = take['member']
238             member['take'] = take['nominal_amount']
239             member['balance'] = take['balance']
240             member['percentage'] = take['percentage']
241 
242             member['removal_allowed'] = current_participant == self
243             member['editing_allowed'] = False
244             member['is_current_user'] = False
245             if current_participant is not None:
246                 if member['username'] == current_participant.username:
247                     member['is_current_user'] = True
248                     if take['ctime'] is not None:
249                         # current user, but not the team itself
250                         member['editing_allowed']= True
251 
252             member['last_week'] = last_week = self.get_take_last_week_for(member)
253             member['max_this_week'] = self.compute_max_this_week(last_week)
254             members.append(member)
255         return members
256
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gratipay/models/_mixin_team.py b/gratipay/models/_mixin_team.py
--- a/gratipay/models/_mixin_team.py
+++ b/gratipay/models/_mixin_team.py
@@ -172,7 +172,7 @@
             new = new_takes.get(username, {}).get('actual_amount', Decimal(0))
             diff = new - old
             if diff != 0:
-                r = (self.db or cursor).one("""
+                r = (cursor or self.db).one("""
                     UPDATE participants
                        SET taking = (taking + %(diff)s)
                          , receiving = (receiving + %(diff)s)

{"golden_diff": "diff --git a/gratipay/models/_mixin_team.py b/gratipay/models/_mixin_team.py\n--- a/gratipay/models/_mixin_team.py\n+++ b/gratipay/models/_mixin_team.py\n@@ -172,7 +172,7 @@\n             new = new_takes.get(username, {}).get('actual_amount', Decimal(0))\n             diff = new - old\n             if diff != 0:\n-                r = (self.db or cursor).one(\"\"\"\n+                r = (cursor or self.db).one(\"\"\"\n                     UPDATE participants\n                        SET taking = (taking + %(diff)s)\n                          , receiving = (receiving + %(diff)s)\n", "issue": "Cannot close (delete) my account\nI works for a while but then I see an \"Application Error\" page from Heroku. Ostensibly the operation takes too long and Heroku kills the request.\n\nCannot close (delete) my account\nI works for a while but then I see an \"Application Error\" page from Heroku. Ostensibly the operation takes too long and Heroku kills the request.\n\n", "before_files": [{"content": "\"\"\"Teams on Gratipay are plural participants with members.\n\"\"\"\nfrom collections import OrderedDict\nfrom decimal import Decimal\n\nfrom aspen.utils import typecheck\n\n\nclass MemberLimitReached(Exception): pass\n\nclass StubParticipantAdded(Exception): pass\n\nclass MixinTeam(object):\n    \"\"\"This class provides methods for working with a Participant as a Team.\n\n    :param Participant participant: the underlying :py:class:`~gratipay.participant.Participant` object for this team\n\n    \"\"\"\n\n    # XXX These were all written with the ORM and need to be converted.\n\n    def __init__(self, participant):\n        self.participant = participant\n\n    def show_as_team(self, user):\n        \"\"\"Return a boolean, whether to show this participant as a team.\n        \"\"\"\n        if not self.IS_PLURAL:\n            return False\n        if user.ADMIN:\n            return True\n        if not self.get_current_takes():\n            if self == user.participant:\n                return True\n            return False\n        return True\n\n    def add_member(self, member):\n        \"\"\"Add a member to this team.\n        \"\"\"\n        assert self.IS_PLURAL\n        if len(self.get_current_takes()) == 149:\n            raise MemberLimitReached\n        if not member.is_claimed:\n            raise StubParticipantAdded\n        self.__set_take_for(member, Decimal('0.01'), self)\n\n    def remove_member(self, member):\n        \"\"\"Remove a member from this team.\n        \"\"\"\n        assert self.IS_PLURAL\n        self.__set_take_for(member, Decimal('0.00'), self)\n\n    def remove_all_members(self, cursor=None):\n        (cursor or self.db).run(\"\"\"\n            INSERT INTO takes (ctime, member, team, amount, recorder) (\n                SELECT ctime, member, %(username)s, 0.00, %(username)s\n                  FROM current_takes\n                 WHERE team=%(username)s\n                   AND amount > 0\n            );\n        \"\"\", dict(username=self.username))\n\n    def member_of(self, team):\n        \"\"\"Given a Participant object, return a boolean.\n        \"\"\"\n        assert team.IS_PLURAL\n        for take in team.get_current_takes():\n            if take['member'] == self.username:\n                return True\n        return False\n\n    def get_take_last_week_for(self, member):\n        \"\"\"Get the user's nominal take last week. Used in throttling.\n        \"\"\"\n        assert self.IS_PLURAL\n        membername = member.username if hasattr(member, 'username') \\\n                                                        else member['username']\n        return self.db.one(\"\"\"\n\n            SELECT amount\n              FROM takes\n             WHERE team=%s AND member=%s\n               AND mtime < (\n                       SELECT ts_start\n                         FROM paydays\n                        WHERE ts_end > ts_start\n                     ORDER BY ts_start DESC LIMIT 1\n                   )\n          ORDER BY mtime DESC LIMIT 1\n\n        \"\"\", (self.username, membername), default=Decimal('0.00'))\n\n    def get_take_for(self, member):\n        \"\"\"Return a Decimal representation of the take for this member, or 0.\n        \"\"\"\n        assert self.IS_PLURAL\n        return self.db.one( \"SELECT amount FROM current_takes \"\n                            \"WHERE member=%s AND team=%s\"\n                          , (member.username, self.username)\n                          , default=Decimal('0.00')\n                           )\n\n    def compute_max_this_week(self, last_week):\n        \"\"\"2x last week's take, but at least a dollar.\n        \"\"\"\n        return max(last_week * Decimal('2'), Decimal('1.00'))\n\n    def set_take_for(self, member, take, recorder, cursor=None):\n        \"\"\"Sets member's take from the team pool.\n        \"\"\"\n        assert self.IS_PLURAL\n\n        # lazy import to avoid circular import\n        from gratipay.security.user import User\n        from gratipay.models.participant import Participant\n\n        typecheck( member, Participant\n                 , take, Decimal\n                 , recorder, (Participant, User)\n                  )\n\n        last_week = self.get_take_last_week_for(member)\n        max_this_week = self.compute_max_this_week(last_week)\n        if take > max_this_week:\n            take = max_this_week\n\n        self.__set_take_for(member, take, recorder, cursor)\n        return take\n\n    def __set_take_for(self, member, amount, recorder, cursor=None):\n        assert self.IS_PLURAL\n        # XXX Factored out for testing purposes only! :O Use .set_take_for.\n        with self.db.get_cursor(cursor) as cursor:\n            # Lock to avoid race conditions\n            cursor.run(\"LOCK TABLE takes IN EXCLUSIVE MODE\")\n            # Compute the current takes\n            old_takes = self.compute_actual_takes(cursor)\n            # Insert the new take\n            cursor.run(\"\"\"\n\n                INSERT INTO takes (ctime, member, team, amount, recorder)\n                 VALUES ( COALESCE (( SELECT ctime\n                                        FROM takes\n                                       WHERE member=%(member)s\n                                         AND team=%(team)s\n                                       LIMIT 1\n                                     ), CURRENT_TIMESTAMP)\n                        , %(member)s\n                        , %(team)s\n                        , %(amount)s\n                        , %(recorder)s\n                         )\n\n            \"\"\", dict(member=member.username, team=self.username, amount=amount,\n                      recorder=recorder.username))\n            # Compute the new takes\n            new_takes = self.compute_actual_takes(cursor)\n            # Update receiving amounts in the participants table\n            self.update_taking(old_takes, new_takes, cursor, member)\n            # Update is_funded on member's tips\n            member.update_giving(cursor)\n\n    def update_taking(self, old_takes, new_takes, cursor=None, member=None):\n        \"\"\"Update `taking` amounts based on the difference between `old_takes`\n        and `new_takes`.\n        \"\"\"\n        for username in set(old_takes.keys()).union(new_takes.keys()):\n            if username == self.username:\n                continue\n            old = old_takes.get(username, {}).get('actual_amount', Decimal(0))\n            new = new_takes.get(username, {}).get('actual_amount', Decimal(0))\n            diff = new - old\n            if diff != 0:\n                r = (self.db or cursor).one(\"\"\"\n                    UPDATE participants\n                       SET taking = (taking + %(diff)s)\n                         , receiving = (receiving + %(diff)s)\n                     WHERE username=%(username)s\n                 RETURNING taking, receiving\n                \"\"\", dict(username=username, diff=diff))\n                if member and username == member.username:\n                    member.set_attributes(**r._asdict())\n\n    def get_current_takes(self, cursor=None):\n        \"\"\"Return a list of member takes for a team.\n        \"\"\"\n        assert self.IS_PLURAL\n        TAKES = \"\"\"\n            SELECT member, amount, ctime, mtime\n              FROM current_takes\n             WHERE team=%(team)s\n          ORDER BY ctime DESC\n        \"\"\"\n        records = (cursor or self.db).all(TAKES, dict(team=self.username))\n        return [r._asdict() for r in records]\n\n    def get_team_take(self, cursor=None):\n        \"\"\"Return a single take for a team, the team itself's take.\n        \"\"\"\n        assert self.IS_PLURAL\n        TAKE = \"SELECT sum(amount) FROM current_takes WHERE team=%s\"\n        total_take = (cursor or self.db).one(TAKE, (self.username,), default=0)\n        team_take = max(self.receiving - total_take, 0)\n        membership = { \"ctime\": None\n                     , \"mtime\": None\n                     , \"member\": self.username\n                     , \"amount\": team_take\n                      }\n        return membership\n\n    def compute_actual_takes(self, cursor=None):\n        \"\"\"Get the takes, compute the actual amounts, and return an OrderedDict.\n        \"\"\"\n        actual_takes = OrderedDict()\n        nominal_takes = self.get_current_takes(cursor=cursor)\n        nominal_takes.append(self.get_team_take(cursor=cursor))\n        budget = balance = self.balance + self.receiving - self.giving\n        for take in nominal_takes:\n            nominal_amount = take['nominal_amount'] = take.pop('amount')\n            actual_amount = take['actual_amount'] = min(nominal_amount, balance)\n            if take['member'] != self.username:\n                balance -= actual_amount\n            take['balance'] = balance\n            take['percentage'] = (actual_amount / budget) if budget > 0 else 0\n            actual_takes[take['member']] = take\n        return actual_takes\n\n    def get_members(self, current_participant):\n        \"\"\"Return a list of member dicts.\n        \"\"\"\n        assert self.IS_PLURAL\n        takes = self.compute_actual_takes()\n        members = []\n        for take in takes.values():\n            member = {}\n            member['username'] = take['member']\n            member['take'] = take['nominal_amount']\n            member['balance'] = take['balance']\n            member['percentage'] = take['percentage']\n\n            member['removal_allowed'] = current_participant == self\n            member['editing_allowed'] = False\n            member['is_current_user'] = False\n            if current_participant is not None:\n                if member['username'] == current_participant.username:\n                    member['is_current_user'] = True\n                    if take['ctime'] is not None:\n                        # current user, but not the team itself\n                        member['editing_allowed']= True\n\n            member['last_week'] = last_week = self.get_take_last_week_for(member)\n            member['max_this_week'] = self.compute_max_this_week(last_week)\n            members.append(member)\n        return members\n", "path": "gratipay/models/_mixin_team.py"}], "after_files": [{"content": "\"\"\"Teams on Gratipay are plural participants with members.\n\"\"\"\nfrom collections import OrderedDict\nfrom decimal import Decimal\n\nfrom aspen.utils import typecheck\n\n\nclass MemberLimitReached(Exception): pass\n\nclass StubParticipantAdded(Exception): pass\n\nclass MixinTeam(object):\n    \"\"\"This class provides methods for working with a Participant as a Team.\n\n    :param Participant participant: the underlying :py:class:`~gratipay.participant.Participant` object for this team\n\n    \"\"\"\n\n    # XXX These were all written with the ORM and need to be converted.\n\n    def __init__(self, participant):\n        self.participant = participant\n\n    def show_as_team(self, user):\n        \"\"\"Return a boolean, whether to show this participant as a team.\n        \"\"\"\n        if not self.IS_PLURAL:\n            return False\n        if user.ADMIN:\n            return True\n        if not self.get_current_takes():\n            if self == user.participant:\n                return True\n            return False\n        return True\n\n    def add_member(self, member):\n        \"\"\"Add a member to this team.\n        \"\"\"\n        assert self.IS_PLURAL\n        if len(self.get_current_takes()) == 149:\n            raise MemberLimitReached\n        if not member.is_claimed:\n            raise StubParticipantAdded\n        self.__set_take_for(member, Decimal('0.01'), self)\n\n    def remove_member(self, member):\n        \"\"\"Remove a member from this team.\n        \"\"\"\n        assert self.IS_PLURAL\n        self.__set_take_for(member, Decimal('0.00'), self)\n\n    def remove_all_members(self, cursor=None):\n        (cursor or self.db).run(\"\"\"\n            INSERT INTO takes (ctime, member, team, amount, recorder) (\n                SELECT ctime, member, %(username)s, 0.00, %(username)s\n                  FROM current_takes\n                 WHERE team=%(username)s\n                   AND amount > 0\n            );\n        \"\"\", dict(username=self.username))\n\n    def member_of(self, team):\n        \"\"\"Given a Participant object, return a boolean.\n        \"\"\"\n        assert team.IS_PLURAL\n        for take in team.get_current_takes():\n            if take['member'] == self.username:\n                return True\n        return False\n\n    def get_take_last_week_for(self, member):\n        \"\"\"Get the user's nominal take last week. Used in throttling.\n        \"\"\"\n        assert self.IS_PLURAL\n        membername = member.username if hasattr(member, 'username') \\\n                                                        else member['username']\n        return self.db.one(\"\"\"\n\n            SELECT amount\n              FROM takes\n             WHERE team=%s AND member=%s\n               AND mtime < (\n                       SELECT ts_start\n                         FROM paydays\n                        WHERE ts_end > ts_start\n                     ORDER BY ts_start DESC LIMIT 1\n                   )\n          ORDER BY mtime DESC LIMIT 1\n\n        \"\"\", (self.username, membername), default=Decimal('0.00'))\n\n    def get_take_for(self, member):\n        \"\"\"Return a Decimal representation of the take for this member, or 0.\n        \"\"\"\n        assert self.IS_PLURAL\n        return self.db.one( \"SELECT amount FROM current_takes \"\n                            \"WHERE member=%s AND team=%s\"\n                          , (member.username, self.username)\n                          , default=Decimal('0.00')\n                           )\n\n    def compute_max_this_week(self, last_week):\n        \"\"\"2x last week's take, but at least a dollar.\n        \"\"\"\n        return max(last_week * Decimal('2'), Decimal('1.00'))\n\n    def set_take_for(self, member, take, recorder, cursor=None):\n        \"\"\"Sets member's take from the team pool.\n        \"\"\"\n        assert self.IS_PLURAL\n\n        # lazy import to avoid circular import\n        from gratipay.security.user import User\n        from gratipay.models.participant import Participant\n\n        typecheck( member, Participant\n                 , take, Decimal\n                 , recorder, (Participant, User)\n                  )\n\n        last_week = self.get_take_last_week_for(member)\n        max_this_week = self.compute_max_this_week(last_week)\n        if take > max_this_week:\n            take = max_this_week\n\n        self.__set_take_for(member, take, recorder, cursor)\n        return take\n\n    def __set_take_for(self, member, amount, recorder, cursor=None):\n        assert self.IS_PLURAL\n        # XXX Factored out for testing purposes only! :O Use .set_take_for.\n        with self.db.get_cursor(cursor) as cursor:\n            # Lock to avoid race conditions\n            cursor.run(\"LOCK TABLE takes IN EXCLUSIVE MODE\")\n            # Compute the current takes\n            old_takes = self.compute_actual_takes(cursor)\n            # Insert the new take\n            cursor.run(\"\"\"\n\n                INSERT INTO takes (ctime, member, team, amount, recorder)\n                 VALUES ( COALESCE (( SELECT ctime\n                                        FROM takes\n                                       WHERE member=%(member)s\n                                         AND team=%(team)s\n                                       LIMIT 1\n                                     ), CURRENT_TIMESTAMP)\n                        , %(member)s\n                        , %(team)s\n                        , %(amount)s\n                        , %(recorder)s\n                         )\n\n            \"\"\", dict(member=member.username, team=self.username, amount=amount,\n                      recorder=recorder.username))\n            # Compute the new takes\n            new_takes = self.compute_actual_takes(cursor)\n            # Update receiving amounts in the participants table\n            self.update_taking(old_takes, new_takes, cursor, member)\n            # Update is_funded on member's tips\n            member.update_giving(cursor)\n\n    def update_taking(self, old_takes, new_takes, cursor=None, member=None):\n        \"\"\"Update `taking` amounts based on the difference between `old_takes`\n        and `new_takes`.\n        \"\"\"\n        for username in set(old_takes.keys()).union(new_takes.keys()):\n            if username == self.username:\n                continue\n            old = old_takes.get(username, {}).get('actual_amount', Decimal(0))\n            new = new_takes.get(username, {}).get('actual_amount', Decimal(0))\n            diff = new - old\n            if diff != 0:\n                r = (cursor or self.db).one(\"\"\"\n                    UPDATE participants\n                       SET taking = (taking + %(diff)s)\n                         , receiving = (receiving + %(diff)s)\n                     WHERE username=%(username)s\n                 RETURNING taking, receiving\n                \"\"\", dict(username=username, diff=diff))\n                if member and username == member.username:\n                    member.set_attributes(**r._asdict())\n\n    def get_current_takes(self, cursor=None):\n        \"\"\"Return a list of member takes for a team.\n        \"\"\"\n        assert self.IS_PLURAL\n        TAKES = \"\"\"\n            SELECT member, amount, ctime, mtime\n              FROM current_takes\n             WHERE team=%(team)s\n          ORDER BY ctime DESC\n        \"\"\"\n        records = (cursor or self.db).all(TAKES, dict(team=self.username))\n        return [r._asdict() for r in records]\n\n    def get_team_take(self, cursor=None):\n        \"\"\"Return a single take for a team, the team itself's take.\n        \"\"\"\n        assert self.IS_PLURAL\n        TAKE = \"SELECT sum(amount) FROM current_takes WHERE team=%s\"\n        total_take = (cursor or self.db).one(TAKE, (self.username,), default=0)\n        team_take = max(self.receiving - total_take, 0)\n        membership = { \"ctime\": None\n                     , \"mtime\": None\n                     , \"member\": self.username\n                     , \"amount\": team_take\n                      }\n        return membership\n\n    def compute_actual_takes(self, cursor=None):\n        \"\"\"Get the takes, compute the actual amounts, and return an OrderedDict.\n        \"\"\"\n        actual_takes = OrderedDict()\n        nominal_takes = self.get_current_takes(cursor=cursor)\n        nominal_takes.append(self.get_team_take(cursor=cursor))\n        budget = balance = self.balance + self.receiving - self.giving\n        for take in nominal_takes:\n            nominal_amount = take['nominal_amount'] = take.pop('amount')\n            actual_amount = take['actual_amount'] = min(nominal_amount, balance)\n            if take['member'] != self.username:\n                balance -= actual_amount\n            take['balance'] = balance\n            take['percentage'] = (actual_amount / budget) if budget > 0 else 0\n            actual_takes[take['member']] = take\n        return actual_takes\n\n    def get_members(self, current_participant):\n        \"\"\"Return a list of member dicts.\n        \"\"\"\n        assert self.IS_PLURAL\n        takes = self.compute_actual_takes()\n        members = []\n        for take in takes.values():\n            member = {}\n            member['username'] = take['member']\n            member['take'] = take['nominal_amount']\n            member['balance'] = take['balance']\n            member['percentage'] = take['percentage']\n\n            member['removal_allowed'] = current_participant == self\n            member['editing_allowed'] = False\n            member['is_current_user'] = False\n            if current_participant is not None:\n                if member['username'] == current_participant.username:\n                    member['is_current_user'] = True\n                    if take['ctime'] is not None:\n                        # current user, but not the team itself\n                        member['editing_allowed']= True\n\n            member['last_week'] = last_week = self.get_take_last_week_for(member)\n            member['max_this_week'] = self.compute_max_this_week(last_week)\n            members.append(member)\n        return members\n", "path": "gratipay/models/_mixin_team.py"}]}