Merge branch 'release/0.2.2'

This commit is contained in:
Robert Einsle 2017-08-18 10:41:31 +02:00
commit 2acd2fb952
14 changed files with 117 additions and 112 deletions

View File

@ -1,4 +1,8 @@
from django.contrib import admin from django.conf.urls import url
from django.contrib import admin, messages
from django.shortcuts import redirect
from django.template.response import TemplateResponse
from .models import * from .models import *
from django import forms from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
@ -33,6 +37,16 @@ class ClientAdmin(admin.ModelAdmin):
@admin.register(LocationData) @admin.register(LocationData)
class LocationDataAdmin(admin.ModelAdmin): class LocationDataAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super().get_urls()
my_urls = [
url(r'^process_locationdata/$', self.admin_site.admin_view(self.process_locationdata), name='process_locationdata'),
]
return my_urls + urls
def process_locationdata(self, request):
messages.success(request, 'Items processed.')
return redirect('admin:billard_locationdata_changelist')
list_display = ('client_id', 'desk_no', 'tst', 'on_off', 'processed', 'error_msg') list_display = ('client_id', 'desk_no', 'tst', 'on_off', 'processed', 'error_msg')
fields = ['client_id', 'desk_no', 'tst', 'on_off', 'processed', 'error_msg'] fields = ['client_id', 'desk_no', 'tst', 'on_off', 'processed', 'error_msg']
@ -61,4 +75,6 @@ class AccountingAdmin(admin.ModelAdmin):
list_filter = ('desk__client__location', 'account_user', 'account_tst', 'billed') list_filter = ('desk__client__location', 'account_user', 'account_tst', 'billed')
def has_add_permission(self, request): def has_add_permission(self, request):
if request.user.username == 'reinsle':
return True
return False return False

View File

@ -100,4 +100,4 @@ class Accounting(models.Model):
@receiver(post_save, sender=LocationData) @receiver(post_save, sender=LocationData)
def test(sender, **kwargs): def test(sender, **kwargs):
from .tasks import process_location_data from .tasks import process_location_data
process_location_data.delay() process_location_data()

View File

