prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  break history page into multiple pages
  Each week should get its own page, with paging nav added in the box.
  
  break history page into multiple pages
  Each week should get its own page, with paging nav added in the box.
  
  Total Given on history pages for teams includes takes
  On the history pages for teams, the "Total Given" amount includes both tips to people **and** takes by members, which is not _correct_. 
  
  
  --- 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/utils/history.py`
  Content:
  ```
  1 def iter_payday_events(db, participant):
  2     """Yields payday events for the given participant.
  3     """
  4     username = participant.username
  5     exchanges = db.all("""
  6         SELECT *
  7           FROM exchanges
  8          WHERE participant=%s
  9     """, (username,), back_as=dict)
  10     transfers = db.all("""
  11         SELECT *
  12           FROM transfers
  13          WHERE tipper=%(username)s OR tippee=%(username)s
  14     """, locals(), back_as=dict)
  15 
  16     if not (exchanges or transfers):
  17         return
  18 
  19     if transfers:
  20         yield dict(
  21             kind='totals',
  22             given=sum(t['amount'] for t in transfers if t['tipper'] == username),
  23             received=sum(t['amount'] for t in transfers if t['tippee'] == username),
  24         )
  25 
  26     payday_dates = db.all("""
  27         SELECT ts_start::date
  28           FROM paydays
  29       ORDER BY ts_start ASC
  30     """)
  31 
  32     balance = participant.balance
  33     prev_date = None
  34     get_timestamp = lambda e: e['timestamp']
  35     events = sorted(exchanges+transfers, key=get_timestamp, reverse=True)
  36     for event in events:
  37 
  38         event['balance'] = balance
  39 
  40         event_date = event['timestamp'].date()
  41         if event_date != prev_date:
  42             if prev_date:
  43                 yield dict(kind='day-close', balance=balance)
  44             day_open = dict(kind='day-open', date=event_date, balance=balance)
  45             if payday_dates:
  46                 while payday_dates and payday_dates[-1] > event_date:
  47                     payday_dates.pop()
  48                 payday_date = payday_dates[-1] if payday_dates else None
  49                 if event_date == payday_date:
  50                     day_open['payday_number'] = len(payday_dates) - 1
  51             yield day_open
  52             prev_date = event_date
  53 
  54         if 'fee' in event:
  55             if event['amount'] > 0:
  56                 kind = 'charge'
  57                 if event['status'] in (None, 'succeeded'):
  58                     balance -= event['amount']
  59             else:
  60                 kind = 'credit'
  61                 if event['status'] != 'failed':
  62                     balance -= event['amount'] - event['fee']
  63         else:
  64             kind = 'transfer'
  65             if event['tippee'] == username:
  66                 balance -= event['amount']
  67             else:
  68                 balance += event['amount']
  69         event['kind'] = kind
  70 
  71         yield event
  72 
  73     yield dict(kind='day-close', balance='0.00')
  74
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/gratipay/utils/history.py b/gratipay/utils/history.py
  --- a/gratipay/utils/history.py
  +++ b/gratipay/utils/history.py
  @@ -1,16 +1,83 @@
  -def iter_payday_events(db, participant):
  +from datetime import datetime
  +from decimal import Decimal
  +
  +from psycopg2 import IntegrityError
  +
  +
  +def get_end_of_year_balance(db, participant, year, current_year):
  +    if year == current_year:
  +        return participant.balance
  +    if year < participant.claimed_time.year:
  +        return Decimal('0.00')
  +
  +    balance = db.one("""
  +        SELECT balance
  +          FROM balances_at
  +         WHERE participant = %s
  +           AND "at" = %s
  +    """, (participant.id, datetime(year+1, 1, 1)))
  +    if balance is not None:
  +        return balance
  +
  +    username = participant.username
  +    start_balance = get_end_of_year_balance(db, participant, year-1, current_year)
  +    delta = db.one("""
  +        SELECT (
  +                  SELECT COALESCE(sum(amount), 0) AS a
  +                    FROM exchanges
  +                   WHERE participant = %(username)s
  +                     AND extract(year from timestamp) = %(year)s
  +                     AND amount > 0
  +                     AND (status is null OR status = 'succeeded')
  +               ) + (
  +                  SELECT COALESCE(sum(amount-fee), 0) AS a
  +                    FROM exchanges
  +                   WHERE participant = %(username)s
  +                     AND extract(year from timestamp) = %(year)s
  +                     AND amount < 0
  +                     AND (status is null OR status <> 'failed')
  +               ) + (
  +                  SELECT COALESCE(sum(-amount), 0) AS a
  +                    FROM transfers
  +                   WHERE tipper = %(username)s
  +                     AND extract(year from timestamp) = %(year)s
  +               ) + (
  +                  SELECT COALESCE(sum(amount), 0) AS a
  +                    FROM transfers
  +                   WHERE tippee = %(username)s
  +                     AND extract(year from timestamp) = %(year)s
  +               ) AS delta
  +    """, locals())
  +    balance = start_balance + delta
  +    try:
  +        db.run("""
  +            INSERT INTO balances_at
  +                        (participant, at, balance)
  +                 VALUES (%s, %s, %s)
  +        """, (participant.id, datetime(year+1, 1, 1), balance))
  +    except IntegrityError:
  +        pass
  +    return balance
  +
  +
  +def iter_payday_events(db, participant, year=None):
       """Yields payday events for the given participant.
       """
  +    current_year = datetime.utcnow().year
  +    year = year or current_year
  +
       username = participant.username
       exchanges = db.all("""
           SELECT *
             FROM exchanges
  -         WHERE participant=%s
  -    """, (username,), back_as=dict)
  +         WHERE participant=%(username)s
  +           AND extract(year from timestamp) = %(year)s
  +    """, locals(), back_as=dict)
       transfers = db.all("""
           SELECT *
             FROM transfers
  -         WHERE tipper=%(username)s OR tippee=%(username)s
  +         WHERE (tipper=%(username)s OR tippee=%(username)s)
  +           AND extract(year from timestamp) = %(year)s
       """, locals(), back_as=dict)
   
       if not (exchanges or transfers):
  @@ -19,7 +86,7 @@
       if transfers:
           yield dict(
               kind='totals',
  -            given=sum(t['amount'] for t in transfers if t['tipper'] == username),
  +            given=sum(t['amount'] for t in transfers if t['tipper'] == username and t['context'] != 'take'),
               received=sum(t['amount'] for t in transfers if t['tippee'] == username),
           )
   
  @@ -29,7 +96,7 @@
         ORDER BY ts_start ASC
       """)
   
  -    balance = participant.balance
  +    balance = get_end_of_year_balance(db, participant, year, current_year)
       prev_date = None
       get_timestamp = lambda e: e['timestamp']
       events = sorted(exchanges+transfers, key=get_timestamp, reverse=True)
  @@ -70,4 +137,4 @@
   
           yield event
   
  -    yield dict(kind='day-close', balance='0.00')
  +    yield dict(kind='day-close', balance=balance)
  
