Merge branch 'feature/use_generic_views' into develop

This commit is contained in:
Robert Einsle 2017-04-27 14:05:21 +02:00
commit b345c9dfaf
12 changed files with 189 additions and 134 deletions

View File

@ -10,6 +10,7 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('sessions', '0001_initial'),
]
operations = [

View File

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11 on 2017-04-27 08:35
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('billard', '0021_accounting_account_user'),
]
operations = [
migrations.AlterField(
model_name='client',
name='location',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='clients', to='billard.Location', verbose_name='Standort'),
),
]

View File

@ -48,7 +48,7 @@ class Location(models.Model):
class Client(models.Model):
uuid = models.UUIDField(unique=True, default=uuid.uuid4, verbose_name="Identifier")
location = models.ForeignKey(Location, verbose_name="Standort")
location = models.ForeignKey(Location, related_name="clients", verbose_name="Standort")
report_user = models.ForeignKey(User, blank=True, null=True, verbose_name="Reporting Benutzer", related_name='reporting_clients')
def __str__(self):

View File

@ -1,24 +1,14 @@
{% extends 'billard/base.html' %}
{% load display_client %}
{% block title %}Accounting Data{% endblock %}
{% block title %}Abrechnung{% endblock %}
{% block content %}
{% if not locations|length_is:"1" %}
<form action="accounting" method="post" id="location-form">
{% csrf_token %}
<div id="location-selector" class="alert">
<select class="form-control" form="location-form" name="location-selector" id="location-select">
{% for loc in locations %}
<option value="{{ loc.id }}"{% if loc.id == location_id %} selected{% endif %}>{{ loc.code }} - {{ loc.name }}</option>
{% endfor %}
</select>
</div>
</form>
{% endif %}
<div class="alert alert-success" role="alert">Gesamt-Summe: {{ acc_sum }}</div>
{{ pk }}
<table class="table">
<tr>
<th>Start-Datum:</th>
@ -38,7 +28,7 @@
{% endfor %}
</table>
<form action="accounting" method="post" id="accounting">
<form action="confirm/" method="post" id="accounting">
{% csrf_token %}
<input type="hidden" name="location-selector" value="{{ location_id }}">
<input type="hidden" name="accountings" value="{{ acc_ids }}">

View File

@ -22,7 +22,7 @@
</table>
</div>
<div class="modal-footer">
<a class="btn btn-default btn-primary" href="{% url 'accountmodalconfirm' account.pk %}">Schliessen</a>
<a class="btn btn-default btn-primary" href="{% url 'billard:account_modal_confirm' pk=account.id %}">Schliessen</a>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->

View File

@ -5,7 +5,7 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}TITLE SETZEN{% endblock %}</title>
<title>carom - {% block title %}TITLE SETZEN{% endblock %}</title>
<meta name="description" content="">
<meta name="author" content="">
{% block header %}
@ -28,10 +28,7 @@
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li class="{% ifequal request.path '/billard/' %}active{% endifequal %}"><a href="{% url "carom_index" %}">Tische</a></li>
{% if perms.billard.change_accounting %}
<li class="{% ifequal request.path '/billard/accounting' %}active{% endifequal %}"><a href="{% url "accounting" %}">Abrechnung</a></li>
{% endif %}
<li class="{% ifequal request.path '/billard/' %}active{% endifequal %}"><a href="{% url "billard:location_index" %}">Standorte</a></li>
{% if user.is_superuser %}
<li class="{% ifequal request.path '/logout/' %}active{% endifequal %}"><a href="/admin/">Administration</a></li>
{% endif %}

View File

@ -16,12 +16,17 @@
</div>
</form>
{% endif %}
<div id="desk_data">
{% include 'billard/index_ajax.html' %}
</div>
<div id="modal-wrapper">
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
var interval;

View File

@ -0,0 +1,31 @@
{% extends 'billard/base.html' %}
{% block title %}Standort{% endblock %}
{% block content %}
<div id="desk_data">
{% include 'billard/location_detail_ajax.html' %}
</div>
<div id="modal-wrapper">
</div>
{% endblock %}
{% block js %}
<script type="text/javascript">
var interval;
$(document).ready(function() {
$.ajaxSetup({ cache: false });
interval = window.setInterval(refresh_page, 1000);
});
function refresh_page() {
$('#desk_data').load('#');
$('#modal-wrapper').load('{% url 'billard:account_modal' %}', function() {
if ( $('#accountsmodal').length ) {
window.clearInterval(interval);
$('#accountsmodal').modal('show');
}
});
}
</script>
{% endblock %}

View File

@ -0,0 +1,12 @@
{% load display_client %}
{% if location.clients.all %}
{% for cli in location.clients.all %}
{% for i in "12345678" %}
{{ cli|display_client:i }}
{% endfor %}
{% endfor %}
{% else %}
<div class="col-md-12">
<div class="col-md-12 alert alert-danger">Keine Tische angelegt!</div>
</div>
{% endif %}

View File

