Ejemplo n.º 1
0
def change_memo(request):
    split_guid = request.POST.get('split_guid', '')
    memo = request.POST.get('memo', '')
    split = Split.objects.get(guid=split_guid)
    Lock.obtain()
    try:
        split.memo = request.POST.get('memo', '')
        split.save()
    finally:
        Lock.release()
    return {
        'split_guid': split_guid,
        'memo': memo,
    }
Ejemplo n.º 2
0
def change_account(request):
    split_guid = request.POST.get('split_guid', '')
    account_guid = request.POST.get('account_guid', '')
    split = Split.objects.get(guid=split_guid)
    Lock.obtain()
    try:
        split.account = Account.objects.get(guid=account_guid)
        split.save()
    finally:
        Lock.release()
    return {
        'split_guid': split_guid,
        'account_guid': account_guid,
    }
Ejemplo n.º 3
0
def change_account(request):
  split_guid = request.POST.get('split_guid', '')
  account_guid = request.POST.get('account_guid', '')
  split = Split.objects.get(guid=split_guid)
  Lock.obtain()
  try:
    split.account = Account.objects.get(guid=account_guid)
    split.save()
  finally:
    Lock.release()
  return {
    'split_guid': split_guid,
    'account_guid': account_guid,
  }
Ejemplo n.º 4
0
def change_memo(request):
  split_guid = request.POST.get('split_guid', '')
  memo = request.POST.get('memo', '')
  split = Split.objects.get(guid=split_guid)
  Lock.obtain()
  try:
    split.memo = request.POST.get('memo', '')
    split.save()
  finally:
    Lock.release()
  return {
    'split_guid': split_guid,
    'memo': memo,
  }
Ejemplo n.º 5
0
def new_transaction(request, key):
  accounts = misc_functions.get_accounts_by_webapp_key(key)
  if len(accounts) != 1:
    raise ValueError('Can only create transactions for 1 account at a time.')
  src_account = accounts[0]

  choices = forms.AccountChoices(accounts)

  new_tx_form = forms.NewTransactionForm(choices, request.POST)

  if not new_tx_form.is_valid():
    raise ValueError(new_tx_form.errors)

  txinfo = new_tx_form.cleaned_data

  txinfo['amount'] = Decimal(txinfo['amount'])

  global set_home_for_gnucash_api
  if not set_home_for_gnucash_api:
    # Bad gnucash depends on $HOME (this dir needs to be writable by the webserver)
    os.environ['HOME'] = os.path.abspath(os.path.join(
      os.path.dirname(os.path.dirname(__file__)), 'gnucash_api_home'))
    set_home_for_gnucash_api = True

  import gnucash
  from gnucash_scripts import common

  # make sure we can begin a session
  Lock.check_can_obtain()

  # begin GnuCash API session
  session = gnucash.Session(settings.GNUCASH_CONN_STRING)

  try:
    book = session.book
    USD = book.get_table().lookup('ISO4217', 'USD')

    root = book.get_root_account()
    imbalance = common.get_account_by_path(root, 'Imbalance-USD')

    acct = common.get_account_by_guid(root, src_account.guid)
    opposing_acct = common.get_account_by_guid(root, txinfo['opposing_account'])
    gnc_amount = common.decimal_to_gnc_numeric(Decimal(txinfo['amount']))

    # From example script 'test_imbalance_transaction.py'
    trans = gnucash.Transaction(book)
    trans.BeginEdit()
    trans.SetCurrency(USD)
    trans.SetDescription(str(txinfo['tx_desc']))
    trans.SetDate(
      txinfo['post_date'].day,
      txinfo['post_date'].month,
      txinfo['post_date'].year)

    split1 = gnucash.Split(book)
    split1.SetParent(trans)
    split1.SetAccount(acct)
    if txinfo.has_key('memo'):
      split1.SetMemo(str(txinfo['memo']))
    # The docs say both of these are needed:
    # http://svn.gnucash.org/docs/HEAD/group__Transaction.html
    split1.SetValue(gnc_amount)
    split1.SetAmount(gnc_amount)
    split1.SetReconcile('c')

    if opposing_acct != None:
      split2 = gnucash.Split(book)
      split2.SetParent(trans)
      split2.SetAccount(opposing_acct)
      split2.SetValue(gnc_amount.neg())
      split2.SetAmount(gnc_amount.neg())
      split2.SetReconcile('c')

    trans.CommitEdit()

  finally:
    session.end()
    session.destroy()

  dest_url = request.META.get('HTTP_REFERER')
  if not dest_url:
    dest_url = reverse('money_views.views.account', kwargs={'key': key})

  return redirect(dest_url)