@ -0,0 +1,4 @@
/**
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);

View File

@ -0,0 +1,6 @@
/*! Respond.js v1.4.2: min/max-width media query polyfill
* Copyright 2014 Scott Jehl
* Licensed under MIT
* https://j.mp/respondjs */
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){v(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},g=function(a){return a.replace(c.regex.minmaxwh,"").match(c.regex.other)};if(c.ajax=f,c.queue=d,c.unsupportedmq=g,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,comments:/\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,maxw:/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/,minmaxwh:/\(\s*m(in|ax)\-(height|width)\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/gi,other:/\([^\)]*\)/g},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var h,i,j,k=a.document,l=k.documentElement,m=[],n=[],o=[],p={},q=30,r=k.getElementsByTagName("head")[0]||l,s=k.getElementsByTagName("base")[0],t=r.getElementsByTagName("link"),u=function(){var a,b=k.createElement("div"),c=k.body,d=l.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=k.createElement("body"),c.style.background="none"),l.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&l.insertBefore(c,l.firstChild),a=b.offsetWidth,f?l.removeChild(c):c.removeChild(b),l.style.fontSize=d,e&&(c.style.fontSize=e),a=j=parseFloat(a)},v=function(b){var c="clientWidth",d=l[c],e="CSS1Compat"===k.compatMode&&d||k.body[c]||d,f={},g=t[t.length-1],p=(new Date).getTime();if(b&&h&&q>p-h)return a.clearTimeout(i),i=a.setTimeout(v,q),void 0;h=p;for(var s in m)if(m.hasOwnProperty(s)){var w=m[s],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?j||u():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?j||u():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(n[w.rules]))}for(var C in o)o.hasOwnProperty(C)&&o[C]&&o[C].parentNode===r&&r.removeChild(o[C]);o.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=k.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,r.insertBefore(E,g.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(k.createTextNode(F)),o.push(E)}},w=function(a,b,d){var e=a.replace(c.regex.comments,"").replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},i=!f&&d;b.length&&(b+="/"),i&&(f=1);for(var j=0;f>j;j++){var k,l,o,p;i?(k=d,n.push(h(a))):(k=e[j].match(c.regex.findStyles)&&RegExp.$1,n.push(RegExp.$2&&h(RegExp.$2))),o=k.split(","),p=o.length;for(var q=0;p>q;q++)l=o[q],g(l)||m.push({media:l.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:n.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}v()},x=function(){if(d.length){var b=d.shift();f(b.href,function(c){w(c,b.href,b.media),p[b.href]=!0,a.setTimeout(function(){x()},0)})}},y=function(){for(var b=0;b<t.length;b++){var c=t[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!p[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(w(c.styleSheet.rawCssText,e,f),p[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!s||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}x()};y(),c.update=y,c.getEmValue=u,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);

View File

@ -2,16 +2,16 @@ from __future__ import absolute_import, unicode_literals
import logging import logging
import billard.utils as utils import billard.utils as utils
from celery import shared_task
from billard.models import LocationData, Client, Accounting from billard.models import LocationData, Client, Accounting
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@shared_task
def process_location_data(): def process_location_data():
data = LocationData.objects.filter(processed=False) data = LocationData.objects.filter(processed=False).order_by('tst')
for ld in data: for ld in data:
try:
cli = Client.objects.filter(uuid=ld.client_id, desks__desk_no=ld.desk_no) cli = Client.objects.filter(uuid=ld.client_id, desks__desk_no=ld.desk_no)
if cli.count() < 1: if cli.count() < 1:
ld.processed = True ld.processed = True
@ -61,3 +61,5 @@ def process_location_data():
ld.error_msg = 'No existing accountings found. Stopp processing! {}, {}'.format(ld.client_id, ld.desk_no) ld.error_msg = 'No existing accountings found. Stopp processing! {}, {}'.format(ld.client_id, ld.desk_no)
ld.save() ld.save()
log.error(ld.error_msg) log.error(ld.error_msg)
except:
log.exception('', exc_info=True)

View File

@ -0,0 +1,10 @@
{% extends "admin/change_list.html" %}
{% load i18n admin_urls static admin_list %}
{% block object-tools-items %}
<li>
<a href="{% url 'admin:process_locationdata' %}">
LD Verarbeiten
</a>
</li>
{{ block.super }}
{% endblock %}

View File

@ -6,16 +6,22 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>carom - {% block title %}TITLE SETZEN{% endblock %}</title> <title>carom - {% block title %}TITLE SETZEN{% endblock %}</title>
<meta name="description" content=""> <meta name="description" content="carom billard management">
<meta name="author" content=""> <meta name="author" content="Robert Einsle <robert@einsle.de>">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
{% block header %} {% block header %}
{% endblock %} {% endblock %}
<!-- Bootstrap --> <!-- Bootstrap -->
<link href="{% static 'billard/css/bootstrap.min.css' %}" rel="stylesheet" type="text/css"> <link href="{% static 'billard/css/bootstrap.css' %}" rel="stylesheet" type="text/css">
<link href="{% static 'billard/css/billard.css' %}" rel="stylesheet" type="text/css"> <link href="{% static 'billard/css/billard.css' %}" rel="stylesheet" type="text/css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="{% static 'billard/js/html5shiv.min.js' %}"></script>
<script src="{% static 'billard/js/respond.min.js' %}" type="text/javascript"></script>
<![endif]-->
</head> </head>
<body> <body>
<nav class="navbar navbar-inverse navbar-fixed-top"> <header class="navbar navbar-inverse navbar-fixed-top">
<div class="container"> <div class="container">
<div class="navbar-header"> <div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
@ -44,19 +50,19 @@
{% endif %} {% endif %}
</ul> </ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
<li><a href="#">rel. c@0.2.0</a></li> <li><a href="#">c@0.2.2</a></li>
</ul> </ul>
</div><!--/.nav-collapse --> </div><!--/.nav-collapse -->
</div> </div>
</nav> </header>
<div class="container" id="content"> <div class="container" id="content">
{% block content %} {% block content %}
{% endblock %} {% endblock %}
</div><!-- /.container --> </div><!-- /.container -->
<script src="{% static 'billard/js/jquery-1.12.4.min.js' %}"></script> <script src="{% static 'billard/js/jquery-1.12.4.min.js' %}" type="text/javascript"></script>
<script src="{% static 'billard/js/bootstrap.min.js' %}"></script> <script src="{% static 'billard/js/bootstrap.js' %}" type="text/javascript"></script>
<script src="{% static 'billard/js/carom.js' %}"></script> <script src="{% static 'billard/js/carom.js' %}" type="text/javascript"></script>
{% block js %} {% block js %}
{% endblock %} {% endblock %}
</body> </body>

View File

@ -4,7 +4,7 @@ from rest_framework import routers
from billard import views from billard import views
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register(r'location_data', views.LocationDataViewSet) router.register(r'locationdata', views.LocationDataViewSet)
app_name = 'billard' app_name = 'billard'
urlpatterns = [ urlpatterns = [

View File

@ -1,4 +1,5 @@
import ast import ast
import logging
from billard.serializers import LocationDataSerializer from billard.serializers import LocationDataSerializer
from billard.models import LocationData, Location, Client, Accounting from billard.models import LocationData, Location, Client, Accounting
@ -13,6 +14,9 @@ from django.utils.decorators import method_decorator
from django.utils import timezone from django.utils import timezone
log = logging.getLogger(__name__)
class LocationIndexView(generic.ListView): class LocationIndexView(generic.ListView):
template_name = 'billard/location_index.html' template_name = 'billard/location_index.html'
context_object_name = 'location_list' context_object_name = 'location_list'
@ -43,7 +47,8 @@ class AccountingView(generic.ListView):
context_object_name = 'accounting' context_object_name = 'accounting'
def get_queryset(self): def get_queryset(self):
return Accounting.objects.filter(billed=False).exclude(time_to__isnull=True).order_by('time_from') return Accounting.objects.filter(billed=False).filter(desk__client__location_id=self.kwargs['pk'])\
.exclude(time_to__isnull=True).order_by('time_from')
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
result = super(AccountingView, self).dispatch(request, *args, **kwargs) result = super(AccountingView, self).dispatch(request, *args, **kwargs)
@ -63,9 +68,11 @@ def accounting_confirm(request, pk):
if 'accountings' in request.POST: if 'accountings' in request.POST:
acc_ids = ast.literal_eval(request.POST['accountings']) acc_ids = ast.literal_eval(request.POST['accountings'])
if len(acc_ids) > 0: if len(acc_ids) > 0:
Accounting.objects.filter(id__in=acc_ids).update(billed=True) Accounting.objects.filter(id__in=acc_ids).update(
Accounting.objects.filter(id__in=acc_ids).update(account_user=request.user.username) billed=True,
Accounting.objects.filter(id__in=acc_ids).update(account_tst=timezone.now()) account_user=request.user.username,
account_tst=timezone.now(),
)
resp = redirect('billard:accounting_detail', pk=pk) resp = redirect('billard:accounting_detail', pk=pk)
return resp return resp

View File

@ -1,7 +0,0 @@
from __future__ import absolute_import, unicode_literals
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ['celery_app']

View File

@ -1,28 +0,0 @@
from __future__ import absolute_import, unicode_literals
import os
import django
from celery import Celery
from django.conf import settings
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'caromserver.settings')
app = Celery(settings.CELERY_PREFIX)
# Using a string here means the worker don't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings')
# Load task modules from all registered Django app configs.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "caromserver.settings")
django.setup()
app.autodiscover_tasks(['billard'])
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))

View File

@ -138,14 +138,6 @@ LOGOUT_URL = 'logout'
LOGIN_REDIRECT_URL = 'billard:location_index' LOGIN_REDIRECT_URL = 'billard:location_index'
LOGOUT_REDIRECT_URL = 'billard:location_index' LOGOUT_REDIRECT_URL = 'billard:location_index'
# CELERY STUFF
BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Europe/Berlin'
# Admin eMails # Admin eMails
ADMINS = ( ADMINS = (
('Robert Einsle', 'robert@einsle.de'), ('Robert Einsle', 'robert@einsle.de'),
@ -162,8 +154,6 @@ URL_LOCATION_PROCESSOR = 'http://127.0.0.1:8000/billard/process_locationdata'
STATIC_ROOT = "/srv/carom/carom-server/static/" STATIC_ROOT = "/srv/carom/carom-server/static/"
CELERY_PREFIX = 'carom'
try: try:
from local_settings import * from local_settings import *
except ImportError: except ImportError:

View File

@ -1,6 +1,5 @@
celery==4.0.2 Django>=1.11
Django==1.11
django-crispy-forms==1.6.1 django-crispy-forms==1.6.1
django-extensions==1.7.8 django-extensions>=1.7.0
djangorestframework==3.6.2 djangorestframework>=3.6.0
requests==2.13.0 requests>=2.18.0

View File

@ -5,7 +5,7 @@ from datetime import datetime
import requests import requests
url = 'http://127.0.0.1:8000/billard/api/v1/location_data/' url = 'http://127.0.0.1:8000/billard/api/v1/locationdata/'
client_id = '28a34fa1-7b62-4b78-8d2a-ada4db4ac6ea' client_id = '28a34fa1-7b62-4b78-8d2a-ada4db4ac6ea'
token = '588d0f4c4b8b90b507e6d5c0ea26f0e28b021262' token = '588d0f4c4b8b90b507e6d5c0ea26f0e28b021262'
default_desk_id = 2 default_desk_id = 2