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, }
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, }
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)
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
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