@ -0,0 +1,37 @@
{% extends 'billard/base.html' %}
{% block title %}Standortliste{% endblock %}
{% block content %}
{% if location_list %}
<h2>Bitte Standort auswählen:</h2>
<table class="table table-hover">
<tr>
<th>Code</th>
<th>Name</th>
<th>Strasse</th>
<th>Plz</th>
<th>Ort</th>
{% if perms.billard.change_accounting %}
<th>Accounting</th>
{% endif %}
</tr>
{% for loc in location_list %}
<tr>
<td><a href="{% url 'billard:location_detail' loc.id %}">{{ loc.code|default_if_none:"" }}</a></td>
<td><a href="{% url 'billard:location_detail' loc.id %}">{{ loc.name|default_if_none:"" }}</a></td>
<td><a href="{% url 'billard:location_detail' loc.id %}">{{ loc.street|default_if_none:"" }}</a></td>
<td><a href="{% url 'billard:location_detail' loc.id %}">{{ loc.plz|default_if_none:"" }}</a></td>
<td><a href="{% url 'billard:location_detail' loc.id %}">{{ loc.city|default_if_none:"" }}</a></td>
{% if perms.billard.change_accounting %}
<td><a href="{% url 'billard:accounting_detail' loc.id %}" class="btn btn-primary">Abrechnen</a></td>
{% endif %}
</tr>
{% endfor %}
</table>
{% else %}
<p>Keine Standorte Zugeordnet.</p>
{% endif %}
{% endblock %}

View File

@ -1,16 +1,27 @@
from django.conf.urls import url, include
from django.contrib.auth.decorators import login_required
from rest_framework import routers
from billard import views
router = routers.DefaultRouter()
router.register(r'location_data', views.LocationDataViewSet)
app_name = 'billard'
urlpatterns = [
url(r'^$', views.index, name='carom_index'),
url(r'^(?P<pk>[0-9]+)/$', views.LocationDataDetailView.as_view(), name='detail'),
# ex. /billard/
url(r'^$', login_required(views.LocationIndexView.as_view()), name='location_index'),
# ex. /billard/1/
url(r'^(?P<pk>[0-9]+)/$', login_required(views.LocationDetailView.as_view()), name='location_detail'),
# ex. /billard/1/accounting/
url(r'^(?P<pk>[0-9]+)/accounting/$', views.AccountingView.as_view(), name='accounting_detail'),
# ex. /billard/1/accounting/confirm
url(r'^(?P<pk>[0-9]+)/accounting/confirm/$', views.accounting_confirm, name='accounting_detail_confirm'),
# ex. /billard/1/account_modal/
url(r'^account_modal/$', views.account_modal_view, name='account_modal'),
# ex. /billard/1/account_modal/confirm/
url(r'^account_modal/(?P<pk>[0-9]+)/confirm/$', views.account_modal_confirm_view, name='account_modal_confirm'),
# ex. /billard/api/v1/ (rest api)
url(r'api/v1/', include(router.urls)),
url(r'process_locationdata', views.process_locationdata, name='process_locationdata'),
url(r'accounting', views.accounting, name='accounting'),
url(r'accountmodal$', views.accountmodalview, name='accountmodal'),
url(r'accoutmodal/confirm/(?P<pk>[0-9]+)$', views.accountmodalconfirmview, name="accountmodalconfirm")
# ex. /billard/process_location_data/
url(r'^process_location_data/$', views.process_location_data, name='process_location_data'),
]

View File

