Add withdrawn, cancelled budget states
This commit is contained in:
parent
e7e39ef66f
commit
1344f612f8
@ -43,6 +43,9 @@
|
|||||||
{% if revision.can_withdraw(request.user) %}
|
{% if revision.can_withdraw(request.user) %}
|
||||||
<button class="ui mini labeled basic negative icon button" data-action="Withdraw" style="margin-left: 1em;" onclick="return uiConfirm(this);"><i class="undo icon"></i> Withdraw</button>
|
<button class="ui mini labeled basic negative icon button" data-action="Withdraw" style="margin-left: 1em;" onclick="return uiConfirm(this);"><i class="undo icon"></i> Withdraw</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if revision.can_cancel(request.user) %}
|
||||||
|
<button class="ui mini labeled basic negative icon button" data-action="Cancel" style="margin-left: 1em;" onclick="return uiConfirm(this);"><i class="times circle outline icon"></i> Cancel</button>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if revision.can_edit(request.user) %}
|
{% if revision.can_edit(request.user) %}
|
||||||
<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>
|
<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>
|
||||||
@ -290,6 +293,9 @@
|
|||||||
<div class="content" data-action="Withdraw">
|
<div class="content" data-action="Withdraw">
|
||||||
<p>Are you sure you want to withdraw this budget from being considered for approval? The budget will be reverted to a draft.</p>
|
<p>Are you sure you want to withdraw this budget from being considered for approval? The budget will be reverted to a draft.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="content" data-action="Cancel">
|
||||||
|
<p>Are you sure you want to cancel this budget?</p>
|
||||||
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<div class="ui primary approve button">Continue</div>
|
<div class="ui primary approve button">Continue</div>
|
||||||
<div class="ui cancel button">Cancel</div>
|
<div class="ui cancel button">Cancel</div>
|
||||||
|
@ -44,11 +44,12 @@ class BudgetComment(models.Model):
|
|||||||
|
|
||||||
class BudgetState(DescriptionEnum):
|
class BudgetState(DescriptionEnum):
|
||||||
DRAFT = 10, 'Draft'
|
DRAFT = 10, 'Draft'
|
||||||
|
WITHDRAWN = 15, 'Withdrawn'
|
||||||
RESUBMIT = 20, 'Returned for redrafting'
|
RESUBMIT = 20, 'Returned for redrafting'
|
||||||
AWAIT_REVIEW = 30, 'Awaiting Treasury review'
|
AWAIT_REVIEW = 30, 'Awaiting Treasury review'
|
||||||
ENDORSED = 40, 'Endorsed by Treasury, awaiting committee approval'
|
ENDORSED = 40, 'Endorsed by Treasury, awaiting committee approval'
|
||||||
APPROVED = 50, 'Approved'
|
APPROVED = 50, 'Approved'
|
||||||
#CANCELLED = 60, 'Cancelled'
|
CANCELLED = 60, 'Cancelled'
|
||||||
|
|
||||||
class BudgetAction(DescriptionEnum):
|
class BudgetAction(DescriptionEnum):
|
||||||
CREATE = 5, 'Created'
|
CREATE = 5, 'Created'
|
||||||
@ -121,7 +122,7 @@ class BudgetRevision(models.Model):
|
|||||||
return True
|
return True
|
||||||
if user.groups.filter(name='Treasury').exists():
|
if user.groups.filter(name='Treasury').exists():
|
||||||
return True
|
return True
|
||||||
if (self.state == BudgetState.AWAIT_REVIEW.value or self.state == BudgetState.ENDORSED.value or self.state == BudgetState.APPROVED.value) and user.groups.filter(name='Committee').exists():
|
if self.state in (BudgetState.AWAIT_REVIEW.value, BudgetState.ENDORSED.value, BudgetState.APPROVED.value) and user.groups.filter(name='Committee').exists():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
@ -136,7 +137,7 @@ class BudgetRevision(models.Model):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
# Only Treasurer or Secretary may edit if submitted
|
# Only Treasurer or Secretary may edit if submitted
|
||||||
if self.state != BudgetState.DRAFT.value and self.state != BudgetState.RESUBMIT.value:
|
if self.state not in (BudgetState.DRAFT.value, BudgetState.RESUBMIT.value, BudgetState.WITHDRAWN.value):
|
||||||
if user.groups.filter(name='Treasury').exists() or user.groups.filter(name='Secretary').exists():
|
if user.groups.filter(name='Treasury').exists() or user.groups.filter(name='Secretary').exists():
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
@ -155,7 +156,7 @@ class BudgetRevision(models.Model):
|
|||||||
def can_submit(self, user):
|
def can_submit(self, user):
|
||||||
if not self.can_edit(user):
|
if not self.can_edit(user):
|
||||||
return False
|
return False
|
||||||
if self.state == BudgetState.DRAFT.value or self.state == BudgetState.RESUBMIT.value:
|
if self.state in (BudgetState.DRAFT.value, BudgetState.RESUBMIT.value, BudgetState.WITHDRAWN.value):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -165,7 +166,7 @@ class BudgetRevision(models.Model):
|
|||||||
if user != self.author and user not in self.contributors.all() and not user.groups.filter(name='Treasury').exists():
|
if user != self.author and user not in self.contributors.all() and not user.groups.filter(name='Treasury').exists():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self.state == BudgetState.AWAIT_REVIEW.value or self.state == BudgetState.ENDORSED.value:
|
if self.state in (BudgetState.DRAFT.value, BudgetState.RESUBMIT.value, BudgetState.AWAIT_REVIEW.value, BudgetState.ENDORSED.value):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -174,7 +175,7 @@ class BudgetRevision(models.Model):
|
|||||||
return False
|
return False
|
||||||
if not user.groups.filter(name='Treasury').exists():
|
if not user.groups.filter(name='Treasury').exists():
|
||||||
return False
|
return False
|
||||||
if self.state == BudgetState.AWAIT_REVIEW.value or self.state == BudgetState.DRAFT.value or self.state == BudgetState.RESUBMIT.value:
|
if self.state in (BudgetState.AWAIT_REVIEW.value, BudgetState.DRAFT.value, BudgetState.RESUBMIT.value, BudgetState.WITHDRAWN.value):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -197,6 +198,15 @@ class BudgetRevision(models.Model):
|
|||||||
return False
|
return False
|
||||||
return self.can_approve(user)
|
return self.can_approve(user)
|
||||||
|
|
||||||
|
def can_cancel(self, user):
|
||||||
|
if not self.can_view(user):
|
||||||
|
return False
|
||||||
|
if not user.groups.filter(name='Secretary').exists() and not user.groups.filter(name='Treasury').exists():
|
||||||
|
return False
|
||||||
|
if self.state != BudgetState.APPROVED.value:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
class ClaimState(DescriptionEnum):
|
class ClaimState(DescriptionEnum):
|
||||||
DRAFT = 10, 'Draft'
|
DRAFT = 10, 'Draft'
|
||||||
RESUBMIT = 20, 'Returned for redrafting'
|
RESUBMIT = 20, 'Returned for redrafting'
|
||||||
|
@ -211,6 +211,9 @@ def budget_list(request):
|
|||||||
revision = budget.budgetrevision_set.reverse()[0]
|
revision = budget.budgetrevision_set.reverse()[0]
|
||||||
state = models.BudgetState(revision.state)
|
state = models.BudgetState(revision.state)
|
||||||
|
|
||||||
|
if not revision.can_view(request.user):
|
||||||
|
continue
|
||||||
|
|
||||||
group = None
|
group = None
|
||||||
|
|
||||||
if request.user.groups.filter(name='Treasury').exists() and state == models.BudgetState.AWAIT_REVIEW:
|
if request.user.groups.filter(name='Treasury').exists() and state == models.BudgetState.AWAIT_REVIEW:
|
||||||
@ -226,8 +229,8 @@ def budget_list(request):
|
|||||||
group = budgets_open
|
group = budgets_open
|
||||||
else:
|
else:
|
||||||
group = budgets_closed
|
group = budgets_closed
|
||||||
elif request.user.groups.filter(name='Treasury').exists() or request.user.groups.filter(name='Secretary').exists() or request.user.groups.filter(name='Committee').exists():
|
else:
|
||||||
if state == models.BudgetState.APPROVED:
|
if state in (models.BudgetState.APPROVED, models.BudgetState.WITHDRAWN, models.BudgetState.CANCELLED):
|
||||||
group = budgets_closed
|
group = budgets_closed
|
||||||
else:
|
else:
|
||||||
group = budgets_open
|
group = budgets_open
|
||||||
@ -390,7 +393,7 @@ def budget_action(request, budget, revision):
|
|||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
revision.update_state(request.user, models.BudgetState.DRAFT)
|
revision.update_state(request.user, models.BudgetState.WITHDRAWN)
|
||||||
|
|
||||||
if 'Endorse' in actions:
|
if 'Endorse' in actions:
|
||||||
if not revision.can_endorse(request.user):
|
if not revision.can_endorse(request.user):
|
||||||
@ -438,6 +441,13 @@ def budget_action(request, budget, revision):
|
|||||||
for user in revision.contributors.all():
|
for user in revision.contributors.all():
|
||||||
emailer.send_mail([user.email], 'Action required: Budget returned for re-drafting: {} (BU-{})'.format(revision.name, budget.id), 'sstreasury/email/budget_returned_committee.md', {'revision': revision})
|
emailer.send_mail([user.email], 'Action required: Budget returned for re-drafting: {} (BU-{})'.format(revision.name, budget.id), 'sstreasury/email/budget_returned_committee.md', {'revision': revision})
|
||||||
|
|
||||||
|
if 'Cancel' in actions:
|
||||||
|
if not revision.can_cancel(request.user):
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
revision.update_state(request.user, models.BudgetState.CANCELLED)
|
||||||
|
|
||||||
return redirect(reverse('budget_view', kwargs={'id': budget.id}))
|
return redirect(reverse('budget_view', kwargs={'id': budget.id}))
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
Loading…
Reference in New Issue
Block a user