diff --git a/billard/migrations/0001_initial.py b/billard/migrations/0001_initial.py index 143db55..6a2e816 100644 --- a/billard/migrations/0001_initial.py +++ b/billard/migrations/0001_initial.py @@ -10,6 +10,7 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('sessions', '0001_initial'), ] operations = [ diff --git a/billard/migrations/0022_auto_20170427_0835.py b/billard/migrations/0022_auto_20170427_0835.py new file mode 100644 index 0000000..96e686e --- /dev/null +++ b/billard/migrations/0022_auto_20170427_0835.py @@ -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'), + ), + ] diff --git a/billard/models.py b/billard/models.py index 689289e..0a7e356 100644 --- a/billard/models.py +++ b/billard/models.py @@ -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): diff --git a/billard/templates/billard/accounting.html b/billard/templates/billard/accounting.html index 112beae..207b502 100644 --- a/billard/templates/billard/accounting.html +++ b/billard/templates/billard/accounting.html @@ -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" %} -
-{% csrf_token %} -
- -
-
-{% endif %} + {{ pk }} + @@ -38,7 +28,7 @@ {% endfor %}
Start-Datum:
-
+ {% csrf_token %} diff --git a/billard/templates/billard/accountmodal.html b/billard/templates/billard/accountmodal.html index 9d0b008..f064504 100644 --- a/billard/templates/billard/accountmodal.html +++ b/billard/templates/billard/accountmodal.html @@ -22,7 +22,7 @@ diff --git a/billard/templates/billard/base.html b/billard/templates/billard/base.html index 137ddb3..5fb9fa6 100644 --- a/billard/templates/billard/base.html +++ b/billard/templates/billard/base.html @@ -5,7 +5,7 @@ - {% block title %}TITLE SETZEN{% endblock %} + carom - {% block title %}TITLE SETZEN{% endblock %} {% block header %} @@ -28,10 +28,7 @@
{% endif %} + + + +
{% include 'billard/index_ajax.html' %}
{% endblock %} + {% block js %} +{% endblock %} \ No newline at end of file diff --git a/billard/templates/billard/location_detail_ajax.html b/billard/templates/billard/location_detail_ajax.html new file mode 100644 index 0000000..cef9821 --- /dev/null +++ b/billard/templates/billard/location_detail_ajax.html @@ -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 %} +
+
Keine Tische angelegt!
+
+{% endif %} diff --git a/billard/templates/billard/location_index.html b/billard/templates/billard/location_index.html new file mode 100644 index 0000000..196b36f --- /dev/null +++ b/billard/templates/billard/location_index.html @@ -0,0 +1,37 @@ +{% extends 'billard/base.html' %} + +{% block title %}Standortliste{% endblock %} + +{% block content %} + +{% if location_list %} +

Bitte Standort auswählen:

+ + + + + + + +{% if perms.billard.change_accounting %} + +{% endif %} + +{% for loc in location_list %} + + + + + + +{% if perms.billard.change_accounting %} + +{% endif %} + +{% endfor %} +
CodeNameStrassePlzOrtAccounting
{{ loc.code|default_if_none:"" }}{{ loc.name|default_if_none:"" }}{{ loc.street|default_if_none:"" }}{{ loc.plz|default_if_none:"" }}{{ loc.city|default_if_none:"" }}Abrechnen
+{% else %} +

Keine Standorte Zugeordnet.

+{% endif %} + +{% endblock %} diff --git a/billard/urls.py b/billard/urls.py index c61e51c..77853a3 100644 --- a/billard/urls.py +++ b/billard/urls.py @@ -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[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[0-9]+)/$', login_required(views.LocationDetailView.as_view()), name='location_detail'), + # ex. /billard/1/accounting/ + url(r'^(?P[0-9]+)/accounting/$', views.AccountingView.as_view(), name='accounting_detail'), + # ex. /billard/1/accounting/confirm + url(r'^(?P[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[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[0-9]+)$', views.accountmodalconfirmview, name="accountmodalconfirm") + # ex. /billard/process_location_data/ + url(r'^process_location_data/$', views.process_location_data, name='process_location_data'), ] diff --git a/billard/views.py b/billard/views.py index c78c742..be4c464 100644 --- a/billard/views.py +++ b/billard/views.py @@ -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')