@ -1,44 +1,77 @@
import ast
from billard.serializers import LocationDataSerializer
from billard.models import LocationData, Location, Client, Accounting
from billard.tasks import process_location_data
from rest_framework import viewsets
from django.shortcuts import render, redirect
from django.views import generic
from django.views.generic.detail import DetailView
from django.contrib.auth.decorators import login_required, permission_required
from django.db.models import Min, Sum
from django.http import HttpResponse
from django.utils.decorators import method_decorator
class LocationDataViewSet(viewsets.ModelViewSet):
queryset = LocationData.objects.all()
serializer_class = LocationDataSerializer
class LocationIndexView(generic.ListView):
template_name = 'billard/location_index.html'
context_object_name = 'location_list'
def get_queryset(self):
"""Return the last five published questions."""
return Location.objects.filter(users__id=self.request.user.id).order_by('code')
class IndexView(generic.ListView):
model = LocationData
class LocationDetailView(generic.DetailView):
model = Location
template_name = 'billard/location_detail.html'
def get_template_names(self):
if self.request.is_ajax():
return ('billard/locationdata_list_ajax.html',)
return super().get_template_names()
def dispatch(self, request, *args, **kwargs):
if request.is_ajax():
context = {
'location': self.get_object(),
}
return render(request, template_name='billard/location_detail_ajax.html', context=context)
return super(LocationDetailView, self).dispatch(request, *args, **kwargs)
class LocationDataDetailView(DetailView):
model = LocationData
@method_decorator(login_required, name='dispatch')
class AccountingView(generic.ListView):
template_name = 'billard/accounting.html'
context_object_name = 'accounting'
def get_template_names(self):
if self.request.is_ajax():
return ('billard/locationdata_detail_ajax.html',)
return super().get_template_names()
def get_queryset(self):
return Accounting.objects.filter(billed=False).exclude(time_to__isnull=True).order_by('time_from')
def dispatch(self, request, *args, **kwargs):
result = super(AccountingView, self).dispatch(request, *args, **kwargs)
acc_sum = self.get_queryset().aggregate(Sum('prize'))
if acc_sum['prize__sum'] is None:
result.context_data['acc_sum'] = 0
else:
result.context_data['acc_sum'] = acc_sum['prize__sum']
result.context_data['acc_ids'] = [acc.id for acc in self.get_queryset().all()]
return result
@login_required
def accountmodalview(request):
@permission_required('billard.change_accounting')
def accounting_confirm(request, pk):
if request.method == 'POST':
if 'accountings' in request.POST:
acc_ids = ast.literal_eval(request.POST['accountings'])
if len(acc_ids) > 0:
Accounting.objects.filter(id__in=acc_ids).update(billed=True)
Accounting.objects.filter(id__in=acc_ids).update(account_user=request.user.username)
resp = redirect('billard:accounting_detail', pk=pk)
return resp
@login_required
def account_modal_view(request):
try:
uuids = Client.objects.filter(report_user=request.user).values_list('uuid')
account = Accounting.objects.filter(reporter_uuid__in=uuids).first
#TODO: support multiple account objects
# TODO: support multiple account objects
except Client.DoesNotExist:
account = None
context = {
@ -48,101 +81,18 @@ def accountmodalview(request):
@login_required
def accountmodalconfirmview(request, pk):
def account_modal_confirm_view(request, pk):
account = Accounting.objects.get(pk=pk)
account.reporter_uuid = None
account.save()
return redirect('carom_index')
return redirect('billard:location_detail', pk=account.desk.client.location_id)
@login_required
@permission_required('billard.change_accounting')
def accounting(request):
if request.method == 'GET':
template = 'billard/accounting.html'
loc = None
min_loc = Location.objects.filter(users__id=request.user.id).aggregate(Min('id'))['id__min']
if 'loc' in request.GET:
loc = request.GET['loc']
if not Location.objects.filter(users__id=request.user.id).filter(id=loc).exists():
resp = redirect('accounting')
if min_loc is not None:
resp['Location'] += '?loc={}'.format(str(min_loc))
request.session['loc'] = str(min_loc)
return resp
else:
return render(request, accounting)
if loc is None:
loc = min_loc
locations = Location.objects.filter(users__id=request.user.id).order_by('code')
acc = Accounting.objects.filter(billed=False).exclude(time_to__isnull=True).\
filter(desk__client__location_id=loc).order_by('-time_from')
acc_sum = acc.aggregate(Sum('prize'))
acc_ids = list()
for a in acc:
acc_ids.append(a.id)
context = {
'location_id': int(loc),
'locations': locations,
'accounting': acc,
'acc_ids': ','.join(str(e) for e in acc_ids),
}
if acc_sum['prize__sum'] is None:
context['acc_sum'] = 0
else:
context['acc_sum'] = acc_sum['prize__sum']
return render(request, template_name=template, context=context)
if request.method == 'POST':
loc = request.POST['location-selector']
if 'accountings' in request.POST:
acc_ids = request.POST['accountings'].split(',')
Accounting.objects.filter(id__in=acc_ids).update(billed=True)
Accounting.objects.filter(id__in=acc_ids).update(account_user=request.user.username)
request.session['loc'] = str(loc)
resp = redirect('accounting')
resp['Location'] += '?loc={}'.format(str(loc))
return resp
class LocationDataViewSet(viewsets.ModelViewSet):
queryset = LocationData.objects.all()
serializer_class = LocationDataSerializer
@login_required
def index(request):
if request.method == 'GET':
template = 'billard/index.html'
loc = None
if request.is_ajax():
template = 'billard/index_ajax.html'
loc = request.session.get('loc')
min_loc = Location.objects.filter(users__id=request.user.id).aggregate(Min('id'))['id__min']
if 'loc' in request.GET:
loc = request.GET['loc']
if not Location.objects.filter(users__id=request.user.id).filter(id=loc).exists():
resp = redirect('carom_index')
if min_loc is not None:
resp['Location'] += '?loc={}'.format(str(min_loc))
request.session['loc'] = str(min_loc)
return resp
else:
return render(request, template)
if loc is None:
loc = min_loc
locations = Location.objects.filter(users__id=request.user.id).order_by('code')
clients = Client.objects.filter(location_id=loc).order_by('id')
context = {
'range': range(1, 9),
'locations': locations,
'clients': clients,
'location_id': int(loc),
}
return render(request, template, context=context)
if request.method == 'POST':
loc = request.POST['location-selector']
request.session['loc'] = str(loc)
resp = redirect('carom_index')
resp['Location'] += '?loc={}'.format(str(loc))
return resp
def process_locationdata(request):
def process_location_data(request):
process_location_data()
return HttpResponse('DONE')