def index(request): template = loader.get_template('page_index.html') accounts = [Account.from_path(path) for path in settings.ACCOUNTS_LIST] all_accounts = Account.get_all() all_accounts.sort(key=lambda a: a.path) c = RequestContext(request, { 'accounts': accounts, 'all_accounts': all_accounts, 'showing_index': True, }) return HttpResponse(template.render(c))
def account(request, key): template = loader.get_template('page_account_details.html') account = get_account(key) splits = filters.TransactionSplitFilter(account) all_accounts = Account.get_all() all_accounts.sort(key=lambda a: a.path) all_accounts_dict = {} for a in all_accounts: all_accounts_dict[a.guid] = { 'path': a.path, 'name': a.name } choices = forms.AccountChoices(account) filter_form = forms.FilterForm(choices, request.GET) if filter_form.is_valid(): splits.filter_splits(filter_form.cleaned_data) splits.order_filtered_splits() modify_form_data = request.GET.copy() modify_form_data['save_rule'] = True modify_form = forms.ModifyForm(choices, modify_form_data, auto_id="modify_id_%s") try: page_num = int(request.GET.get('page')) except: page_num = 1 pages = Paginator(splits.filtered_splits, settings.NUM_TRANSACTIONS_PER_PAGE) try: page = pages.page(page_num) except PageNotAnInteger: page = pages.page(1) except EmptyPage: page = pages.page(pages.num_pages) Transaction.cache_from_splits(page.object_list) c = RequestContext(request, { 'any_filters_applied': splits.any_filters_applied, 'one_opposing_account_filter_applied': splits.one_opposing_account_filter_applied, 'regex_chars_js': json.dumps(filters.TransactionSplitFilter.REGEX_CHARS), 'all_accounts': all_accounts, 'accounts_js': json.dumps(all_accounts_dict), 'current_account_js': json.dumps(account.guid), 'num_transactions_js': json.dumps(page.paginator.count), 'api_functions_js': json.dumps(api.function_urls.urls_dict), 'account': account, 'page': page, 'filter_form': filter_form, 'modify_form': modify_form, }) return HttpResponse(template.render(c))
def modify(request, key): template = loader.get_template('page_modify.html') accounts = misc_functions.get_accounts_by_webapp_key(key) splits = filters.TransactionSplitFilter(accounts) errors = False choices = forms.AccountChoices(accounts) opposing_account_guid = request.POST['change_opposing_account'] opposing_account = None try: if opposing_account_guid != 'DELETE': opposing_account = Account.get(opposing_account_guid) except Account.DoesNotExist: errors = "Account '%s' not found." % opposing_account_guid form_data = request.POST.copy() modified_tx_count = 0 if not errors: modify_form = forms.ModifyForm(choices, request.POST) if modify_form.is_valid(): splits.filter_splits(modify_form.cleaned_data) save_rule = modify_form.cleaned_data['save_rule'] if save_rule and not splits.tx_desc: errors = 'Cannot save rule with no description filter.' save_rule = False modified_tx_count = filters.RuleHelper.apply( splits=splits, opposing_account=opposing_account, min_amount=modify_form.cleaned_data['min_amount'], max_amount=modify_form.cleaned_data['max_amount'], save_rule=save_rule) if modified_tx_count: form_data['opposing_accounts'] = opposing_account_guid else: # modify_form is not valid errors = str(modify_form.errors) hidden_filter_form = forms.HiddenFilterForm(choices, form_data) c = RequestContext(request, { 'accounts': accounts, 'current_accounts_key': misc_functions.accounts_webapp_key(accounts), 'opposing_account': opposing_account, 'hidden_filter_form': hidden_filter_form, 'errors': errors, 'modified_tx_count': modified_tx_count, }) return HttpResponse(template.render(c))
def index(request): template = loader.get_template('index.html') accounts = [Account.from_path(path) for path in settings.ACCOUNTS_LIST] c = RequestContext(request, { 'accounts': accounts, 'show_account_links': True, }) return HttpResponse(template.render(c))
def modify(request, index): template = loader.get_template('modify.html') path = settings.ACCOUNTS_LIST[int(index)] account = Account.from_path(path) splits = filters.TransactionSplitFilter(account) errors = False choices = forms.AccountChoices(account) opposing_account_guid = request.POST['change_opposing_account'] opposing_account = None try: opposing_account = Account.objects.get(guid=opposing_account_guid) except Account.DoesNotExist: errors = "Account '%s' not found." % opposing_account_guid form_data = request.POST.copy() modified_tx_count = 0 if not errors: modify_form = forms.ModifyForm(choices, request.POST) if modify_form.is_valid(): splits.filter_splits(modify_form.cleaned_data) save_rule = modify_form.cleaned_data['save_rule'] if save_rule and not splits.tx_desc: errors = 'Cannot save rule with no description filter.' save_rule = False modified_tx_count = filters.RuleHelper.apply( splits=splits, opposing_account=opposing_account, min_amount=modify_form.cleaned_data['min_amount'], max_amount=modify_form.cleaned_data['max_amount'], save_rule=save_rule) if modified_tx_count: form_data['opposing_accounts'] = opposing_account_guid else: # modify_form is not valid errors = str(modify_form.errors) hidden_filter_form = forms.HiddenFilterForm(choices, form_data) c = RequestContext(request, { 'account': account, 'opposing_account': opposing_account, 'hidden_filter_form': hidden_filter_form, 'errors': errors, 'modified_tx_count': modified_tx_count, }) return HttpResponse(template.render(c))
def batch_categorize(request, index): template = loader.get_template('batch_categorize.html') path = settings.ACCOUNTS_LIST[int(index)] account = Account.from_path(path) splits = filters.TransactionSplitFilter(account) imbalance = Account.from_path('Imbalance-USD') choices = forms.AccountChoices(account, exclude=imbalance) merchants = splits.get_merchants_info(imbalance) no_merchants = (len(merchants) == 0) batch_modify_form = forms.BatchModifyForm(choices, merchants) c = RequestContext(request, { 'account': account, 'batch_modify_form': batch_modify_form, 'no_merchants': no_merchants, 'imbalance': imbalance, }) return HttpResponse(template.render(c))
def apply_categorize(request, key): template = loader.get_template('page_apply_categorize.html') accounts = misc_functions.get_accounts_by_webapp_key(key) splits = filters.TransactionSplitFilter(accounts) imbalance = Account.from_path('Imbalance-USD') choices = forms.AccountChoices(accounts, exclude=imbalance) merchants = splits.get_merchants_info(imbalance) batch_modify_form = forms.BatchModifyForm(choices, merchants, request.POST) if not batch_modify_form.is_valid(): raise ValueError(batch_modify_form.errors) modified_tx_count = 0 rule_count = 0 for i in range(settings.NUM_MERCHANTS_BATCH_CATEGORIZE): if 'merchant_' + str(i) in batch_modify_form.cleaned_data: tx_desc = batch_modify_form.cleaned_data['merchant_name_' + str(i)] opposing_account_guid = batch_modify_form.cleaned_data['merchant_' + str(i)] if opposing_account_guid: rule_count += 1 opposing_account = None if opposing_account_guid != 'DELETE': opposing_account = Account.get(opposing_account_guid) modified_tx_count += filters.RuleHelper.apply( splits=splits, tx_desc=tx_desc, opposing_account=opposing_account, save_rule=True) c = RequestContext(request, { 'accounts': accounts, 'current_accounts_key': misc_functions.accounts_webapp_key(accounts), 'modified_tx_count': modified_tx_count, 'rule_count': rule_count, }) return HttpResponse(template.render(c))
def apply_categorize(request, index): template = loader.get_template('apply_categorize.html') path = settings.ACCOUNTS_LIST[int(index)] account = Account.from_path(path) imbalance = Account.from_path('Imbalance-USD') choices = forms.AccountChoices(account, exclude=imbalance) splits = filters.TransactionSplitFilter(account) merchants = splits.get_merchants_info(imbalance) batch_modify_form = forms.BatchModifyForm(choices, merchants, request.POST) if not batch_modify_form.is_valid(): raise ValueError(batch_modify_form.errors) modified_tx_count = 0 rule_count = 0 for i in range(settings.NUM_MERCHANTS_BATCH_CATEGORIZE): if 'merchant_' + str(i) in batch_modify_form.cleaned_data: tx_desc = batch_modify_form.cleaned_data['merchant_name_' + str(i)] opposing_account_guid = batch_modify_form.cleaned_data['merchant_' + str(i)] if opposing_account_guid: rule_count += 1 modified_tx_count += filters.RuleHelper.apply( splits=splits, tx_desc=tx_desc, opposing_account=Account.objects.get(guid=opposing_account_guid), save_rule=True) c = RequestContext(request, { 'account': account, 'modified_tx_count': modified_tx_count, 'rule_count': rule_count, }) return HttpResponse(template.render(c))
def account(request, index): template = loader.get_template('account_details.html') path = settings.ACCOUNTS_LIST[int(index)] account = Account.from_path(path) splits = filters.TransactionSplitFilter(account) choices = forms.AccountChoices(account) filter_form = forms.FilterForm(choices, request.GET) if filter_form.is_valid(): splits.filter_splits(filter_form.cleaned_data) splits.order_filtered_splits() modify_form_data = request.GET.copy() modify_form_data['save_rule'] = True modify_form = forms.ModifyForm(choices, modify_form_data, auto_id="modify_id_%s") try: page_num = int(request.GET.get('page')) except: page_num = 1 pages = Paginator(splits.filtered_splits, settings.NUM_TRANSACTIONS_PER_PAGE) try: page = pages.page(page_num) except PageNotAnInteger: page = pages.page(1) except EmptyPage: page = pages.page(pages.num_pages) c = RequestContext(request, { 'any_filters_applied': splits.any_filters_applied, 'one_opposing_account_filter_applied': splits.one_opposing_account_filter_applied, 'regex_chars_js': json.dumps(filters.TransactionSplitFilter.REGEX_CHARS), 'accounts_js': json.dumps(choices.accounts_dict), 'num_transactions_js': json.dumps(page.paginator.count), 'account': account, 'page': page, 'filter_form': filter_form, 'modify_form': modify_form, }) return HttpResponse(template.render(c))
def batch_categorize(request, key): template = loader.get_template('page_batch_categorize.html') accounts = misc_functions.get_accounts_by_webapp_key(key) splits = filters.TransactionSplitFilter(accounts) imbalance = Account.from_path('Imbalance-USD') choices = forms.AccountChoices(accounts, exclude=imbalance) merchants = splits.get_merchants_info(imbalance) no_merchants = (len(merchants) == 0) batch_modify_form = forms.BatchModifyForm(choices, merchants) c = RequestContext(request, { 'accounts': accounts, 'current_accounts_key': misc_functions.accounts_webapp_key(accounts), 'batch_modify_form': batch_modify_form, 'no_merchants': no_merchants, 'imbalance': imbalance, }) return HttpResponse(template.render(c))
def account(request, key): template = loader.get_template('page_account_details.html') accounts = misc_functions.get_accounts_by_webapp_key(key) splits = filters.TransactionSplitFilter(accounts) all_accounts = Account.get_all() all_accounts.sort(key=lambda a: a.path) all_accounts_dict = {} for a in all_accounts: all_accounts_dict[a.guid] = { 'path': a.path, 'name': a.name } choices = forms.AccountChoices(accounts) filter_form = forms.FilterForm(choices, request.GET) if filter_form.is_valid(): splits.filter_splits(filter_form.cleaned_data) splits.order_filtered_splits() modify_form_data = request.GET.copy() modify_form_data['save_rule'] = True modify_form = forms.ModifyForm(choices, modify_form_data, auto_id="modify_id_%s") try: can_add_transactions = settings.ENABLE_ADD_TRANSACTIONS except AttributeError: can_add_transactions = False can_add_transactions = (can_add_transactions and len(accounts) == 1) if can_add_transactions: new_transaction_form = forms.NewTransactionForm(choices, auto_id='id_new_trans_%s') else: new_transaction_form = None try: page_num = int(request.GET.get('page')) except: page_num = 1 pages = Paginator(splits.filtered_splits, settings.NUM_TRANSACTIONS_PER_PAGE) try: page = pages.page(page_num) except PageNotAnInteger: page = pages.page(1) except EmptyPage: page = pages.page(pages.num_pages) Transaction.cache_from_splits(page.object_list) current_accounts_key = misc_functions.accounts_webapp_key(accounts) c = RequestContext(request, { 'any_filters_applied': splits.any_filters_applied, 'one_opposing_account_filter_applied': splits.one_opposing_account_filter_applied, 'query_params_js': json.dumps(request.GET), 'regex_chars_js': json.dumps(filters.TransactionSplitFilter.REGEX_CHARS), 'all_accounts': all_accounts, 'accounts_js': json.dumps(all_accounts_dict), 'current_accounts_js': json.dumps([a.guid for a in accounts]), 'num_transactions_js': json.dumps(page.paginator.count), 'api_functions_js': json.dumps(api.function_urls.urls_dict), 'accounts': accounts, 'current_accounts_key': current_accounts_key, 'current_accounts_key_js': json.dumps(current_accounts_key), 'can_add_transactions': can_add_transactions, 'account': accounts[0], 'page': page, 'filter_form': filter_form, 'modify_form': modify_form, 'new_transaction_form': new_transaction_form, 'total_balance': sum(a.balance for a in accounts), }) return HttpResponse(template.render(c))
def get_account_by_webapp_key(key): try: path = settings.ACCOUNTS_LIST[int(key)] return Account.from_path(path) except ValueError: return Account.get(key)
def __init__(self, accounts, **kwargs): cursor = connections['gnucash'].cursor() sql = ''' SELECT a.guid, CASE WHEN s.account_guid IS NULL THEN 0 ELSE 1 END AS is_present, a.placeholder FROM accounts a LEFT JOIN ( SELECT s2.account_guid, MAX(t.post_date) post_date FROM splits s INNER JOIN transactions t ON s.tx_guid = t.guid INNER JOIN splits s2 ON s2.tx_guid = t.guid WHERE s.account_guid IN (%s) AND s2.account_guid NOT IN (%s) GROUP BY 1 ) s ON s.account_guid = a.guid WHERE a.account_type <> 'ROOT' ''' params = ', '.join('%s' for a in accounts) sql = sql % (params, params) account_guids = [a.guid for a in accounts] cursor.execute(sql, account_guids + account_guids) filter_all_account_choices = [] filter_account_choices = [] modify_account_choices = [] exclude_guids = account_guids if 'exclude' in kwargs: exclude_guids.append(kwargs['exclude'].guid) for row in cursor.fetchall(): guid = row[0] path = Account.get(guid).path is_present = row[1] placeholder = row[2] filter_all_account_choices.append((guid, path)) if is_present: filter_account_choices.append((guid, path)) if not placeholder and guid not in exclude_guids: modify_account_choices.append((guid, path)) get_account_path = lambda a: a[1] filter_account_choices.sort(key=get_account_path) modify_account_choices.sort(key=get_account_path) self.filter_all_account_choices = \ DEFAULT_FILTER_ACCOUNT_CHOICES + filter_all_account_choices self.filter_account_choices = \ DEFAULT_FILTER_ACCOUNT_CHOICES + filter_account_choices self.modify_account_choices = \ DEFAULT_MODIFY_ACCOUNT_CHOICES + modify_account_choices
def process_request(self, request): Account.clear_caches() Transaction.clear_caches() return None
def get_account(key): try: path = settings.ACCOUNTS_LIST[int(key)] return Account.from_path(path) except ValueError: return Account.get(key)