verification_info: {"golden_diff": "diff --git a/gratipay/utils/history.py b/gratipay/utils/history.py\n--- a/gratipay/utils/history.py\n+++ b/gratipay/utils/history.py\n@@ -1,16 +1,83 @@\n-def iter_payday_events(db, participant):\n+from datetime import datetime\n+from decimal import Decimal\n+\n+from psycopg2 import IntegrityError\n+\n+\n+def get_end_of_year_balance(db, participant, year, current_year):\n+    if year == current_year:\n+        return participant.balance\n+    if year < participant.claimed_time.year:\n+        return Decimal('0.00')\n+\n+    balance = db.one(\"\"\"\n+        SELECT balance\n+          FROM balances_at\n+         WHERE participant = %s\n+           AND \"at\" = %s\n+    \"\"\", (participant.id, datetime(year+1, 1, 1)))\n+    if balance is not None:\n+        return balance\n+\n+    username = participant.username\n+    start_balance = get_end_of_year_balance(db, participant, year-1, current_year)\n+    delta = db.one(\"\"\"\n+        SELECT (\n+                  SELECT COALESCE(sum(amount), 0) AS a\n+                    FROM exchanges\n+                   WHERE participant = %(username)s\n+                     AND extract(year from timestamp) = %(year)s\n+                     AND amount > 0\n+                     AND (status is null OR status = 'succeeded')\n+               ) + (\n+                  SELECT COALESCE(sum(amount-fee), 0) AS a\n+                    FROM exchanges\n+                   WHERE participant = %(username)s\n+                     AND extract(year from timestamp) = %(year)s\n+                     AND amount < 0\n+                     AND (status is null OR status <> 'failed')\n+               ) + (\n+                  SELECT COALESCE(sum(-amount), 0) AS a\n+                    FROM transfers\n+                   WHERE tipper = %(username)s\n+                     AND extract(year from timestamp) = %(year)s\n+               ) + (\n+                  SELECT COALESCE(sum(amount), 0) AS a\n+                    FROM transfers\n+                   WHERE tippee = %(username)s\n+                     AND extract(year from timestamp) = %(year)s\n+               ) AS delta\n+    \"\"\", locals())\n+    balance = start_balance + delta\n+    try:\n+        db.run(\"\"\"\n+            INSERT INTO balances_at\n+                        (participant, at, balance)\n+                 VALUES (%s, %s, %s)\n+        \"\"\", (participant.id, datetime(year+1, 1, 1), balance))\n+    except IntegrityError:\n+        pass\n+    return balance\n+\n+\n+def iter_payday_events(db, participant, year=None):\n     \"\"\"Yields payday events for the given participant.\n     \"\"\"\n+    current_year = datetime.utcnow().year\n+    year = year or current_year\n+\n     username = participant.username\n     exchanges = db.all(\"\"\"\n         SELECT *\n           FROM exchanges\n-         WHERE participant=%s\n-    \"\"\", (username,), back_as=dict)\n+         WHERE participant=%(username)s\n+           AND extract(year from timestamp) = %(year)s\n+    \"\"\", locals(), back_as=dict)\n     transfers = db.all(\"\"\"\n         SELECT *\n           FROM transfers\n-         WHERE tipper=%(username)s OR tippee=%(username)s\n+         WHERE (tipper=%(username)s OR tippee=%(username)s)\n+           AND extract(year from timestamp) = %(year)s\n     \"\"\", locals(), back_as=dict)\n \n     if not (exchanges or transfers):\n@@ -19,7 +86,7 @@\n     if transfers:\n         yield dict(\n             kind='totals',\n-            given=sum(t['amount'] for t in transfers if t['tipper'] == username),\n+            given=sum(t['amount'] for t in transfers if t['tipper'] == username and t['context'] != 'take'),\n             received=sum(t['amount'] for t in transfers if t['tippee'] == username),\n         )\n \n@@ -29,7 +96,7 @@\n       ORDER BY ts_start ASC\n     \"\"\")\n \n-    balance = participant.balance\n+    balance = get_end_of_year_balance(db, participant, year, current_year)\n     prev_date = None\n     get_timestamp = lambda e: e['timestamp']\n     events = sorted(exchanges+transfers, key=get_timestamp, reverse=True)\n@@ -70,4 +137,4 @@\n \n         yield event\n \n-    yield dict(kind='day-close', balance='0.00')\n+    yield dict(kind='day-close', balance=balance)\n", "issue": "break history page into multiple pages\nEach week should get its own page, with paging nav added in the box.\n\nbreak history page into multiple pages\nEach week should get its own page, with paging nav added in the box.\n\nTotal Given on history pages for teams includes takes\nOn the history pages for teams, the \"Total Given\" amount includes both tips to people **and** takes by members, which is not _correct_. \n\n", "before_files": [{"content": "def iter_payday_events(db, participant):\n    \"\"\"Yields payday events for the given participant.\n    \"\"\"\n    username = participant.username\n    exchanges = db.all(\"\"\"\n        SELECT *\n          FROM exchanges\n         WHERE participant=%s\n    \"\"\", (username,), back_as=dict)\n    transfers = db.all(\"\"\"\n        SELECT *\n          FROM transfers\n         WHERE tipper=%(username)s OR tippee=%(username)s\n    \"\"\", locals(), back_as=dict)\n\n    if not (exchanges or transfers):\n        return\n\n    if transfers:\n        yield dict(\n            kind='totals',\n            given=sum(t['amount'] for t in transfers if t['tipper'] == username),\n            received=sum(t['amount'] for t in transfers if t['tippee'] == username),\n        )\n\n    payday_dates = db.all(\"\"\"\n        SELECT ts_start::date\n          FROM paydays\n      ORDER BY ts_start ASC\n    \"\"\")\n\n    balance = participant.balance\n    prev_date = None\n    get_timestamp = lambda e: e['timestamp']\n    events = sorted(exchanges+transfers, key=get_timestamp, reverse=True)\n    for event in events:\n\n        event['balance'] = balance\n\n        event_date = event['timestamp'].date()\n        if event_date != prev_date:\n            if prev_date:\n                yield dict(kind='day-close', balance=balance)\n            day_open = dict(kind='day-open', date=event_date, balance=balance)\n            if payday_dates:\n                while payday_dates and payday_dates[-1] > event_date:\n                    payday_dates.pop()\n                payday_date = payday_dates[-1] if payday_dates else None\n                if event_date == payday_date:\n                    day_open['payday_number'] = len(payday_dates) - 1\n            yield day_open\n            prev_date = event_date\n\n        if 'fee' in event:\n            if event['amount'] > 0:\n                kind = 'charge'\n                if event['status'] in (None, 'succeeded'):\n                    balance -= event['amount']\n            else:\n                kind = 'credit'\n                if event['status'] != 'failed':\n                    balance -= event['amount'] - event['fee']\n        else:\n            kind = 'transfer'\n            if event['tippee'] == username:\n                balance -= event['amount']\n            else:\n                balance += event['amount']\n        event['kind'] = kind\n\n        yield event\n\n    yield dict(kind='day-close', balance='0.00')\n", "path": "gratipay/utils/history.py"}], "after_files": [{"content": "from datetime import datetime\nfrom decimal import Decimal\n\nfrom psycopg2 import IntegrityError\n\n\ndef get_end_of_year_balance(db, participant, year, current_year):\n    if year == current_year:\n        return participant.balance\n    if year < participant.claimed_time.year:\n        return Decimal('0.00')\n\n    balance = db.one(\"\"\"\n        SELECT balance\n          FROM balances_at\n         WHERE participant = %s\n           AND \"at\" = %s\n    \"\"\", (participant.id, datetime(year+1, 1, 1)))\n    if balance is not None:\n        return balance\n\n    username = participant.username\n    start_balance = get_end_of_year_balance(db, participant, year-1, current_year)\n    delta = db.one(\"\"\"\n        SELECT (\n                  SELECT COALESCE(sum(amount), 0) AS a\n                    FROM exchanges\n                   WHERE participant = %(username)s\n                     AND extract(year from timestamp) = %(year)s\n                     AND amount > 0\n                     AND (status is null OR status = 'succeeded')\n               ) + (\n                  SELECT COALESCE(sum(amount-fee), 0) AS a\n                    FROM exchanges\n                   WHERE participant = %(username)s\n                     AND extract(year from timestamp) = %(year)s\n                     AND amount < 0\n                     AND (status is null OR status <> 'failed')\n               ) + (\n                  SELECT COALESCE(sum(-amount), 0) AS a\n                    FROM transfers\n                   WHERE tipper = %(username)s\n                     AND extract(year from timestamp) = %(year)s\n               ) + (\n                  SELECT COALESCE(sum(amount), 0) AS a\n                    FROM transfers\n                   WHERE tippee = %(username)s\n                     AND extract(year from timestamp) = %(year)s\n               ) AS delta\n    \"\"\", locals())\n    balance = start_balance + delta\n    try:\n        db.run(\"\"\"\n            INSERT INTO balances_at\n                        (participant, at, balance)\n                 VALUES (%s, %s, %s)\n        \"\"\", (participant.id, datetime(year+1, 1, 1), balance))\n    except IntegrityError:\n        pass\n    return balance\n\n\ndef iter_payday_events(db, participant, year=None):\n    \"\"\"Yields payday events for the given participant.\n    \"\"\"\n    current_year = datetime.utcnow().year\n    year = year or current_year\n\n    username = participant.username\n    exchanges = db.all(\"\"\"\n        SELECT *\n          FROM exchanges\n         WHERE participant=%(username)s\n           AND extract(year from timestamp) = %(year)s\n    \"\"\", locals(), back_as=dict)\n    transfers = db.all(\"\"\"\n        SELECT *\n          FROM transfers\n         WHERE (tipper=%(username)s OR tippee=%(username)s)\n           AND extract(year from timestamp) = %(year)s\n    \"\"\", locals(), back_as=dict)\n\n    if not (exchanges or transfers):\n        return\n\n    if transfers:\n        yield dict(\n            kind='totals',\n            given=sum(t['amount'] for t in transfers if t['tipper'] == username and t['context'] != 'take'),\n            received=sum(t['amount'] for t in transfers if t['tippee'] == username),\n        )\n\n    payday_dates = db.all(\"\"\"\n        SELECT ts_start::date\n          FROM paydays\n      ORDER BY ts_start ASC\n    \"\"\")\n\n    balance = get_end_of_year_balance(db, participant, year, current_year)\n    prev_date = None\n    get_timestamp = lambda e: e['timestamp']\n    events = sorted(exchanges+transfers, key=get_timestamp, reverse=True)\n    for event in events:\n\n        event['balance'] = balance\n\n        event_date = event['timestamp'].date()\n        if event_date != prev_date:\n            if prev_date:\n                yield dict(kind='day-close', balance=balance)\n            day_open = dict(kind='day-open', date=event_date, balance=balance)\n            if payday_dates:\n                while payday_dates and payday_dates[-1] > event_date:\n                    payday_dates.pop()\n                payday_date = payday_dates[-1] if payday_dates else None\n                if event_date == payday_date:\n                    day_open['payday_number'] = len(payday_dates) - 1\n            yield day_open\n            prev_date = event_date\n\n        if 'fee' in event:\n            if event['amount'] > 0:\n                kind = 'charge'\n                if event['status'] in (None, 'succeeded'):\n                    balance -= event['amount']\n            else:\n                kind = 'credit'\n                if event['status'] != 'failed':\n                    balance -= event['amount'] - event['fee']\n        else:\n            kind = 'transfer'\n            if event['tippee'] == username:\n                balance -= event['amount']\n            else:\n                balance += event['amount']\n        event['kind'] = kind\n\n        yield event\n\n    yield dict(kind='day-close', balance=balance)\n", "path": "gratipay/utils/history.py"}]}