Exemplo n.º 1
0
    def start(cls):
        """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.

        """
        try:
            d = 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)
            log("Starting payday #%s." % d['id'])
        except IntegrityError:  # Collision, we have a Payday already.
            d = 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)
            log("Picking up payday #%s." % d['id'])

        d['ts_start'] = d['ts_start'].replace(tzinfo=pando.utils.utc)

        log("Payday started at %s." % d['ts_start'])

        payday = Payday()
        payday.__dict__.update(d)
        return payday
Exemplo n.º 2
0
    def start(cls, public_log=''):
        """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.

        """
        d = cls.db.one("""
            INSERT INTO paydays
                        (id, public_log, ts_start)
                 VALUES ( COALESCE((SELECT id FROM paydays ORDER BY id DESC LIMIT 1), 0) + 1
                        , %s
                        , now()
                        )
            ON CONFLICT (ts_end) DO UPDATE
                    SET ts_start = COALESCE(paydays.ts_start, excluded.ts_start)
              RETURNING id, (ts_start AT TIME ZONE 'UTC') AS ts_start, stage
        """, (public_log, ),
                       back_as=dict)
        log("Running payday #%s." % d['id'])

        d['ts_start'] = d['ts_start'].replace(tzinfo=pando.utils.utc)

        log("Payday started at %s." % d['ts_start'])

        payday = Payday()
        payday.__dict__.update(d)
        return payday
Exemplo n.º 3
0
    def test_iter_payday_events(self):
        Payday.start().run()
        team = self.make_participant('team', kind='group')
        alice = self.make_participant('alice')
        self.make_exchange('mango-cc', 10000, 0, alice)
        self.make_exchange('mango-cc', -5000, 0, alice)
        self.db.run("""
            UPDATE transfers
               SET timestamp = "timestamp" - interval '1 month'
        """)
        bob = self.make_participant('bob')
        carl = self.make_participant('carl')
        david = self.make_participant('david')
        self.make_exchange('mango-cc', 10000, 0, david)
        david.set_tip_to(team, Decimal('1.00'))
        team.set_take_for(bob, Decimal('1.00'), bob)
        alice.set_tip_to(bob, Decimal('5.00'))

        assert bob.balance == 0
        for i in range(2):
            Payday.start().run()
            self.db.run("""
                UPDATE paydays
                   SET ts_start = ts_start - interval '1 week'
                     , ts_end = ts_end - interval '1 week';
                UPDATE transfers
                   SET timestamp = "timestamp" - interval '1 week';
            """)
        bob = Participant.from_id(bob.id)
        assert bob.balance == 12

        Payday().start()
        events = list(iter_payday_events(self.db, bob))
        assert len(events) == 9
        assert events[0]['kind'] == 'totals'
        assert events[0]['given'] == 0
        assert events[0]['received'] == 12
        assert events[1]['kind'] == 'day-open'
        assert events[1]['payday_number'] == 2
        assert events[2]['balance'] == 12
        assert events[-1]['kind'] == 'day-close'
        assert events[-1]['balance'] == 0

        alice = Participant.from_id(alice.id)
        assert alice.balance == 4990
        events = list(iter_payday_events(self.db, alice))
        assert events[0]['given'] == 10
        assert len(events) == 11

        carl = Participant.from_id(carl.id)
        assert carl.balance == 0
        events = list(iter_payday_events(self.db, carl))
        assert len(events) == 0
Exemplo n.º 4
0
 def test_end_raises_NoPayday(self):
     with self.assertRaises(NoPayday):
         Payday().end()
Exemplo n.º 5
0
    def test_iter_payday_events(self):
        now = datetime.now()
        Payday.start().run()
        team = self.make_participant('team', kind='group')
        alice = self.make_participant('alice')
        self.make_exchange('mango-cc', 10000, 0, alice)
        self.make_exchange('mango-cc', -5000, 0, alice)
        self.db.run("""
            UPDATE exchanges
               SET timestamp = "timestamp" - interval '1 week'
        """)
        bob = self.make_participant('bob')
        carl = self.make_participant('carl')
        david = self.make_participant('david')
        self.make_exchange('mango-cc', 10000, 0, david)
        david.set_tip_to(team, EUR('1.00'))
        team.set_take_for(bob, EUR('1.00'), team)
        alice.set_tip_to(bob, EUR('5.00'))

        assert bob.balance == 0
        for i in range(2):
            Payday.start().run()
            self.db.run("""
                UPDATE exchanges
                   SET timestamp = "timestamp" - interval '1 week';
                UPDATE paydays
                   SET ts_start = ts_start - interval '1 week'
                     , ts_end = ts_end - interval '1 week';
                UPDATE transfers
                   SET timestamp = "timestamp" - interval '1 week';
            """)
        bob = Participant.from_id(bob.id)
        assert bob.balance == 12

        Payday().start()

        # Make sure events are all in the same year
        delta = '%s days' % (364 - (now - datetime(now.year, 1, 1)).days)
        self.db.run(
            """
            UPDATE exchanges
               SET timestamp = "timestamp" + interval %(delta)s;
            UPDATE paydays
               SET ts_start = ts_start + interval %(delta)s;
            UPDATE paydays
               SET ts_end = ts_end + interval %(delta)s
             WHERE ts_end >= ts_start;
            UPDATE transfers
               SET timestamp = "timestamp" + interval %(delta)s;
        """, dict(delta=delta))

        events = list(iter_payday_events(self.db, bob, now.year))
        assert len(events) == 9
        assert events[0]['kind'] == 'totals'
        assert not events[0]['regular_donations']['sent']
        assert events[0]['regular_donations']['received'] == EUR(12)
        assert events[1]['kind'] == 'day-open'
        assert events[1]['payday_number'] == 3
        assert events[2]['balances'] == EUR(12)
        assert events[-1]['kind'] == 'day-close'
        assert events[-1]['balances'] == 0

        alice = Participant.from_id(alice.id)
        assert alice.balance == 4990
        events = list(iter_payday_events(self.db, alice, now.year))
        assert events[0]['regular_donations']['sent'] == EUR(10)
        assert len(events) == 11

        carl = Participant.from_id(carl.id)
        assert carl.balance == 0
        events = list(iter_payday_events(self.db, carl, now.year))
        assert len(events) == 0