Module ImportFrom alias Import alias Import alias Import alias Import alias ImportFrom alias ImportFrom alias ImportFrom alias ImportFrom alias ImportFrom alias ImportFrom alias ImportFrom alias ClassDef bases NameLoad body Assign NameStore Lambda arguments args NameParam defaults Str decorator_list ClassDef bases NameLoad body FunctionDef arguments args NameParam NameParam defaults body Expr Call AttributeLoad AttributeLoad NameLoad attr attr NameLoad decorator_list decorator_list ClassDef bases NameLoad body FunctionDef arguments args NameParam defaults body Expr Str TryExcept body Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Str keyword NameLoad Expr Call NameLoad BinOpMod Str SubscriptLoad NameLoad Index Str handlers ExceptHandler type NameLoad body Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Str keyword NameLoad Expr Call NameLoad BinOpMod Str SubscriptLoad NameLoad Index Str Assign SubscriptStore NameLoad Index Str Call AttributeLoad SubscriptLoad NameLoad Index Str attr keyword AttributeLoad AttributeLoad NameLoad attr attr Expr Call NameLoad BinOpMod Str SubscriptLoad NameLoad Index Str Assign NameStore Call NameLoad Expr Call AttributeLoad AttributeLoad NameLoad attr attr NameLoad Return NameLoad decorator_list NameLoad FunctionDef arguments args NameParam NameParam NameParam defaults Str NameLoad body Expr Str Expr Call AttributeLoad AttributeLoad NameLoad attr attr Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Expr Call NameLoad Str Expr Call AttributeLoad NameLoad attr NameLoad Expr Call AttributeLoad NameLoad attr Expr Call AttributeLoad NameLoad attr Expr Call AttributeLoad NameLoad attr Expr Call AttributeLoad NameLoad attr If UnaryOpNot NameLoad body Expr Call AttributeLoad NameLoad attr AttributeLoad NameLoad attr Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Assign NameStore BinOpSub NameLoad NameLoad Assign NameStore BinOpMod Str NameLoad Expr Call NameLoad Call AttributeLoad AttributeLoad NameLoad attr attr NameLoad keyword NameLoad decorator_list FunctionDef arguments args NameParam NameParam defaults Str body Assign AttributeStore NameLoad attr BinOpAdd NameLoad BinOpMod Str AttributeLoad NameLoad attr If Call AttributeLoad AttributeLoad NameLoad attr attr AttributeLoad NameLoad attr body With Call NameLoad AttributeLoad NameLoad attr Str NameStore body Assign NameStore Call AttributeLoad NameLoad attr NameLoad Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Str Call NameLoad keyword AttributeLoad NameLoad attr Assign NameStore Call NameLoad GeneratorExp TupleLoad AttributeLoad NameLoad attr AttributeLoad NameLoad attr AttributeLoad NameLoad attr AttributeLoad NameLoad attr comprehension NameStore NameLoad Assign NameStore ListComp NameLoad comprehension NameStore NameLoad CompareNotIn TupleLoad AttributeLoad NameLoad attr AttributeLoad NameLoad attr AttributeLoad NameLoad attr AttributeLoad NameLoad attr NameLoad orelse With Call AttributeLoad AttributeLoad NameLoad attr attr NameStore body Expr Call AttributeLoad NameLoad attr NameLoad AttributeLoad NameLoad attr Expr Call AttributeLoad NameLoad attr NameLoad Assign NameStore ListComp Call NameLoad Call AttributeLoad NameLoad attr comprehension NameStore Call AttributeLoad NameLoad attr Str Expr Call AttributeLoad NameLoad attr NameLoad With Call NameLoad AttributeLoad NameLoad attr Str NameStore body Expr Call AttributeLoad NameLoad attr NameLoad NameLoad If CompareGt AttributeLoad NameLoad attr Num body Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Str TupleLoad BinOpSub AttributeLoad NameLoad attr Num orelse Assign NameStore AttributeLoad NameLoad attr Assert NameLoad Assign NameStore AttributeLoad NameLoad attr Expr Call AttributeLoad NameLoad attr Str Call NameLoad Expr Call AttributeLoad NameLoad attr Expr Call AttributeLoad NameLoad attr NameLoad Expr Call AttributeLoad AttributeLoad NameLoad attr attr decorator_list FunctionDef arguments args NameParam NameParam defaults body Expr Str Expr Call AttributeLoad NameLoad attr Str Call NameLoad keyword NameLoad Expr Call NameLoad Str decorator_list NameLoad FunctionDef arguments args NameParam defaults body Expr Call AttributeLoad NameLoad attr Str decorator_list NameLoad FunctionDef arguments args NameParam defaults body Expr Str Assign NameStore Call AttributeLoad NameLoad attr Str If NameLoad body Expr Call NameLoad NameLoad Raise Call NameLoad Expr Call NameLoad Str decorator_list NameLoad FunctionDef arguments args NameParam NameParam defaults body Assign NameStore AttributeLoad NameLoad attr For NameStore NameLoad body Expr Call NameLoad NameLoad AttributeLoad NameLoad attr decorator_list FunctionDef arguments args NameParam defaults body Expr Call AttributeLoad AttributeLoad NameLoad attr attr Str decorator_list FunctionDef arguments args NameParam defaults body Expr Call AttributeLoad AttributeLoad NameLoad attr attr Str Dict Str AttributeLoad NameLoad attr Expr Call NameLoad Str decorator_list FunctionDef arguments args NameParam defaults body Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr With Call AttributeLoad AttributeLoad NameLoad attr attr NameStore body Expr Call AttributeLoad NameLoad attr NameLoad NameLoad Expr Call AttributeLoad NameLoad attr NameLoad Expr Call AttributeLoad NameLoad attr Str Expr Call AttributeLoad NameLoad attr Expr Call NameLoad Str decorator_list FunctionDef arguments args NameParam defaults body Assign AttributeStore NameLoad attr Call AttributeLoad Call AttributeLoad AttributeLoad NameLoad attr attr Str keyword NameLoad attr keyword AttributeLoad AttributeLoad NameLoad attr attr decorator_list FunctionDef arguments args NameParam defaults body Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Str TupleLoad AttributeLoad NameLoad attr keyword AttributeLoad NameLoad attr Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Str TupleLoad NameLoad AttributeLoad NameLoad attr For TupleStore NameStore NameStore NameLoad body Assign NameStore ListComp NameLoad comprehension NameStore NameLoad CompareEq SubscriptLoad NameLoad Index Str Str If UnaryOpNot NameLoad body Continue Assign NameStore DictComp NameLoad Call NameLoad GeneratorExp SubscriptLoad NameLoad Index Str comprehension NameStore NameLoad comprehension TupleStore NameStore NameStore Call AttributeLoad Call NameLoad NameLoad Str attr Assign NameStore Call AttributeLoad NameLoad attr NameLoad Num Assign NameStore DictComp AttributeLoad Call AttributeLoad NameLoad attr NameLoad attr NameLoad comprehension TupleStore NameStore NameStore Call AttributeLoad NameLoad attr Expr Call AttributeLoad Call AttributeLoad NameLoad attr NameLoad attr Str keyword Call NameLoad GeneratorExp SubscriptLoad NameLoad Index Str comprehension NameStore NameLoad keyword NameLoad keyword NameLoad Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Str For NameStore NameLoad body Expr Call AttributeLoad NameLoad attr Str keyword NameLoad Assign NameStore Call AttributeLoad AttributeLoad NameLoad attr attr Str TupleLoad NameLoad AttributeLoad NameLoad attr For NameStore NameLoad body Expr Call AttributeLoad NameLoad attr Str decorator_list decorator_list FunctionDef arguments args defaults body ImportFrom alias ImportFrom alias ImportFrom alias ImportFrom alias If CompareEq AttributeLoad AttributeLoad NameLoad attr attr Str body Assign NameStore SubscriptLoad NameLoad Index Str Assign NameStore NameLoad orelse Assign NameStore Str Assign NameStore NameLoad TryExcept body Expr Call NameLoad AttributeLoad NameLoad attr Expr Call AttributeLoad Call AttributeLoad NameLoad attr attr NameLoad NameLoad handlers ExceptHandler type NameLoad body Pass ExceptHandler body Import alias Expr Call AttributeLoad NameLoad attr decorator_list If CompareEq NameLoad Str body Expr Call NameLoad
N/A __future__ unicode_literals N/A os N/A os.path N/A pickle N/A aspen.utils aspen log psycopg2 IntegrityError liberapay constants liberapay.billing.exchanges transfer liberapay.exceptions NegativeBalance liberapay.models.participant Participant liberapay.utils group_by NoPayday N/A Exception N/A N/A __str__ N/A N/A N/A self N/A No payday found where one was expected. N/A NS N/A object N/A __init__ N/A N/A self d N/A N/A N/A N/A N/A N/A self __dict__ update d N/A N/A Payday N/A object N/A start N/A N/A cls N/A N/A N/A Try to start a new Payday.

        If there is a Payday that hasn't finished yet, then the UNIQUE
        constraint on ts_end will kick in and notify us of that. In that case
        we load the existing Payday and work on it some more. We use the start
        time of the current Payday to synchronize our work.

         N/A N/A N/A d N/A N/A N/A cls db one 
                INSERT INTO paydays (id) VALUES (COALESCE((
                     SELECT id
                       FROM paydays
                   ORDER BY id DESC
                      LIMIT 1
                ), 0) + 1)
                RETURNING id, (ts_start AT TIME ZONE 'UTC') AS ts_start
             back_as dict N/A N/A log N/A Starting payday #%s. N/A d N/A id N/A N/A N/A IntegrityError N/A N/A d N/A N/A N/A cls db one 
                SELECT id, (ts_start AT TIME ZONE 'UTC') AS ts_start
                  FROM paydays
                 WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz
             back_as dict N/A N/A log N/A Picking up payday #%s. N/A d N/A id N/A N/A d N/A ts_start N/A N/A N/A d N/A ts_start replace tzinfo N/A N/A aspen utils utc N/A N/A log N/A Payday started at %s. N/A d N/A ts_start N/A payday N/A Payday N/A N/A N/A N/A payday __dict__ update d N/A payday N/A classmethod run N/A N/A self log_dir keep_log N/A False N/A N/A This is the starting point for payday.

        It is structured such that it can be run again safely (with a
        newly-instantiated Payday object) if it crashes.

         N/A N/A N/A N/A self db self_check N/A _start N/A N/A N/A aspen utils utcnow N/A N/A log Greetings, program! It's PAYDAY!!!! N/A N/A N/A self shuffle log_dir N/A N/A N/A self update_stats N/A N/A N/A self update_cached_amounts N/A N/A N/A self end N/A N/A N/A self notify_participants N/A N/A keep_log N/A N/A N/A N/A os unlink N/A self transfers_filename N/A _end N/A N/A N/A aspen utils utcnow N/A _delta N/A _end _start N/A fmt_past N/A Script ran for %%(age)s (%s). _delta N/A N/A log N/A N/A N/A aspen utils to_age _start fmt_past fmt_past N/A shuffle N/A N/A self log_dir N/A N/A N/A N/A self transfers_filename N/A log_dir N/A payday-%s_transfers.pickle N/A self id N/A N/A N/A N/A os path exists N/A self transfers_filename N/A N/A N/A open N/A self transfers_filename rb f N/A N/A transfers N/A N/A pickle load f N/A done N/A N/A N/A self db all 
                SELECT *
                  FROM transfers t
                 WHERE t.timestamp >= %(ts_start)s;
             N/A dict ts_start N/A self ts_start N/A done N/A set N/A N/A N/A t tipper N/A t tippee N/A t context N/A t team N/A t done N/A transfers N/A t N/A t transfers N/A N/A N/A t tipper N/A t tippee N/A t context N/A t team done N/A N/A N/A N/A N/A self db get_cursor cursor N/A N/A N/A N/A self prepare cursor N/A self ts_start N/A N/A N/A self transfer_virtually cursor N/A transfers N/A N/A NS N/A N/A t _asdict N/A t N/A N/A cursor all 
                    SELECT t.*
                         , p.mangopay_user_id AS tipper_mango_id
                         , p2.mangopay_user_id AS tippee_mango_id
                         , p.mangopay_wallet_id AS tipper_wallet_id
                         , p2.mangopay_wallet_id AS tippee_wallet_id
                      FROM payday_transfers t
                      JOIN participants p ON p.id = t.tipper
                      JOIN participants p2 ON p2.id = t.tippee
                 N/A N/A N/A self check_balances cursor N/A N/A open N/A self transfers_filename wb f N/A N/A N/A N/A pickle dump transfers f N/A N/A N/A self id 1 N/A N/A previous_ts_start N/A N/A N/A self db one 
                        SELECT ts_start
                          FROM paydays
                         WHERE id = %s
                     N/A N/A N/A self id 1 N/A N/A previous_ts_start N/A constants EPOCH N/A previous_ts_start N/A ts_start N/A self ts_start N/A N/A N/A cursor run 
                    WITH week_exchanges AS (
                             SELECT e.*
                               FROM exchanges e
                              WHERE e.timestamp < %(ts_start)s
                                AND e.timestamp >= %(previous_ts_start)s
                                AND status <> 'failed'
                         )
                    UPDATE paydays
                       SET nparticipants = (SELECT count(*) FROM payday_participants)
                         , nusers = (
                               SELECT count(*)
                                 FROM participants
                                WHERE kind IN ('individual', 'organization')
                                  AND join_time < %(ts_start)s
                                  AND status = 'active'
                           )
                         , week_deposits = (
                               SELECT COALESCE(sum(amount), 0)
                                 FROM week_exchanges
                                WHERE amount > 0
                           )
                         , week_withdrawals = (
                               SELECT COALESCE(-sum(amount), 0)
                                 FROM week_exchanges
                                WHERE amount < 0
                           )
                     WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz;
                 N/A locals N/A N/A N/A self clean_up N/A N/A N/A self transfer_for_real transfers N/A N/A N/A N/A self db self_check N/A prepare N/A N/A cursor ts_start N/A N/A N/A Prepare the DB: we need temporary tables with indexes and triggers.
         N/A N/A N/A cursor run 

        -- Create the necessary temporary tables and indexes

        CREATE TEMPORARY TABLE payday_participants ON COMMIT DROP AS
            SELECT id
                 , username
                 , join_time
                 , balance AS old_balance
                 , balance AS new_balance
                 , goal
                 , kind
              FROM participants p
             WHERE join_time < %(ts_start)s
               AND (mangopay_user_id IS NOT NULL OR kind = 'group')
          ORDER BY join_time;

        CREATE UNIQUE INDEX ON payday_participants (id);

        CREATE TEMPORARY TABLE payday_tips ON COMMIT DROP AS
            SELECT t.id, tipper, tippee, amount, (p2.kind = 'group') AS to_team
              FROM ( SELECT DISTINCT ON (tipper, tippee) *
                       FROM tips
                      WHERE mtime < %(ts_start)s
                   ORDER BY tipper, tippee, mtime DESC
                   ) t
              JOIN payday_participants p ON p.id = t.tipper
              JOIN payday_participants p2 ON p2.id = t.tippee
             WHERE t.amount > 0
               AND (p2.goal IS NULL or p2.goal >= 0)
          ORDER BY p.join_time ASC, t.ctime ASC;

        CREATE INDEX ON payday_tips (tipper);
        CREATE INDEX ON payday_tips (tippee);
        ALTER TABLE payday_tips ADD COLUMN is_funded boolean;

        CREATE TEMPORARY TABLE payday_takes ON COMMIT DROP AS
            SELECT team, member, amount
              FROM ( SELECT DISTINCT ON (team, member)
                            team, member, amount
                       FROM takes
                      WHERE mtime < %(ts_start)s
                   ORDER BY team, member, mtime DESC
                   ) t
             WHERE t.amount IS NOT NULL
               AND t.amount > 0
               AND t.team IN (SELECT id FROM payday_participants)
               AND t.member IN (SELECT id FROM payday_participants);

        CREATE UNIQUE INDEX ON payday_takes (team, member);

        CREATE TEMPORARY TABLE payday_transfers
        ( timestamp timestamptz DEFAULT now()
        , tipper bigint
        , tippee bigint
        , amount numeric(35,2)
        , context transfer_context
        , team bigint
        , UNIQUE (tipper, tippee, context, team)
        ) ON COMMIT DROP;


        -- Prepare a statement that makes and records a transfer

        CREATE OR REPLACE FUNCTION transfer(bigint, bigint, numeric, transfer_context, bigint)
        RETURNS void AS $$
            BEGIN
                IF ($3 = 0) THEN RETURN; END IF;
                UPDATE payday_participants
                   SET new_balance = (new_balance - $3)
                 WHERE id = $1;
                IF (NOT FOUND) THEN RAISE 'tipper %% not found', $1; END IF;
                UPDATE payday_participants
                   SET new_balance = (new_balance + $3)
                 WHERE id = $2;
                IF (NOT FOUND) THEN RAISE 'tippee %% not found', $2; END IF;
                INSERT INTO payday_transfers
                            (tipper, tippee, amount, context, team)
                     VALUES ($1, $2, $3, $4, $5);
            END;
        $$ LANGUAGE plpgsql;


        -- Create a trigger to process tips

        CREATE OR REPLACE FUNCTION process_tip() RETURNS trigger AS $$
            DECLARE
                tipper payday_participants;
            BEGIN
                tipper := (
                    SELECT p.*::payday_participants
                      FROM payday_participants p
                     WHERE id = NEW.tipper
                );
                IF (NEW.amount <= tipper.new_balance) THEN
                    EXECUTE transfer(NEW.tipper, NEW.tippee, NEW.amount, 'tip', NULL);
                    RETURN NEW;
                END IF;
                RETURN NULL;
            END;
        $$ LANGUAGE plpgsql;

        CREATE TRIGGER process_tip BEFORE UPDATE OF is_funded ON payday_tips
            FOR EACH ROW
            WHEN (NEW.is_funded IS true AND OLD.is_funded IS NOT true AND NEW.to_team IS NOT true)
            EXECUTE PROCEDURE process_tip();


        -- Create a function to settle one-to-one donations

        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 payday_tips
                            SET is_funded = true
                          WHERE is_funded IS NOT true
                            AND to_team 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;


        -- Create a function to resolve many-to-many donations (team takes)

        CREATE OR REPLACE FUNCTION resolve_takes(team_id bigint) RETURNS void AS $$
            DECLARE
                total_income numeric(35,2);
                total_takes numeric(35,2);
                takes_ratio numeric;
                tips_ratio numeric;
                tip record;
                take record;
                transfer_amount numeric(35,2);
                our_tips CURSOR FOR
                    SELECT t.id, t.tipper, (round_up(t.amount * tips_ratio, 2)) AS amount
                      FROM payday_tips t
                      JOIN payday_participants p ON p.id = t.tipper
                     WHERE t.tippee = team_id
                       AND p.new_balance >= t.amount;
            BEGIN
                WITH funded AS (
                     UPDATE payday_tips
                        SET is_funded = true
                       FROM payday_participants p
                      WHERE p.id = tipper
                        AND tippee = team_id
                        AND p.new_balance >= amount
                  RETURNING amount
                )
                SELECT COALESCE(sum(amount), 0) FROM funded INTO total_income;
                total_takes := (
                    SELECT COALESCE(sum(t.amount), 0)
                      FROM payday_takes t
                     WHERE t.team = team_id
                );
                IF (total_income = 0 OR total_takes = 0) THEN RETURN; END IF;
                takes_ratio := min(total_income / total_takes, 1::numeric);
                tips_ratio := min(total_takes / total_income, 1::numeric);

                DROP TABLE IF EXISTS our_takes;
                CREATE TEMPORARY TABLE our_takes ON COMMIT DROP AS
                    SELECT t.member, (round_up(t.amount * takes_ratio, 2)) AS amount
                      FROM payday_takes t
                     WHERE t.team = team_id;

                FOR tip IN our_tips LOOP
                    FOR take IN (SELECT * FROM our_takes ORDER BY member) LOOP
                        IF (take.amount = 0 OR tip.tipper = take.member) THEN
                            CONTINUE;
                        END IF;
                        transfer_amount := min(tip.amount, take.amount);
                        EXECUTE transfer(tip.tipper, take.member, transfer_amount, 'take', team_id);
                        tip.amount := tip.amount - transfer_amount;
                        UPDATE our_takes t
                           SET amount = take.amount - transfer_amount
                         WHERE t.member = take.member;
                        EXIT WHEN tip.amount = 0;
                    END LOOP;
                END LOOP;
                RETURN;
            END;
        $$ LANGUAGE plpgsql;

         N/A dict ts_start ts_start N/A N/A log Prepared the DB. N/A staticmethod transfer_virtually N/A N/A cursor N/A N/A N/A N/A N/A cursor run 
            SELECT settle_tip_graph();
            SELECT resolve_takes(id) FROM payday_participants WHERE kind = 'group';
            SELECT settle_tip_graph();
            UPDATE payday_tips SET is_funded = false WHERE is_funded IS NULL;
         N/A staticmethod check_balances N/A N/A cursor N/A N/A N/A Check that balances aren't becoming (more) negative
         N/A oops N/A N/A 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
         N/A oops N/A N/A N/A log oops N/A N/A NegativeBalance N/A N/A log Checked the balances. N/A staticmethod transfer_for_real N/A N/A self transfers N/A N/A N/A db N/A self db N/A t transfers N/A N/A N/A transfer db N/A t __dict__ N/A clean_up N/A N/A self N/A N/A N/A N/A N/A N/A self db run 
            DROP FUNCTION process_tip();
            DROP FUNCTION settle_tip_graph();
            DROP FUNCTION transfer(bigint, bigint, numeric, transfer_context, bigint);
            DROP FUNCTION resolve_takes(bigint);
         N/A update_stats N/A N/A self N/A N/A N/A N/A N/A N/A self db run 
            WITH our_transfers AS (
                     SELECT *
                       FROM transfers
                      WHERE "timestamp" >= %(ts_start)s
                        AND status = 'succeeded'
                 )
               , our_tips AS (
                     SELECT *
                       FROM our_transfers
                      WHERE context = 'tip'
                 )
               , our_takes AS (
                     SELECT *
                       FROM our_transfers
                      WHERE context = 'take'
                 )
            UPDATE paydays
               SET nactive = (
                       SELECT DISTINCT count(*) FROM (
                           SELECT tipper FROM our_transfers
                               UNION
                           SELECT tippee FROM our_transfers
                       ) AS foo
                   )
                 , ntippers = (SELECT count(DISTINCT tipper) FROM our_transfers)
                 , ntippees = (SELECT count(DISTINCT tippee) FROM our_transfers)
                 , ntips = (SELECT count(*) FROM our_tips)
                 , ntakes = (SELECT count(*) FROM our_takes)
                 , take_volume = (SELECT COALESCE(sum(amount), 0) FROM our_takes)
                 , ntransfers = (SELECT count(*) FROM our_transfers)
                 , transfer_volume = (SELECT COALESCE(sum(amount), 0) FROM our_transfers)
             WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz

         N/A ts_start N/A self ts_start N/A N/A log Updated payday stats. N/A update_cached_amounts N/A N/A self N/A N/A N/A now N/A N/A N/A aspen utils utcnow N/A N/A N/A N/A self db get_cursor cursor N/A N/A N/A N/A self prepare cursor now N/A N/A N/A self transfer_virtually cursor N/A N/A N/A cursor run 

            UPDATE tips t
               SET is_funded = t2.is_funded
              FROM payday_tips t2
             WHERE t.id = t2.id
               AND t.is_funded <> t2.is_funded;

            UPDATE participants p
               SET giving = p2.giving
              FROM ( SELECT p2.id
                          , COALESCE((
                                SELECT sum(amount)
                                  FROM payday_tips t
                                 WHERE t.tipper = p2.id
                                   AND t.is_funded
                            ), 0) AS giving
                       FROM participants p2
                   ) p2
             WHERE p.id = p2.id
               AND p.giving <> p2.giving;

            UPDATE participants p
               SET taking = p2.taking
              FROM ( SELECT p2.id
                          , COALESCE((
                                SELECT sum(amount)
                                  FROM payday_transfers t
                                 WHERE t.tippee = p2.id
                                   AND context = 'take'
                            ), 0) AS taking
                       FROM participants p2
                   ) p2
             WHERE p.id = p2.id
               AND p.taking <> p2.taking;

            UPDATE participants p
               SET receiving = p2.receiving
              FROM ( SELECT p2.id
                          , p2.taking + COALESCE((
                                SELECT sum(amount)
                                  FROM payday_tips t
                                 WHERE t.tippee = p2.id
                                   AND t.is_funded
                            ), 0) AS receiving
                       FROM participants p2
                   ) p2
             WHERE p.id = p2.id
               AND p.receiving <> p2.receiving
               AND p.status <> 'stub';

            UPDATE participants p
               SET npatrons = p2.npatrons
              FROM ( SELECT p2.id
                          , ( SELECT count(*)
                                FROM payday_transfers t
                               WHERE t.tippee = p2.id
                            ) AS npatrons
                       FROM participants p2
                   ) p2
             WHERE p.id = p2.id
               AND p.npatrons <> p2.npatrons
               AND p.status <> 'stub'
               AND p.kind IN ('individual', 'organization');

            UPDATE participants p
               SET npatrons = p2.npatrons
              FROM ( SELECT p2.id
                          , ( SELECT count(*)
                                FROM payday_tips t
                               WHERE t.tippee = p2.id
                                 AND t.is_funded
                            ) AS npatrons
                       FROM participants p2
                   ) p2
             WHERE p.id = p2.id
               AND p.npatrons <> p2.npatrons
               AND p.kind = 'group';

             N/A N/A N/A self clean_up N/A N/A log Updated receiving amounts. N/A end N/A N/A self N/A N/A N/A N/A self ts_end N/A N/A N/A N/A N/A self db one 
            UPDATE paydays
               SET ts_end=now()
             WHERE ts_end='1970-01-01T00:00:00+00'::timestamptz
         RETURNING ts_end AT TIME ZONE 'UTC'
         default NoPayday replace tzinfo N/A N/A aspen utils utc N/A notify_participants N/A N/A self N/A N/A N/A previous_ts_end N/A N/A N/A self db one 
            SELECT ts_end
              FROM paydays
             WHERE ts_start < %s
          ORDER BY ts_end DESC
             LIMIT 1
         N/A N/A self ts_start default N/A constants BIRTHDAY N/A r N/A N/A N/A self db all 
            SELECT tippee, json_agg(t) AS transfers
              FROM transfers t
             WHERE "timestamp" > %s
               AND "timestamp" <= %s
          GROUP BY tippee
         N/A previous_ts_end N/A self ts_end N/A N/A tippee_id transfers r N/A N/A successes N/A t N/A t transfers N/A N/A t N/A status succeeded N/A N/A successes N/A N/A N/A by_team N/A k N/A sum N/A N/A t N/A amount N/A t v N/A N/A k v N/A N/A N/A group_by successes team items N/A personal N/A N/A by_team pop None 0 N/A by_team N/A N/A N/A N/A Participant from_id k username v N/A N/A k v N/A N/A by_team items N/A N/A N/A N/A N/A Participant from_id tippee_id notify income total N/A sum N/A N/A t N/A amount N/A t successes personal personal by_team by_team N/A participants N/A N/A N/A self db all 
            SELECT p.*::participants
              FROM participants p
             WHERE mangopay_user_id IS NULL
               AND (p.goal IS NULL OR p.goal >= 0)
               AND EXISTS (
                     SELECT 1
                       FROM current_tips t
                       JOIN participants p2 ON p2.id = t.tipper
                      WHERE t.tippee = p.id
                        AND t.amount > 0
                        AND p2.balance > t.amount
                   )
         N/A p participants N/A N/A N/A N/A p notify identity_required force_email True N/A participants N/A N/A N/A self db all 
            SELECT p.*::participants
              FROM participants p
             WHERE balance < (
                     SELECT sum(amount)
                       FROM current_tips t
                       JOIN participants p2 ON p2.id = t.tippee
                      WHERE t.tipper = p.id
                        AND p2.mangopay_user_id IS NOT NULL
                        AND p2.status = 'active'
                   )
               AND EXISTS (
                     SELECT 1
                       FROM transfers t
                      WHERE t.tipper = p.id
                        AND t.timestamp > %s
                        AND t.timestamp <= %s
                        AND t.status = 'succeeded'
                   )
         N/A previous_ts_end N/A self ts_end N/A p participants N/A N/A N/A N/A p notify low_balance N/A N/A main N/A N/A N/A N/A os environ liberapay.billing.exchanges sync_with_mangopay liberapay.main website liberapay.billing.payday Payday N/A N/A N/A N/A website env canonical_host liberapay.com N/A N/A log_dir N/A environ N/A OPENSHIFT_DATA_DIR N/A keep_log True N/A N/A log_dir N/A keep_log False N/A N/A N/A N/A sync_with_mangopay N/A website db N/A N/A N/A N/A N/A Payday start run log_dir keep_log N/A N/A N/A KeyboardInterrupt N/A N/A N/A N/A N/A traceback N/A N/A N/A traceback print_exc N/A N/A N/A __name__ __main__ N/A N/A N/A main