from django.shortcuts import render, redirect, HttpResponseRedirect, get_object_or_404, render_to_response from django.http import HttpResponse, JsonResponse from .models import Account, Category, Transaction, Transfer from .forms import NewTransactionExp, NewTransactionInc, NewTransaction, NewTransaction1, NewAccount, NewCategory, NewTransfer, Upload, BaseTransactionFormSet from django.forms import ModelChoiceField from django.forms.models import modelformset_factory, formset_factory from django.template.context_processors import csrf from django.utils import timezone from datetime import datetime, date from django.db.models import Sum, Avg from django.db import connection from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required from django.core import serializers import calendar import requests from json import loads def test(request): url = 'https://www.cbr-xml-daily.ru/daily_utf8.xml' response = requests.get(url) return render(request, 'pfm/test.html', {'status': response.content}) def json(request): transactions = Transaction.objects.all() data = serializers.serialize("json", transactions, use_natural_foreign_keys=True) data_dict = loads(data) return JsonResponse(data_dict, safe=False) def tr_list(request): # TODO: at first load all categories are available - bug! tr_redir_url = '/transactions/#!' tr_list = Transaction.objects.filter(user=request.user).order_by('-tr_date') paginator = Paginator(tr_list, 10) page = request.GET.get('page') try: trs = paginator.page(page) except PageNotAnInteger: trs = paginator.page(1) except EmptyPage: trs = paginator.page(paginator.num_pages) if request.method == 'GET' and 'type' in request.GET: if request.GET['type'] == 'E': form = NewTransactionExp(request.POST, user=request.user) return HttpResponse(form['tr_cat']) elif request.GET['type'] == 'I': form = NewTransactionInc(request.POST, user=request.user) return HttpResponse(form['tr_cat']) if request.method == 'GET' and 'id' in request.GET: if request.GET['id'] == '0': form = NewTransaction(user=request.user) return render(request, 'pfm/tr_edit_form.html', {'form': form, }) tr = Transaction.objects.get(id=request.GET['id']) mapping = {'E': NewTransactionExp, 'I': NewTransactionInc} form = mapping[tr.tr_type](instance=Transaction.objects.get(id=request.GET['id']), user=request.user) return render(request, 'pfm/tr_edit_form.html', {'form': form, }) else: if request.method == "POST" and request.POST.get('action') == 'create': form = NewTransaction(request.POST, user=request.user) if form.is_valid(): tr = form.save(commit=False) tr.published_date = timezone.now() tr.user = request.user tr.save() return redirect(tr_redir_url) else: print('Not valid!', form.errors) elif request.POST.get('action') == 'edit': transaction = Transaction.objects.get(id=request.POST['id']) form = NewTransaction(request.POST, instance=transaction, user=request.user) if form.is_valid(): transaction = form.save(commit=False) transaction.user = request.user transaction.save() return redirect(tr_redir_url) elif request.method == 'POST' and request.POST.get('action') == 'delete': transaction = Transaction.objects.get(id=request.POST.get('id')) transaction.delete() return redirect(tr_redir_url) else: form = NewTransaction(user=request.user) return render(request, 'pfm/transactions.html', {'form': form, 'trs': trs}) def acc_list(request): acc_redir_url = '/account/#!' list = Account.objects.filter(user=request.user) tr_form = NewTransfer(request.POST, user=request.user) trs = Transfer.objects.filter(user=request.user) if request.POST.get('action') == 'delete': account = Account.objects.get(id=request.POST.get('id')) account.delete() return redirect(acc_redir_url) #return redirect('pfm.views.acc_list') elif request.POST.get('action') == 'create': form = NewAccount(request.POST) if form.is_valid(): account = form.save(commit=False) account.user = request.user account.save() return redirect(acc_redir_url) elif request.POST.get('action') == 'edit': acc = Account.objects.get(id=request.POST['id']) form = NewAccount(request.POST, instance = acc ) if form.is_valid(): account = form.save(commit=False) account.user = request.user account.save() return redirect(acc_redir_url) elif request.POST.get('action') == 'transfer': if tr_form.is_valid(): transfer = tr_form.save(commit=False) transfer.user = request.user transfer.save() return redirect(acc_redir_url) else: try: form = NewAccount(instance=Account.objects.get(id=request.GET['id'])) return HttpResponse(form) except: form = NewAccount() tr_form = NewTransfer(user=request.user) #connection. queries return render(request, 'pfm/accounts.html', {'list': list, 'form': form, 'tr_form': tr_form, 'trs': trs}) def massive_cat_edit(request): Cat_formset = modelformset_factory(Category, form=NewCategory, can_delete=True, extra=0) if request.method == "POST": form = Cat_formset(request.POST) if form.is_valid(): categories = form.save(commit=False) for category in categories: category.user = request.user category.save() form.save() return redirect('pfm.views.cat_list') else: form = Cat_formset(queryset=Category.objects.filter(user=request.user).order_by('id')) context = {'form': form, } return render(request, 'pfm/cat_edit.html', context) def massive_tr_edit(request): TestTrModel1 = modelformset_factory(Transaction, form=NewTransaction, can_delete=True, extra=0) if request.method == "POST": form = TestTrModel1(request.POST, form_kwargs={'user': request.user}) # paginator = Paginator(form, 2) # page = request.GET.get('page') # try: # trs = paginator.page(page) # except PageNotAnInteger: # trs = paginator.page(1) # except EmptyPage: # trs = paginator.page(paginator.num_pages) if form.is_valid(): transactions = form.save(commit=False) for transaction in transactions: transaction.user = request.user transaction.save() form.save() return redirect('pfm.views.massive_tr_edit') else: #show only revalent values to select for the user query=Transaction.objects.filter(user=request.user).order_by('-tr_date') paginator = Paginator(query, 8) page = request.GET.get('page') try: trs = paginator.page(page) except PageNotAnInteger: trs = paginator.page(1) except EmptyPage: trs = paginator.page(paginator.num_pages) page_query = query.filter(id__in=[tr.id for tr in trs]) form = TestTrModel1(queryset=page_query, form_kwargs={'user': request.user}) context = {'form': form, 'trs': trs} return render(request, 'pfm/tr_edit.html', context) @login_required(login_url="login/?next=/pfm/") def main(request): accounts = Account.objects.filter(user=request.user).annotate(spent=(Sum('transaction__tr_amount'))) transactions = Transaction.objects.filter(user=request.user).order_by('-tr_date')[:11] categories = Category.objects.filter(transaction__user=request.user, transaction__tr_date__month=date.today().month, transaction__tr_date__year=date.today().year, transaction__tr_type='E').annotate(sum_cat=(Sum('transaction__tr_amount')), avg_ca=Avg('transaction__tr_amount')) sum_total = Transaction.objects.filter(user=request.user, tr_date__month =date.today().month, tr_type='E').aggregate(Sum('tr_amount'))['tr_amount__sum'] date_today = datetime.now() return render(request, 'pfm/base.html', {'accounts': accounts, 'transactions': transactions, 'categories': categories, 'sum_total': sum_total, 'date_today': date_today}) def get_csv(request): transactions = Transaction.objects.defer('tr_date').filter(user=request.user) response = HttpResponse(content_type='text/csv') for item in transactions: date = item.tr_date.strftime('%d.%m.%Y') i = '%s,%s,%s,%s,%s,%s\n' % (date, item.tr_type, item.tr_cat, item.tr_acc, item.tr_amount, item.tr_note) #format is equal to uplolad format #response.write(str(i) + '\n') response.write(i) return response def cat_list(request): categories = Category.objects.filter(user=request.user, cat_type='E') sum_total = Transaction.objects.filter(user=request.user, tr_date__month =date.today().month, tr_date__year=date.today().year, tr_type='E').aggregate(Sum('tr_amount'))['tr_amount__sum'] if sum_total == None: sum_total = 0 budget_total = Category.objects.filter(user=request.user, cat_type='E').aggregate(Sum('budget_amount'))['budget_amount__sum'] try: total_balance = budget_total - sum_total except: total_balance = 0 try: progress = sum_total/budget_total*100 except: progress = 100 #form_new = modelformset_factory(Category, exclude=('user',)) #form = NewCategory(request.POST) form = NewCategory(request.POST) if request.POST.get('action') == 'delete': category = Category.objects.get(id=request.POST.get('id')) category.delete() return redirect('/pfm/category/#!') elif request.POST.get('action') == 'create': if form.is_valid(): category = form.save(commit=False) category.user = request.user category.save() return redirect('/category/#!') elif request.POST.get('action') == 'edit': print request.POST cat = Category.objects.get(id=request.POST['id']) form = NewCategory(request.POST, instance = cat ) if form.is_valid(): category = form.save(commit=False) category.user = request.user category.save() return redirect('/category/#!') # return redirect('pfm.views.cat_list') else: print('Not valid!', form.errors) else: try: form = NewCategory(instance=Category.objects.get(id=request.GET['id'])) return HttpResponse (form) # return render(request, 'pfm/cat_tmpl.html', {'form': form,}) except: form = NewCategory() return render(request, 'pfm/categories.html', {'form': form, 'categories': categories, 'sum_total': sum_total, 'budget_total': budget_total, 'total_balance': total_balance, 'progress': progress}) def reports(request): categories = Category.objects.filter(transaction__user=request.user, transaction__tr_date__month=date.today().month, transaction__tr_date__year=date.today().year, transaction__tr_type='E').order_by('-sum_cat').annotate( sum_cat=Sum('transaction__tr_amount')).order_by('-sum_cat') sum_total = Transaction.objects.filter(user=request.user, tr_date__month =date.today().month, tr_date__year=date.today().year, tr_type='E').aggregate(Sum('tr_amount'))['tr_amount__sum'] date_today = datetime.now() selected_month = datetime.now().month year_list = [2015, 2016, 2017] #months = Transaction.objects.datetimes('tr_date', 'month').aggregate(Sum('tr_amount')) month = date.today().month year = date.today().year testing = '%d %d' % (selected_month, year) datedate = date_today mon_calendar = calendar.LocaleHTMLCalendar(0, "ru_RU.utf-8").formatmonth(year, month) context = {'categories': categories, 'datedate': datedate, 'date_today': date_today, 'month': month, 'testing': testing, 'sum_total': sum_total, 'mon_calendar': mon_calendar, 'years': year_list} if request.method == 'POST': print request.__dict__ print '------month-------: %s' % (request.POST.get('selected_month')) selected_month=request.POST.get('selected_month') selected_year=request.POST.get('selected_year') if selected_month == '13': selected_month = 1 selected_year = int(selected_year)+1 if selected_month == '0': selected_month = 12 selected_year = int(selected_year)-1 print selected_month, selected_year #months = Transaction.objects.datetimes('tr_date', 'month') categories = Category.objects.filter(transaction__user=request.user, transaction__tr_date__month=selected_month, transaction__tr_date__year=selected_year, transaction__tr_type='E').annotate( sum_cat=(Sum('transaction__tr_amount')), avg_cat=Avg('transaction__tr_amount')).order_by('-sum_cat') datedate = date(year=int(selected_year), month=int(selected_month), day=1) sum_total = Transaction.objects.filter(user=request.user, tr_date__month=selected_month, tr_date__year=selected_year, tr_type='E').aggregate(Sum('tr_amount'))['tr_amount__sum'] mon_calendar = calendar.LocaleHTMLCalendar(0, "ru_RU.utf-8").formatmonth(int(selected_year), int(selected_month)) context = {'categories': categories, 'month': selected_month, 'datedate': datedate, 'selected_month': selected_month, 'sum_total': sum_total, 'mon_calendar': mon_calendar} return render(request, 'pfm/reports.html', context) return render(request, 'pfm/reports.html', context) def upload_tr(request): if request.method == 'POST': form = Upload(request.POST, request.FILES) if form.is_valid: try: for row in request.FILES['uploaded']: row = row.split(',') print len(row) transaction = Transaction() transaction.published_date = timezone.now() transaction.user = request.user transaction.tr_date = datetime.strptime(row[0], '%d.%m.%Y') transaction.tr_type = row[1] transaction.tr_cat_id = Category.objects.get(cat_name=row[2], user = request.user).id transaction.tr_acc_id = Account.objects.get(acc_name=row[3], user = request.user).id if len(row) == 5: transaction.tr_amount = row[4].strip() transaction.tr_note = '' if len(row) == 6: transaction.tr_amount = row[4] transaction.tr_note = row[5].strip() transaction.save() return redirect('pfm.views.main') except Account.DoesNotExist: return HttpResponse ('no such acc: %s' % row[1]) except Category.DoesNotExist: return HttpResponse ('no such cat: %s' % row[3]) else: form = Upload() return render(request, 'pfm/upload.html', {'form': form})