Repository: gratipay/gratipay.com

Issue:
Handle takes properly when account is changed from team to individual
@benhc123 did some poking around and discovered this : 

> If you've joined something while it's a team and then it becomes an individual it goes wrong! You can't close the account of the joined member.

Details from Sentry: 

```
Stacktrace (most recent call last):

  File "site-packages/algorithm.py", line 288, in run
    new_state = function(**deps.as_kwargs)
  File "aspen/algorithms/website.py", line 97, in get_response_for_resource
    return {'response': resource.respond(request, dispatch_result)}
  File "aspen/resources/dynamic_resource.py", line 56, in respond
    exec self.pages[1] in context
  File "/app/www/%username/account/close.spt", line 23, in <module>
    participant.close(disbursement_strategy)
  File "gratipay/models/participant.py", line 304, in close
    self.clear_personal_information(cursor)
  File "gratipay/models/participant.py", line 412, in clear_personal_information
    self.clear_takes(cursor)
  File "gratipay/models/participant.py", line 404, in clear_takes
    t.set_take_for(self, Decimal(0), self, cursor)
  File "gratipay/models/_mixin_team.py", line 112, in set_take_for
    assert self.IS_PLURAL
```



Discussion:

Resolving patch:
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
@@ -226,7 +226,16 @@ def compute_actual_takes(self, cursor=None):
             actual_takes[take['member']] = take
         return actual_takes
 
-    def get_members(self, current_participant):
+    @property
+    def nmembers(self):
+        assert self.IS_PLURAL
+        return self.db.one("""
+            SELECT COUNT(*)
+              FROM current_takes
+             WHERE team=%s
+        """, (self.username, ))
+
+    def get_members(self, current_participant=None):
         """Return a list of member dicts.
         """
         assert self.IS_PLURAL
diff --git a/gratipay/models/participant.py b/gratipay/models/participant.py
--- a/gratipay/models/participant.py
+++ b/gratipay/models/participant.py
@@ -202,6 +202,7 @@ def update_number(self, number):
                 raise HasBigTips
         with self.db.get_cursor() as c:
             add_event(c, 'participant', dict(action='set', id=self.id, values=dict(number=number)))
+            self.remove_all_members(c)
             c.execute( "UPDATE participants SET number=%s WHERE id=%s"
                      , (number, self.id)
                       )


Test patch:
diff --git a/tests/py/test_participant.py b/tests/py/test_participant.py
--- a/tests/py/test_participant.py
+++ b/tests/py/test_participant.py
@@ -437,6 +437,13 @@ def test_can_go_singular_without_big_tips(self):
         bob.update_number('singular')
         assert Participant.from_username('bob').number == 'singular'
 
+    def test_going_singular_clears_takes(self):
+        team = self.make_participant('team', number='plural')
+        alice = self.make_participant('alice', claimed_time='now', last_bill_result='')
+        team.set_take_for(alice, Decimal('10'), alice)
+        team.update_number('singular')
+        assert Participant.from_username('alice').get_teams() == []
+
     def test_can_go_plural(self):
         alice = self.make_participant('alice', claimed_time='now', last_bill_result='')
         bob = self.make_participant('bob')