Ejemplo n.º 6
0
    def apply(**kwargs):
        splits = kwargs['splits']
        accounts = splits.accounts
        tx_desc = kwargs.get('tx_desc', None)
        is_regex = kwargs.get('is_regex', False)
        opposing_account = kwargs['opposing_account']
        min_amount = kwargs.get('min_amount', None)
        max_amount = kwargs.get('max_amount', None)
        save_rule = kwargs['save_rule']

        if min_amount is None:
            min_amount = 0
        elif min_amount < 0:
            raise ValueError('min_amount (%s) < 0' % min_amount)
        if max_amount is None:
            max_amount = 0
        elif max_amount < 0:
            raise ValueError('max_amount (%s) < 0' % max_amount)
        if min_amount and max_amount and min_amount > max_amount:
            raise ValueError('min_amount (%s) > max_amount (%s)' %
                             (min_amount, max_amount))

        filtered_splits = splits.filtered_splits

        if tx_desc:
            # Need to do tx_desc filter ourselves
            if is_regex:
                filtered_splits = \
                  filtered_splits.filter(transaction__description__iregex=tx_desc)
            else:
                filtered_splits = \
                  filtered_splits.filter(transaction__description__icontains=tx_desc)
        else:
            # Any tx_desc filtering has already been done for us
            tx_desc = splits.tx_desc
            is_regex = splits.tx_desc_is_regex

        tx_guids = filtered_splits.distinct().values('transaction__guid')
        splits_real = Split.objects \
            .filter(transaction__guid__in=tx_guids) \
            .exclude(account__guid__in=[a.guid for a in accounts])

        split_guids = list(splits_real.distinct().values_list('guid',
                                                              flat=True))
        tx_count = len(split_guids)
        modified_tx_count = 0

        if tx_count > 0:
            Lock.obtain()
            try:
                splits = Split.objects.filter(guid__in=split_guids)
                if opposing_account is None:
                    tx_guids = list(
                        splits.values_list('transaction__guid', flat=True))
                    Transaction.objects.filter(guid__in=tx_guids).delete()
                    Split.objects.filter(guid__in=split_guids).delete()
                else:
                    splits.update(account=opposing_account)
                modified_tx_count = tx_count
            finally:
                Lock.release()

        if save_rule and tx_desc:
            rule = Rule()
            if opposing_account:
                rule.opposing_account_guid = opposing_account.guid
            else:
                rule.opposing_account_guid = None
            rule.match_tx_desc = tx_desc
            rule.is_regex = is_regex
            if min_amount: rule.min_amount = min_amount
            if max_amount: rule.max_amount = max_amount
            rule.save()

            for a in accounts:
                rule_account = RuleAccount()
                rule_account.rule = rule
                rule_account.account_guid = a.guid
                rule_account.save()

        return modified_tx_count
Ejemplo n.º 7
0
  def apply(**kwargs):
    splits           = kwargs['splits']
    account          = splits.account
    tx_desc          = kwargs.get('tx_desc', None)
    is_regex         = kwargs.get('is_regex', False)
    opposing_account = kwargs['opposing_account']
    min_amount       = kwargs.get('min_amount', None)
    max_amount       = kwargs.get('max_amount', None)
    save_rule        = kwargs['save_rule']

    if min_amount is None:
      min_amount = 0
    elif min_amount < 0:
      raise ValueError('min_amount (%s) < 0' % min_amount)
    if max_amount is None:
      max_amount = 0
    elif max_amount < 0:
      raise ValueError('max_amount (%s) < 0' % max_amount)
    if min_amount and max_amount and min_amount > max_amount:
      raise ValueError('min_amount (%s) > max_amount (%s)' % (min_amount, max_amount))

    filtered_splits = splits.filtered_splits

    if tx_desc:
      # Need to do tx_desc filter ourselves
      if is_regex:
        filtered_splits = \
          filtered_splits.filter(transaction__description__iregex=tx_desc)
      else:
        filtered_splits = \
          filtered_splits.filter(transaction__description__icontains=tx_desc)
    else:
      # Any tx_desc filtering has already been done for us
      tx_desc = splits.tx_desc
      is_regex = splits.tx_desc_is_regex

    tx_guids = filtered_splits.distinct().values('transaction__guid')
    splits_real = Split.objects.filter(transaction__guid__in=tx_guids).exclude(account=account)

    # ugh
    if min_amount: min_amount -= Decimal('1e-8')
    if max_amount: max_amount += Decimal('1e-8')

    if min_amount and max_amount:
      splits_real = splits_real.filter(
        (Q(value_num__gte=F('value_denom') *  min_amount) & Q(value_num__lte=F('value_denom') *  max_amount)) |
        (Q(value_num__lte=F('value_denom') * -min_amount) & Q(value_num__gte=F('value_denom') * -max_amount)))
    elif min_amount:
      splits_real = splits_real.filter(
        (Q(value_num__gte=F('value_denom') *  min_amount)) |
        (Q(value_num__lte=F('value_denom') * -min_amount)))
    elif max_amount:
      splits_real = splits_real.filter(
        (Q(value_num__lte=F('value_denom') *  max_amount)) |
        (Q(value_num__gte=F('value_denom') * -max_amount)))

    split_guids = list(splits_real.distinct().values_list('guid', flat=True))
    tx_count = len(split_guids)
    modified_tx_count = 0

    if tx_count > 0:
      Lock.obtain()
      try:
        Split.objects.filter(guid__in=split_guids).update(account=opposing_account)
        modified_tx_count = tx_count
      finally:
        Lock.release()

    if save_rule and tx_desc:
      rule = Rule()
      rule.opposing_account_guid = opposing_account.guid
      rule.match_tx_desc = tx_desc
      rule.is_regex = is_regex
      if min_amount: rule.min_amount = min_amount
      if max_amount: rule.max_amount = max_amount
      rule.save()

      rule_account = RuleAccount()
      rule_account.rule = rule
      rule_account.account_guid = account.guid
      rule_account.save()

    return modified_tx_count