Exemplo n.º 1
0
def lock_bundles(cursor, transfer, bundles=None, prefer_bundles_from=-1):
    assert transfer.status == 'pre'
    tipper, tippee = transfer.tipper, transfer.tippee
    currency = transfer.amount.currency
    if bundles:
        # Refetch the bundles to ensure validity and prevent race conditions
        bundles = tuple(bundles)
        bundles = cursor.all(
            """
            SELECT b.*
              FROM cash_bundles b
             WHERE b.owner = %(tipper)s
               AND b.withdrawal IS NULL
               AND b.locked_for IS NULL
               AND b.amount::currency = %(currency)s
               AND b.id IN %(bundles)s
          ORDER BY b.ts
        """, locals())
    else:
        bundles = cursor.all(
            """
            SELECT b.*
              FROM cash_bundles b
              JOIN exchanges e ON e.id = b.origin
             WHERE b.owner = %(tipper)s
               AND b.withdrawal IS NULL
               AND b.locked_for IS NULL
               AND b.amount::currency = %(currency)s
          ORDER BY b.origin = %(prefer_bundles_from)s DESC
                 , e.participant = %(tippee)s DESC
                 , b.ts
        """, locals())
    transferable = sum(b.amount for b in bundles)
    x = transfer.amount
    if x > transferable:
        raise NegativeBalance()
    for b in bundles:
        if x >= b.amount:
            cursor.run(
                """
                UPDATE cash_bundles
                   SET locked_for = %s
                 WHERE id = %s
            """, (transfer.id, b.id))
            x -= b.amount
            if x == 0:
                break
        else:
            cursor.run(
                """
                UPDATE cash_bundles
                   SET amount = (amount - %s)
                 WHERE id = %s;

                INSERT INTO cash_bundles
                            (owner, origin, amount, ts, locked_for, wallet_id)
                     VALUES (%s, %s, %s, %s, %s, %s);
            """, (x, b.id, transfer.tipper, b.origin, x, b.ts, transfer.id,
                  b.wallet_id))
            break
Exemplo n.º 2
0
 def check_balances(cursor):
     """Check that balances aren't becoming (more) negative
     """
     oops = cursor.one("""
         SELECT p.id
              , p.username
              , p2.balances
           FROM payday_participants p2
           JOIN participants p ON p.id = p2.id
          WHERE (p2.balances).EUR < 0 OR (p2.balances).USD < 0
          LIMIT 1
     """)
     if oops:
         log(oops)
         raise NegativeBalance()
     log("Checked the balances.")
Exemplo n.º 3
0
def lock_bundles(cursor, transfer, bundles=None, prefer_bundles_from=-1):
    assert transfer.status == 'pre'
    cursor.run("LOCK TABLE cash_bundles IN EXCLUSIVE MODE")
    tipper, tippee = transfer.tipper, transfer.tippee
    currency = transfer.amount.currency
    bundles = bundles or cursor.all(
        """
        SELECT b.*
          FROM cash_bundles b
          JOIN exchanges e ON e.id = b.origin
         WHERE b.owner = %(tipper)s
           AND b.withdrawal IS NULL
           AND b.locked_for IS NULL
           AND b.amount::currency = %(currency)s
      ORDER BY b.origin = %(prefer_bundles_from)s DESC
             , e.participant = %(tippee)s DESC
             , b.ts
    """, locals())
    transferable = sum(b.amount for b in bundles)
    x = transfer.amount
    if x > transferable:
        raise NegativeBalance()
    for b in bundles:
        if x >= b.amount:
            cursor.run(
                """
                UPDATE cash_bundles
                   SET locked_for = %s
                 WHERE id = %s
            """, (transfer.id, b.id))
            x -= b.amount
            if x == 0:
                break
        else:
            cursor.run(
                """
                UPDATE cash_bundles
                   SET amount = (amount - %s)
                 WHERE id = %s;

                INSERT INTO cash_bundles
                            (owner, origin, amount, ts, locked_for, wallet_id)
                     VALUES (%s, %s, %s, %s, %s, %s);
            """, (x, b.id, transfer.tipper, b.origin, x, b.ts, transfer.id,
                  b.wallet_id))
            break
Exemplo n.º 4
0
 def check_balances(cursor):
     """Check that balances aren't becoming (more) negative
     """
     oops = cursor.one("""
         SELECT *
           FROM (
                  SELECT p.id
                       , p.username
                       , (p.balance + p2.new_balance - p2.old_balance) AS new_balance
                       , p.balance AS cur_balance
                    FROM payday_participants p2
                    JOIN participants p ON p.id = p2.id
                     AND p2.new_balance <> p2.old_balance
                ) foo
          WHERE new_balance < 0 AND new_balance < cur_balance
          LIMIT 1
     """)
     if oops:
         log(oops)
         raise NegativeBalance()
     log("Checked the balances.")