Committee approval of budgets
This commit is contained in:
parent
69a7c052c1
commit
a43c7da302
@ -29,12 +29,20 @@
|
||||
|
||||
{% if revision.state == import('sstreasury.models').BudgetState.DRAFT.value or revision.state == import('sstreasury.models').BudgetState.RESUBMIT.value %}
|
||||
<button class="ui mini labeled primary icon button" type="submit" name="action" value="Submit" style="margin-left: 1em;" onclick="return confirm('Are you sure you want to submit this budget for Treasury approval? You will not be able to make any additional changes without withdrawing the budget.');"><i class="paper plane icon"></i> Submit</button>
|
||||
|
||||
{% if request.user.groups.filter(name='Secretary').exists() %}
|
||||
<button class="ui mini labeled positive icon button" type="submit" name="action" value="Approve" onclick="return confirm('Are you sure you want to mark this budget as committee-approved?');"><i class="check icon"></i> Approve</button>
|
||||
|
||||
<button class="ui mini labeled basic negative icon button" type="submit" name="action" value="CmteReturn" onclick="return confirm('Are you sure you want to refuse this budget committee approval and return it for re-drafting?');"><i class="undo icon"></i> Return for re-drafting</button>
|
||||
{% endif %}
|
||||
{% elif revision.state == import('sstreasury.models').BudgetState.AWAIT_REVIEW.value and request.user.groups.filter(name='Treasury').exists() %}
|
||||
<button class="ui mini labeled positive icon button" type="submit" name="action" value="Endorse" style="margin-left: 1em;" onclick="return confirm('Are you sure you want to give this budget Treasury endorsement?');"><i class="check icon"></i> Endorse</button>
|
||||
|
||||
<button class="ui mini labeled basic negative icon button" type="submit" name="action" value="Return" onclick="return confirm('Are you sure you want to refuse this budget Treasury endorsement and return it for re-drafting?');"><i class="undo icon"></i> Return for re-drafting</button>
|
||||
{% elif revision.state == import('sstreasury.models').BudgetState.ENDORSED.value and request.user.groups.filter(name='Secretary').exists() %}
|
||||
{# TODO #}
|
||||
{% elif revision.state != import('sstreasury.models').BudgetState.APPROVED.value and request.user.groups.filter(name='Secretary').exists() %}
|
||||
<button class="ui mini labeled positive icon button" type="submit" name="action" value="Approve" style="margin-left: 1em;" onclick="return confirm('Are you sure you want to mark this budget as committee-approved?');"><i class="check icon"></i> Approve</button>
|
||||
|
||||
<button class="ui mini labeled basic negative icon button" type="submit" name="action" value="CmteReturn" onclick="return confirm('Are you sure you want to refuse this budget committee approval and return it for re-drafting?');"><i class="undo icon"></i> Return for re-drafting</button>
|
||||
{% elif revision.state == import('sstreasury.models').BudgetState.APPROVED.value %}
|
||||
{# Blank #}
|
||||
{% else %}
|
||||
@ -43,6 +51,8 @@
|
||||
|
||||
{% if revision.state == import('sstreasury.models').BudgetState.DRAFT.value or revision.state == import('sstreasury.models').BudgetState.RESUBMIT.value or (revision.state != import('sstreasury.models').BudgetState.APPROVED.value and (request.user.groups.filter(name='Treasury').exists() or request.user.groups.filter(name='Secretary').exists())) %}
|
||||
<a class="ui mini labeled right floated icon button" href="{{ url('budget_edit', kwargs={'id': revision.budget.id}) }}"><i class="edit icon"></i> Edit</a>
|
||||
{% elif revision.state == import('sstreasury.models').BudgetState.APPROVED.value %}
|
||||
{# Blank #}
|
||||
{% else %}
|
||||
<div class="ui message">
|
||||
<p>This budget has been submitted and is now awaiting approval. If you wish to edit this budget, you must first withdraw it. This will revert the budget to a draft.</p>
|
||||
@ -143,9 +153,13 @@
|
||||
<input class="ui primary button" type="submit" name="action" value="Comment">
|
||||
|
||||
{% if revision.state == import('sstreasury.models').BudgetState.AWAIT_REVIEW.value and request.user.groups.filter(name='Treasury').exists() %}
|
||||
<button class="ui labeled positive icon button" type="submit" name="action" value="Comment,Endorse" onclick="return confirm('Are you sure you want to give this budget Treasury endorsement?');"><i class="check icon"></i> Comment and endorse</button>
|
||||
<button class="ui right floated labeled basic negative icon button" type="submit" name="action" value="Comment,Return" onclick="return confirm('Are you sure you want to refuse this budget Treasury endorsement and return it for re-drafting?');"><i class="undo icon"></i> Comment and return for re-drafting</button>
|
||||
|
||||
<button class="ui labeled basic negative icon button" type="submit" name="action" value="Comment,Return" onclick="return confirm('Are you sure you want to refuse this budget Treasury endorsement and return it for re-drafting?');"><i class="undo icon"></i> Comment and return for re-drafting</button>
|
||||
<button class="ui right floated labeled positive icon button" type="submit" name="action" value="Comment,Endorse" onclick="return confirm('Are you sure you want to give this budget Treasury endorsement?');"><i class="check icon"></i> Comment and endorse</button>
|
||||
{% elif revision.state != import('sstreasury.models').BudgetState.APPROVED.value and request.user.groups.filter(name='Secretary').exists() %}
|
||||
<button class="ui right floated labeled basic negative icon button" type="submit" name="action" value="Comment,CmteReturn" onclick="return confirm('Are you sure you want to refuse this budget committee approval and return it for re-drafting?');"><i class="undo icon"></i> Comment and return for re-drafting</button>
|
||||
|
||||
<button class="ui right floated labeled positive icon button" type="submit" name="action" value="Comment,Approve" onclick="return confirm('Are you sure you want to mark this budget as committee-approved?');"><i class="check icon"></i> Comment and approve</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
|
3
sstreasury/jinja2/sstreasury/email/approved.md
Normal file
3
sstreasury/jinja2/sstreasury/email/approved.md
Normal file
@ -0,0 +1,3 @@
|
||||
Your budget titled *{{ revision.name }}* has been reviewed by the committee and **approved**. The expenditure shown in the budget may now commence.
|
||||
|
||||
{{ baseurl }}{{ url('budget_view', kwargs={'id': revision.budget.id}) }}
|
3
sstreasury/jinja2/sstreasury/email/endorsed_secretary.md
Normal file
3
sstreasury/jinja2/sstreasury/email/endorsed_secretary.md
Normal file
@ -0,0 +1,3 @@
|
||||
A budget titled *{{ revision.name }}* has been endorsed by Treasury and referred to the committee for consideration at its next meeting.
|
||||
|
||||
{{ baseurl }}{{ url('budget_view', kwargs={'id': revision.budget.id}) }}
|
3
sstreasury/jinja2/sstreasury/email/returned_committee.md
Normal file
3
sstreasury/jinja2/sstreasury/email/returned_committee.md
Normal file
@ -0,0 +1,3 @@
|
||||
Your budget titled *{{ revision.name }}* has been reviewed by the committee and returned to you for re-drafting. You should make any requested changes and resubmit the budget.
|
||||
|
||||
{{ baseurl }}{{ url('budget_view', kwargs={'id': revision.budget.id}) }}
|
@ -46,23 +46,29 @@ def budget_list(request):
|
||||
revision = budget.budgetrevision_set.reverse()[0]
|
||||
state = models.BudgetState(revision.state)
|
||||
|
||||
if request.user.groups.filter(name='Treasury').exists():
|
||||
if state == models.BudgetState.AWAIT_REVIEW:
|
||||
budgets_action.append(revision)
|
||||
elif state != models.BudgetState.APPROVED:
|
||||
budgets_open.append(revision)
|
||||
else:
|
||||
budgets_closed.append(revision)
|
||||
else:
|
||||
if request.user not in revision.contributors.all():
|
||||
continue
|
||||
group = None
|
||||
|
||||
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)
|
||||
if request.user.groups.filter(name='Treasury').exists() and state == models.BudgetState.AWAIT_REVIEW:
|
||||
group = budgets_action
|
||||
elif request.user.groups.filter(name='Secretary').exists() and state == models.BudgetState.ENDORSED:
|
||||
group = budgets_action
|
||||
else:
|
||||
if request.user in revision.contributors.all():
|
||||
if state in [models.BudgetState.DRAFT, models.BudgetState.RESUBMIT]:
|
||||
group = budgets_action
|
||||
elif state in [models.BudgetState.AWAIT_REVIEW, models.BudgetState.ENDORSED]:
|
||||
group = budgets_open
|
||||
else:
|
||||
group = budgets_closed
|
||||
else:
|
||||
budgets_closed.append(revision)
|
||||
if request.user in revision.contributors.all() or request.user.groups.filter(name='Treasury').exists() or request.user.groups.filter(name='Secretary').exists():
|
||||
if state == models.BudgetState.APPROVED:
|
||||
group = budgets_closed
|
||||
else:
|
||||
group = budgets_open
|
||||
|
||||
if group is not None:
|
||||
group.append(revision)
|
||||
|
||||
return render(request, 'sstreasury/budget_list.html', {
|
||||
'budgets_action': budgets_action,
|
||||
@ -272,6 +278,8 @@ def budget_action(request, budget, revision):
|
||||
revision.save()
|
||||
|
||||
emailer = Emailer()
|
||||
for user in User.objects.filter(groups__name='Secretary'):
|
||||
emailer.send_mail([user.email], 'Action required: Budget endorsed: {}'.format(revision.name), 'sstreasury/email/endorsed_secretary.md', {'revision': revision})
|
||||
for user in revision.contributors.all():
|
||||
emailer.send_mail([user.email], 'Budget endorsed, awaiting committee approval: {}'.format(revision.name), 'sstreasury/email/endorsed.md', {'revision': revision})
|
||||
|
||||
@ -293,4 +301,40 @@ def budget_action(request, budget, revision):
|
||||
for user in revision.contributors.all():
|
||||
emailer.send_mail([user.email], 'Action required: Budget returned for re-drafting: {}'.format(revision.name), 'sstreasury/email/returned.md', {'revision': revision})
|
||||
|
||||
if 'Approve' in actions:
|
||||
if revision.state == models.BudgetState.APPROVED.value:
|
||||
raise PermissionDenied
|
||||
if not request.user.groups.filter(name='Secretary').exists():
|
||||
raise PermissionDenied
|
||||
|
||||
with transaction.atomic():
|
||||
revision.copy()
|
||||
revision.author = request.user
|
||||
revision.time = timezone.now()
|
||||
revision.state = models.BudgetState.APPROVED.value
|
||||
revision.action = models.BudgetAction.UPDATE_STATE.value
|
||||
revision.save()
|
||||
|
||||
emailer = Emailer()
|
||||
for user in revision.contributors.all():
|
||||
emailer.send_mail([user.email], 'Budget approved: {}'.format(revision.name), 'sstreasury/email/approved.md', {'revision': revision})
|
||||
|
||||
if 'CmteReturn' in actions:
|
||||
if revision.state == models.BudgetState.APPROVED.value:
|
||||
raise PermissionDenied
|
||||
if not request.user.groups.filter(name='Secretary').exists():
|
||||
raise PermissionDenied
|
||||
|
||||
with transaction.atomic():
|
||||
revision.copy()
|
||||
revision.author = request.user
|
||||
revision.time = timezone.now()
|
||||
revision.state = models.BudgetState.RESUBMIT.value
|
||||
revision.action = models.BudgetAction.UPDATE_STATE.value
|
||||
revision.save()
|
||||
|
||||
emailer = Emailer()
|
||||
for user in revision.contributors.all():
|
||||
emailer.send_mail([user.email], 'Action required: Budget returned for re-drafting: {}'.format(revision.name), 'sstreasury/email/returned_committee.md', {'revision': revision})
|
||||
|
||||
return redirect(reverse('budget_view', kwargs={'id': budget.id}))
|
||||
|
Loading…
Reference in New Issue
Block a user