# Society Self-Service # Copyright © 2018 Yingtong Li (RunasSudo) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . from django.contrib.auth.decorators import login_required from django.contrib.auth.models import User from django.core.exceptions import PermissionDenied from django.core.validators import validate_email from django.db import transaction from django.shortcuts import render, redirect from django.urls import reverse from django.utils import timezone from django.views import generic from . import models import itertools import json @login_required def index(request): return render(request, 'sstreasury/index.html') @login_required def budget_list(request): budgets_action = [] budgets_open = [] budgets_closed = [] for budget in models.Budget.objects.all(): revision = budget.budgetrevision_set.reverse()[0] state = models.BudgetState(revision.state) if state in [models.BudgetState.DRAFT, models.BudgetState.RESUBMIT]: budgets_action.append(revision) elif state in [models.BudgetState.AWAIT_REVIEW, models.BudgetState.ENDORSED]: budgets_open.append(revision) else: budgets_closed.append(revision) return render(request, 'sstreasury/budget_list.html', { 'budgets_action': budgets_action, 'budgets_open': budgets_open, 'budgets_closed': budgets_closed }) @login_required def budget_view(request, id): budget = models.Budget.objects.get(id=id) if 'revision' in request.GET: revision = budget.budgetrevision_set.get(id=int(request.GET['revision'])) else: revision = budget.budgetrevision_set.reverse()[0] history = list(itertools.chain(budget.budgetrevision_set.all(), revision.budget.budgetcomment_set.all())) history.sort(key=lambda x: x.time, reverse=True) return render(request, 'sstreasury/budget_view.html', { 'revision': revision, 'history': history, 'is_latest': 'revision' not in request.GET }) def revision_from_form(budget, revision, form): revision.budget = budget revision.name = form['name'] revision.date = form['date'] if form['date'] else None revision.comments = form['comments'] revision.state = models.BudgetState.DRAFT.value revision.revenue = json.loads(form['revenue']) revision.revenue_comments = form['revenue_comments'] revision.expense = json.loads(form['expense']) revision.expense_comments = form['expense_comments'] revision.expense_no_emergency_fund = True if form.get('expense_no_emergency_fund', False) else False revision.save() contributors = form['contributors'].split('\n') for contributor in contributors: validate_email(contributor.strip()) for contributor in contributors: try: user = User.objects.get(email=contributor.strip()) except User.DoesNotExist: user = User.objects.create_user(contributor.strip().split('@')[0], contributor.strip()) revision.contributors.add(user) revision.save() return revision @login_required def budget_new(request): if request.method == 'POST': with transaction.atomic(): budget = models.Budget() budget.save() revision = models.BudgetRevision() revision.author = request.user revision.time = timezone.now() revision = revision_from_form(budget, revision, request.POST) if request.POST['submit'] == 'Save': return redirect(reverse('budget_view', kwargs={'id': budget.id})) else: return redirect(reverse('budget_edit', kwargs={'id': budget.id})) else: budget = models.Budget() revision = models.BudgetRevision() revision.budget = budget return render(request, 'sstreasury/budget_edit.html', { 'revision': revision, 'contributors': request.user.email }) @login_required def budget_edit(request, id): if request.method == 'POST': budget = models.Budget.objects.get(id=id) revision = budget.budgetrevision_set.reverse()[0] if request.user not in revision.contributors.all(): raise PermissionDenied with transaction.atomic(): revision = models.BudgetRevision() revision.author = request.user revision.time = timezone.now() revision = revision_from_form(budget, revision, request.POST) if request.POST['submit'] == 'Save': return redirect(reverse('budget_view', kwargs={'id': budget.id})) else: return redirect(reverse('budget_edit', kwargs={'id': budget.id})) else: budget = models.Budget.objects.get(id=id) revision = budget.budgetrevision_set.reverse()[0] return render(request, 'sstreasury/budget_edit.html', { 'revision': revision, 'contributors': '\n'.join(revision.contributors.all().values_list('email', flat=True)) }) @login_required def budget_action(request, id): budget = models.Budget.objects.get(id=id) revision = budget.budgetrevision_set.reverse()[0] if request.user not in revision.contributors.all(): raise PermissionDenied if request.POST['action'] == 'Comment': comment = models.BudgetComment() comment.budget = budget comment.author = request.user comment.time = timezone.now() comment.content = request.POST['comment'] comment.save() return redirect(reverse('budget_view', kwargs={'id': budget.id}))