2018-06-26 20:14:16 +10:00
{% extends 'sstreasury/base.html' %}
{#
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 / > .
#}
{% block title %}{{ revision.name }}{% endblock %}
{% block maincontent %}
< h1 > {{ revision.name }}< / h1 >
{% if is_latest %}
2018-06-26 21:58:10 +10:00
< div >
2019-06-19 17:03:52 +10:00
< span class = "ui header" > Status: {{ revision.get_state_display() }}< / span >
2018-06-26 21:58:10 +10:00
< 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 >
< / div >
2018-06-26 20:14:16 +10:00
{% else %}
< div class = "ui 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 >
< / div >
{% endif %}
2018-06-26 23:06:14 +10:00
< table class = "ui mydefinition table" >
2018-06-26 20:14:16 +10:00
< tbody >
< tr >
2018-06-26 23:06:14 +10:00
< td class = "two wide" > ID< / td >
< td class = "fourteen wide" > {{ revision.budget.id }}< / td >
2018-06-26 20:14:16 +10:00
< / 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 >
2018-06-26 23:06:14 +10:00
< div id = "revenue_grid" > < / div >
2018-06-26 20:14:16 +10:00
{% if revision.revenue_comments %}
< div class = "ui accordion" >
< div class = "active title" >
< i class = "dropdown icon" > < / i >
Revenue comments
< / div >
2018-12-07 10:51:43 +11:00
< div class = "active content" >
2018-06-26 20:14:16 +10:00
{{ revision.revenue_comments }}
< / div >
< / div >
{% endif %}
< / td >
< / tr >
< tr >
< td > Expenses< / td >
< td >
2018-06-26 23:06:14 +10:00
< div id = "expense_grid" > < / div >
2018-06-26 20:14:16 +10:00
{% if revision.expense_comments %}
< div class = "ui accordion" >
< div class = "active title" >
< i class = "dropdown icon" > < / i >
Expense comments
< / div >
2018-12-07 10:51:43 +11:00
< div class = "active content" >
2018-06-26 20:14:16 +10:00
{{ revision.expense_comments }}
< / div >
< / div >
{% endif %}
< / td >
< / tr >
< / tbody >
< / table >
{% if is_latest %}
< form class = "ui form" action = "{{ url('budget_action', kwargs={'id': revision.budget.id}) }}" method = "POST" >
< div class = "required field" >
< textarea rows = "4" name = "comment" > < / textarea >
< / div >
< input type = "hidden" name = "csrfmiddlewaretoken" value = "{{ csrf_token }}" >
< input class = "ui primary button" type = "submit" name = "action" value = "Comment" >
< / form >
< div class = "ui feed" >
{% for item in history %}
{% if item.__class__.__name__ == 'BudgetComment' %}
< div class = "event" >
< div class = "label" >
< i class = "comment alternate outline icon" > < / i >
< / div >
< div class = "content" >
< div class = "summary" >
< i class = "user circle icon" > < / i >
< a href = "mailto:{{ item.author.email }}" > {{ item.author.first_name }} {{ item.author.last_name}}< / a > commented
< div class = "date" >
{{ localtime(item.time) }}
< / div >
< / div >
< div class = "extra text" >
{{ item.content }}
< / div >
< / div >
< / div >
{% elif item.__class__.__name__ == 'BudgetRevision' %}
< div class = "event" >
< div class = "label" >
< i class = "edit icon" > < / i >
< / div >
< div class = "content" >
< div class = "summary" >
< i class = "user circle icon" > < / i >
< a href = "mailto:{{ item.author.email }}" > {{ item.author.first_name }} {{ item.author.last_name}}< / a > edited the budget < a href = "{{ url('budget_view', kwargs={'id': revision.budget.id}) }}?revision={{ item.id }}" > (view)< / a >
< div class = "date" >
{{ localtime(item.time) }}
< / div >
< / div >
< / div >
< / div >
{% endif %}
{% endfor %}
< / div >
{% endif %}
{% endblock %}
2018-06-26 23:06:14 +10:00
{% 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 >
2018-12-07 10:51:43 +11:00
/* Fix the CSS */
2018-06-26 23:06:14 +10:00
.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);
}
2018-12-07 10:51:43 +11:00
.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;
}
2018-06-26 23:06:14 +10:00
< / 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 >
2018-12-07 10:51:43 +11:00
$('.ui.accordion').accordion();
2018-06-26 23:06:14 +10:00
function recalcRevTotal(args) {
//console.log(args);
var total = 0;
var totalIWT = 0;
for (var row of args.grid.data) {
2019-06-19 17:03:52 +10:00
total += row['Unit price'] * row['Units'];
if (row['Unit price'] > 0 & & row['IWT']) {
totalIWT += (row['Unit price'] - (row['Unit price'] - 0.8) / 1.019) * row['Units'];
2018-06-26 23:06:14 +10:00
}
}
$(args.grid._body).find('.totalrow').remove();
if (totalIWT > 0) {
2018-12-07 10:51:43 +11:00
var totalrow = $('< tr class = "jsgrid-row totalrow" style = "font-style: italic;" > < / tr > ');
2018-06-26 23:06:14 +10:00
totalrow.append($('< td class = "jsgrid-cell" > Less IWT fees:< / td > ').prop('colspan', args.grid.fields.length - 1));
totalrow.append($('< td class = "jsgrid-cell jsgrid-align-right" > < / td > ').text('($' + totalIWT.toFixed(2) + ')'));
$(args.grid._body).find('tr:last').after(totalrow);
}
var totalrow = $('< tr class = "jsgrid-row totalrow" style = "font-weight: bold;" > < / tr > ');
totalrow.append($('< td class = "jsgrid-cell" > Total:< / td > ').prop('colspan', args.grid.fields.length - 1));
totalrow.append($('< td class = "jsgrid-cell jsgrid-align-right" > < / td > ').text('$' + (total - totalIWT).toFixed(2)));
$(args.grid._body).find('tr:last').after(totalrow);
}
function recalcExpTotal(args) {
var total = 0;
for (var row of args.grid.data) {
2019-06-19 17:03:52 +10:00
total += row['Unit price'] * row['Units'];
2018-06-26 23:06:14 +10:00
}
$(args.grid._body).find('.totalrow').remove();
2018-12-07 10:51:43 +11:00
var totalrow = $('< tr class = "jsgrid-row totalrow" style = "font-style: italic;" > < / tr > ');
2018-06-26 23:06:14 +10:00
totalrow.append($('< td class = "jsgrid-cell" > Plus emergency fund:< / td > ').prop('colspan', args.grid.fields.length - 1));
totalrow.append($('< td class = "jsgrid-cell jsgrid-align-right" > < / td > ').text('$' + (total * 0.05).toFixed(2)));
$(args.grid._body).find('tr:last').after(totalrow);
var totalrow = $('< tr class = "jsgrid-row totalrow" style = "font-weight: bold;" > < / tr > ');
totalrow.append($('< td class = "jsgrid-cell" > Total:< / td > ').prop('colspan', args.grid.fields.length - 1));
totalrow.append($('< td class = "jsgrid-cell jsgrid-align-right" > < / td > ').text('$' + (total * 1.05).toFixed(2)));
$(args.grid._body).find('tr:last').after(totalrow);
}
// Allow floats
function FloatNumberField(config) {
jsGrid.NumberField.call(this, config);
}
FloatNumberField.prototype = new jsGrid.NumberField({
filterValue: function() {
return parseFloat(this.filterControl.val());
},
insertValue: function() {
return parseFloat(this.insertControl.val());
},
editValue: function() {
return parseFloat(this.editControl.val());
}
});
jsGrid.fields.float = FloatNumberField;
var revenue_data = JSON.parse({{ import('json').dumps(import('json').dumps(revision.revenue))|safe }});
$('#revenue_grid').jsGrid({
width: '100%',
height: 'auto',
noDataContent: 'No entries',
data: revenue_data,
fields: [
{ name: 'Description', type: 'text', width: '55%', validate: 'required' },
2019-06-19 17:03:52 +10:00
{ name: 'Unit price', type: 'float', width: '10%', validate: 'required', itemTemplate: function(value, item) { return '$' + value.toFixed(2); } },
2018-06-26 23:06:14 +10:00
{ name: 'Units', type: 'float', width: '10%', validate: 'required' },
{ name: 'IWT', type: 'checkbox', width: '5%' },
2019-06-19 17:03:52 +10:00
{ name: 'Total', align: 'right', width: '10%', itemTemplate: function(value, item) { return '$' + (item['Unit price'] * item['Units']).toFixed(2); } },
2018-06-26 23:06:14 +10:00
],
onRefreshed: recalcRevTotal,
});
var expense_data = JSON.parse({{ import('json').dumps(import('json').dumps(revision.expense))|safe }});
$('#expense_grid').jsGrid({
width: '100%',
height: 'auto',
noDataContent: 'No entries',
data: expense_data,
fields: [
{ name: 'Description', type: 'text', width: '55%', validate: 'required' },
2019-06-19 17:03:52 +10:00
{ name: 'Unit price', type: 'float', width: '10%', validate: 'required', itemTemplate: function(value, item) { return '$' + value.toFixed(2); } },
2018-06-26 23:06:14 +10:00
{ name: 'Units', type: 'float', width: '10%', validate: 'required' },
2019-06-19 17:03:52 +10:00
{ name: 'Total', align: 'right', width: '10%', itemTemplate: function(value, item) { return '$' + (item['Unit price'] * item['Units']).toFixed(2); } },
2018-06-26 23:06:14 +10:00
],
onRefreshed: recalcExpTotal,
});
< / script >
{% endblock %}