Ejemplo n.º 1
0
def determine_debts(session):
    #TODO(rpearl) ...actual arg parsing
    dry_run = len(sys.argv) == 2 and sys.argv[1] == '--dry-run'

    if dry_run:
        print "This is a dry run. Not sending messages."

    # Compute aggregate debt
    debts = model.get_unresolved_transactions(session)
    users = [u.username for u in model.get_users(session)]
    rent = {user: 0 for user in users}
    for debt in debts:
        rent[debt.to_user]   -= debt.amount
        rent[debt.from_user] += debt.amount
    assert sum(rent.values()) == 0

    # Find users who have properties of Shakespeare
    need_paid = []
    can_pay = []
    for u, r in rent.iteritems():
        if r <= -THRESHOLD:
            need_paid.append((r, u))
        elif r > 0:
            can_pay.append((-r, u))

    # Begin paying users to zero
    can_pay = [u for _, u in sorted(can_pay)]
    payments = defaultdict(list)
    for _, u in sorted(need_paid):
        print "Finding money for %s (need %s)" % (u, format_cents(None, rent[u]))
        for u2 in can_pay:
            if rent[u2] > 0:
                to_pay = min(rent[u2], -rent[u])
                rent[u2] -= to_pay
                rent[u] += to_pay
                payments[u2].append((u, to_pay))
            if rent[u] >= 0:
                break
        assert rent[u] == 0

    # Inform users of their debts and reconcile ledger
    for f, txns in payments.iteritems():
        fu = session.query(User).get(f)
        for t, amount in txns:
            tu = session.query(User).get(t)
            print "%s pays %s %s" % (f, t, format_cents(None, amount))
            if not dry_run:
                model.create_transaction(session, t, f, amount, '[automatic] resolving debt')

        msg = debt_message(f, txns)
        if not dry_run:
            model.send_mail(from_user='******', to_user=f, message=msg)
        else:
            print msg
Ejemplo n.º 2
0
def debt_message(person, amount):
    if amount > 0:
        say = "%s more than" % (format_cents(None, amount))
    elif amount == 0:
        say = 'just'
    else:
        say = "%s less than" % (format_cents(None, -amount))
    msg = '''\
To: %s
Subject: End-of-month rent is due

You should pay %s your regular rent.
''' % (person, say)
    return msg
Ejemplo n.º 3
0
def debt_message(person, amount):
    if amount > 0:
        say = "%s more than" % (format_cents(None, amount))
    elif amount == 0:
        say = 'just'
    else:
        say = "%s less than" % (format_cents(None, -amount))
    msg = '''\
To: %s
Subject: End-of-month rent is due

You should pay %s your regular rent.
''' % (person, say)
    return msg
Ejemplo n.º 4
0
def debt_message(person, txns):
    bullets = '\n'.join('    - %s to %s' % (format_cents(None, a), d) for d, a in txns)
    msg = '''\
To: %s
Subject: Rent rebalance required

You should pay the following:
%s
''' % (person, bullets)
    return msg
Ejemplo n.º 5
0
    def create_transaction(self, session, from_user, to_user, amount, comment):
        date = datetime.now()
        txn = Transaction(date=date,
                          from_user=from_user,
                          to_user=to_user,
                          amount=amount,
                          comment=comment,
                          settled=False)
        session.add(txn)
        self.send_mail(from_user, [to_user], '''\
To: %s
Subject: %s sent you %s

for %s
''' % (to_user, from_user, format_cents(None, amount), comment))