Budget print view
This commit is contained in:
parent
9e1cc75287
commit
0d44b8ec78
154
sstreasury/jinja2/sstreasury/budget_print.html
Normal file
154
sstreasury/jinja2/sstreasury/budget_print.html
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
{% extends 'ssmain/base.html' %}
|
||||||
|
|
||||||
|
{#
|
||||||
|
Society Self-Service
|
||||||
|
Copyright © 2018-2019 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/>.
|
||||||
|
#}
|
||||||
|
|
||||||
|
{% block title %}{{ revision.name }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>{{ revision.name }}</h1>
|
||||||
|
|
||||||
|
<span class="ui header">Status: {{ revision.get_state_display() }}</span>
|
||||||
|
|
||||||
|
{% if not is_latest %}
|
||||||
|
<div class="ui warning message">
|
||||||
|
<p>You are printing an older version of this budget.</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<table class="ui mydefinition table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="two wide">ID</td>
|
||||||
|
<td class="fourteen wide">{{ revision.budget.id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Name</td>
|
||||||
|
<td>{{ revision.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Due date</td>
|
||||||
|
<td>{{ revision.date or '' }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Contributors</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui list">
|
||||||
|
{% for contributor in revision.contributors.all() %}
|
||||||
|
<div class="item">
|
||||||
|
<i class="user circle icon"></i>
|
||||||
|
<div class="content"><a href="mailto:{{ contributor.email }}">
|
||||||
|
{% if contributor.first_name %}
|
||||||
|
{{ contributor.first_name }} {{ contributor.last_name }}
|
||||||
|
{% else %}
|
||||||
|
{{ contributor.email }}
|
||||||
|
{% endif %}
|
||||||
|
</a></div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Comments</td>
|
||||||
|
<td>{{ revision.comments }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Revenue</td>
|
||||||
|
<td>
|
||||||
|
<div id="revenue_grid"></div>
|
||||||
|
{% if revision.revenue_comments %}
|
||||||
|
<div class="ui accordion">
|
||||||
|
<div class="active title">
|
||||||
|
<i class="dropdown icon"></i>
|
||||||
|
Revenue comments
|
||||||
|
</div>
|
||||||
|
<div class="active content">
|
||||||
|
{{ revision.revenue_comments }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Expenses</td>
|
||||||
|
<td>
|
||||||
|
{% if revision.expense_no_emergency_fund %}
|
||||||
|
<p><input type="checkbox" id="expense_no_emergency_fund" disabled checked> No emergency fund required (please add a comment explaining why)</p>
|
||||||
|
{% endif %}
|
||||||
|
<div id="expense_grid"></div>
|
||||||
|
{% if revision.expense_comments %}
|
||||||
|
<div class="ui accordion">
|
||||||
|
<div class="active title">
|
||||||
|
<i class="dropdown icon"></i>
|
||||||
|
Expense comments
|
||||||
|
</div>
|
||||||
|
<div class="active content">
|
||||||
|
{{ revision.expense_comments }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{{ super() }}
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jsgrid@1.5.3/dist/jsgrid.min.css" integrity="sha256-a/jNbtm7jpeKiXCShJ8YC+eNL9Abh7CBiYXHgaofUVs=" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jsgrid@1.5.3/dist/jsgrid-theme.min.css" integrity="sha256-0rD7ZUV4NLK6VtGhEim14ZUZGC45Kcikjdcr4N03ddA=" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
/* Fix the CSS */
|
||||||
|
|
||||||
|
.ui.mydefinition.table > tbody > tr > td:first-child:not(.ignored) {
|
||||||
|
background: rgba(0,0,0,.03);
|
||||||
|
font-weight: 700;
|
||||||
|
color: rgba(0,0,0,.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.jsgrid-align-right, .jsgrid-align-right input, .jsgrid-align-right select, .jsgrid-align-right textarea {
|
||||||
|
text-align: right !important;
|
||||||
|
}
|
||||||
|
.jsgrid-cell {
|
||||||
|
padding: .5em !important;
|
||||||
|
}
|
||||||
|
.jsgrid-header-row .jsgrid-header-cell {
|
||||||
|
text-align: center !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block script %}
|
||||||
|
{{ super() }}
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/jsgrid@1.5.3/dist/jsgrid.min.js" integrity="sha256-lzjMTpg04xOdI+MJdjBst98bVI6qHToLyVodu3EywFU=" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<script src="{{ static('sstreasury/budget.js') }}"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var revenue_data = JSON.parse({{ import('json').dumps(import('json').dumps(revision.revenue))|safe }});
|
||||||
|
var expense_data = JSON.parse({{ import('json').dumps(import('json').dumps(revision.expense))|safe }});
|
||||||
|
var editing = false;
|
||||||
|
makeGrid();
|
||||||
|
|
||||||
|
print();
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -23,10 +23,10 @@
|
|||||||
{% block maincontent %}
|
{% block maincontent %}
|
||||||
<h1>{{ revision.name }}</h1>
|
<h1>{{ revision.name }}</h1>
|
||||||
|
|
||||||
{% if is_latest %}
|
|
||||||
<form class="ui form" action="{{ url('budget_action', kwargs={'id': revision.budget.id}) }}" method="POST">
|
<form class="ui form" action="{{ url('budget_action', kwargs={'id': revision.budget.id}) }}" method="POST">
|
||||||
<span class="ui header">Status: {{ revision.get_state_display() }}</span>
|
<span class="ui header">Status: {{ revision.get_state_display() }}</span>
|
||||||
|
|
||||||
|
{% if is_latest %}
|
||||||
{% if revision.state == import('sstreasury.models').BudgetState.DRAFT.value or revision.state == import('sstreasury.models').BudgetState.RESUBMIT.value %}
|
{% 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>
|
<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>
|
||||||
|
|
||||||
@ -51,21 +51,26 @@
|
|||||||
|
|
||||||
{% 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())) %}
|
{% 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>
|
<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_print', kwargs={'id': revision.budget.id}) }}" target="_blank"><i class="print icon"></i> Print</a>
|
||||||
{% elif revision.state == import('sstreasury.models').BudgetState.APPROVED.value %}
|
{% elif revision.state == import('sstreasury.models').BudgetState.APPROVED.value %}
|
||||||
{# Blank #}
|
<a class="ui mini labeled right floated icon button" href="{{ url('budget_print', kwargs={'id': revision.budget.id}) }}" target="_blank"><i class="print icon"></i> Print</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<a class="ui mini labeled right floated icon button" href="{{ url('budget_print', kwargs={'id': revision.budget.id}) }}" target="_blank"><i class="print icon"></i> Print</a>
|
||||||
|
|
||||||
<div class="ui message">
|
<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>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
|
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
|
||||||
</form>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="ui warning message">
|
<a class="ui mini labeled right floated icon button" href="{{ url('budget_print', kwargs={'id': revision.budget.id}) }}?revision={{ revision.id }}" target="_blank"><i class="print icon"></i> Print</a>
|
||||||
|
|
||||||
|
<div class="ui visible warning message">
|
||||||
<p>You are viewing an older version of this budget. To make any changes, <a href="{{ url('budget_view', kwargs={'id': revision.budget.id}) }}">click here</a> to return to the current version.</p>
|
<p>You are viewing an older version of this budget. To make any changes, <a href="{{ url('budget_view', kwargs={'id': revision.budget.id}) }}">click here</a> to return to the current version.</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</form>
|
||||||
|
|
||||||
<table class="ui mydefinition table">
|
<table class="ui mydefinition table">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -22,6 +22,7 @@ urlpatterns = [
|
|||||||
path('budgets/', views.budget_list, name='budget_list'),
|
path('budgets/', views.budget_list, name='budget_list'),
|
||||||
path('budgets/new/', views.budget_new, name='budget_new'),
|
path('budgets/new/', views.budget_new, name='budget_new'),
|
||||||
path('budgets/view/<int:id>', views.budget_view, name='budget_view'),
|
path('budgets/view/<int:id>', views.budget_view, name='budget_view'),
|
||||||
|
path('budgets/view/<int:id>/print', views.budget_print, name='budget_print'),
|
||||||
path('budgets/edit/<int:id>', views.budget_edit, name='budget_edit'),
|
path('budgets/edit/<int:id>', views.budget_edit, name='budget_edit'),
|
||||||
path('budgets/action/<int:id>', views.budget_action, name='budget_action'),
|
path('budgets/action/<int:id>', views.budget_action, name='budget_action'),
|
||||||
path('', views.index, name='treasury'),
|
path('', views.index, name='treasury'),
|
||||||
|
@ -85,6 +85,10 @@ def budget_view(request, id):
|
|||||||
else:
|
else:
|
||||||
revision = budget.budgetrevision_set.reverse()[0]
|
revision = budget.budgetrevision_set.reverse()[0]
|
||||||
|
|
||||||
|
if request.user not in revision.contributors.all():
|
||||||
|
if not request.user.groups.filter(name='Treasury').exists():
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
history = list(itertools.chain(budget.budgetrevision_set.all(), revision.budget.budgetcomment_set.all()))
|
history = list(itertools.chain(budget.budgetrevision_set.all(), revision.budget.budgetcomment_set.all()))
|
||||||
history.sort(key=lambda x: x.time, reverse=True)
|
history.sort(key=lambda x: x.time, reverse=True)
|
||||||
|
|
||||||
@ -94,6 +98,24 @@ def budget_view(request, id):
|
|||||||
'is_latest': 'revision' not in request.GET
|
'is_latest': 'revision' not in request.GET
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def budget_print(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]
|
||||||
|
|
||||||
|
if request.user not in revision.contributors.all():
|
||||||
|
if not request.user.groups.filter(name='Treasury').exists():
|
||||||
|
raise PermissionDenied
|
||||||
|
|
||||||
|
return render(request, 'sstreasury/budget_print.html', {
|
||||||
|
'revision': revision,
|
||||||
|
'is_latest': 'revision' not in request.GET
|
||||||
|
})
|
||||||
|
|
||||||
def revision_from_form(budget, revision, form):
|
def revision_from_form(budget, revision, form):
|
||||||
revision.budget = budget
|
revision.budget = budget
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user