Exemplo n.º 1
0
 def budget(self):
     ''' Fund high priority categories by withdrawing from low priority categories '''
     important = iter(self.priorities)
     unimportant = reversed(self.priorities)
     sink = next(important)
     source = next(unimportant)
     # utils.debug()
     while source is not sink:
         utils.log_info(source, sink)
         need = sink.total_need()
         utils.log_info('need', need)
         if utils.equalish(need, 0):
             sink = next(important)
             utils.log_info('new sink', sink)
         available = source.total_available()
         utils.log_info('available', available)
         if available <= 0:
             source = next(unimportant)
             utils.log_info('new source', source)
         use = min(available, need)
         utils.log_info('use', use)
         before = source.total_available() + sink.total_available()
         utils.log_info('before', before)
         utils.log_info('source before distribute', source)
         source.distribute(-use)
         utils.log_info('source after distribute', source)
         utils.log_info('sink before distribute', sink)
         sink.distribute(use)
         utils.log_info('sink after distribute', sink)
         after = source.total_available() + sink.total_available()
         utils.log_info('after', after)
         assert utils.equalish(after, before, -1)
Exemplo n.º 2
0
def get_order(t, orders):
    ''' Gets an order corresponding to the ynab transaction '''
    utils.log_debug('get_order', t, orders)
    possible_orders = []
    for order in orders.values():
        # need negative because YNAB outflows have negative amount
        if utils.equalish(order.total_charged, -afy.ynab.get_amount(t)):
            possible_orders.append(order)
    utils.log_debug('possible_orders', possible_orders)
    if len(possible_orders) == 0:
        utils.log_debug('No matching order for transaction')
        return None
    if len(possible_orders) == 1:
        order = possible_orders[0]
    else:
        if afy.settings.fail_on_ambiguous_transaction:
            utils.log_error('Skipping ambiguous transaction', t,
                            possible_orders)
            return None
        else:
            utils.log_debug('Skipping ambiguous transaction', t,
                            possible_orders)
        unused_orders = [
            o for o in possible_orders if o.id not in assigned_ids
        ]
        if not unused_orders:
            return None
        unused_orders.sort(
            key=lambda o: utils.day_delta(t.date, o.shipment_date))
        order = unused_orders[0]
    assigned_ids.add(order.id)
    utils.log_info('Matched transaction with order', t, order)
    return order
Exemplo n.º 3
0
 def budget2(self):
     unimportant = list(reversed(self.priorities))
     for p1, p2 in zip(unimportant, unimportant[1:]):
         before = p1.total_available() + p2.total_available()
         amount = p1.total_available()
         utils.log_info('moving', amount)
         utils.log_info(p1, p2)
         p1.distribute(-amount)
         p2.distribute(amount)
         utils.log_info('moved')
         utils.log_info(p1, p2)
         after = p1.total_available() + p2.total_available()
         assert utils.equalish(after, before, -1)
Exemplo n.º 4
0
def add_adjustment_subtransaction(t):
    ''' Ensures that the sum of subtransaction prices equals the transaction amount '''
    utils.log_debug('add_adjustment_subtransaction', t)
    if not t.subtransactions:
        return
    amount = calculate_adjustment(t)
    if not amount:
        return
    adjustment = utils.copy(t.subtransactions[0])
    adjustment.memo = 'Split transaction adjustment'
    adjustment.amount = amount
    adjustment.category_name = afy.settings.default_category  # TODO
    utils.log_info('Warning, adjusting: subtransactions do not add up, by $%s' % -get_amount(adjustment))
    t.subtransactions.append(adjustment)
    assert utils.equalish(t.amount, sum(s.amount for s in t.subtransactions))
Exemplo n.º 5
0
def calculate_adjustment(t):
    subtransaction_total = sum(s.amount for s in t.subtransactions)
    if utils.equalish(subtransaction_total, t.amount, precision=-1):
        return
    return t.amount - subtransaction_total