society-self-service/sstreasury/views.py

177 lines
5.6 KiB
Python

# 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 <https://www.gnu.org/licenses/>.
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}))