carom-server/billard/models.py
2017-02-20 18:49:55 +01:00

153 lines
6.1 KiB
Python

import uuid
from django.db import models
from django.contrib.auth.models import User
from datetime import datetime, timezone
from billard import utils
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.core.mail import mail_admins
from celery import shared_task
from .tasks import request_process_location_data
class LocationData(models.Model):
client_id = models.UUIDField(blank=False, null=False, verbose_name="Client-ID")
desk_no = models.IntegerField(blank=False, null=False, verbose_name="Tischnummer")
tst = models.DateTimeField(blank=False, null=False, verbose_name="Zeitstempel")
on_off = models.BooleanField(blank=False, null=False, verbose_name="Ein/Ausgebucht")
processed = models.BooleanField(default=False, verbose_name="Verarbeitet")
error_msg = models.TextField(blank=True, null=True, verbose_name="Fehlermeldung")
def __str__(self):
return str(self.client_id)
class Meta:
verbose_name = "Standortlog"
verbose_name_plural = "Standortlogs"
class Location(models.Model):
users = models.ManyToManyField(User, related_name='locations', verbose_name="Benutzer")
code = models.CharField(max_length=16, unique=True, verbose_name="Code")
name = models.CharField(max_length=64, unique=True, verbose_name="Name")
street = models.CharField(max_length=64, blank=True, null=True, verbose_name="Straße")
plz = models.CharField(max_length=8, blank=True, null=True, verbose_name="Postleitzahl")
city = models.CharField(max_length=64, blank=True, null=True, verbose_name="Stadt")
phone = models.CharField(max_length=64, blank=True, null=True, verbose_name="Telefon")
email = models.EmailField(blank=True, null=True, verbose_name="Email")
url = models.URLField(blank=True,null=True, verbose_name="URL")
def __str__(self):
return self.name
class Meta:
verbose_name = "Standort"
verbose_name_plural = "Standorte"
class Client(models.Model):
uuid = models.UUIDField(unique=True, default=uuid.uuid4, verbose_name="Identifier")
location = models.ForeignKey(Location, verbose_name="Standort")
def __str__(self):
return '{}, {}'.format(self.location.name, self.uuid)
class Meta:
verbose_name = "Client"
verbose_name_plural = "Clienten"
class Desk(models.Model):
client = models.ForeignKey(Client, verbose_name='Client', related_name='desks')
desk_no = models.IntegerField(verbose_name='Tischnummer')
name = models.CharField(max_length=32, blank=True, null=True, verbose_name='Tischbezeichnung')
enabled = models.BooleanField(verbose_name='Tisch aktiv')
prize = models.DecimalField(max_digits=5, decimal_places=2, default=0.0, verbose_name="Normalpreis")
prize_hh = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True,
verbose_name="Preis Happy Hour")
def accounting_for(self):
t = Accounting.objects.filter(client=self.client, desk_no=self.desk_no)[:3][::-1]
if t.__len__() > 0:
a = t[t.__len__() - 1]
if a.time_to is None:
prize = utils.get_prize_for(start=a.time_from, end=datetime.now(timezone.utc), pph=self.prize)
if prize != a.prize:
a.prize = prize
return t
def __str__(self):
return '{}, {}'.format(self.client.uuid, self.name)
class Meta:
verbose_name = "Tisch"
verbose_name_plural = "Tische"
class Accounting(models.Model):
desk = models.ForeignKey(Desk, verbose_name="Tisch")
time_from = models.DateTimeField(verbose_name="Beginn")
time_to = models.DateTimeField(blank=True, null=True, verbose_name="Ende")
prize = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True, verbose_name="Preis")
billed = models.BooleanField(default=False, verbose_name="Abgerechnet")
def __str__(self):
return '{}: {} -> {}, {}, {}'.format(self.desk, self.time_from, self.time_to, self.prize, self.billed)
class Meta:
ordering = ['-time_from']
verbose_name = "Buchhaltungseintrag"
verbose_name_plural = "Buchhaltungseinträge"
@receiver(post_save, sender=LocationData)
def test(sender, **kwargs):
request_process_location_data.delay()
@shared_task
def process_location_data():
data = LocationData.objects.filter(processed=False)
for ld in data:
cli = Client.objects.filter(uuid=ld.client_id, desks__desk_no=ld.desk_no)
if cli.count() < 1:
ld.processed = True
ld.error_msg = 'No client object found. Stopp processing! {}, {}'.format(ld.client_id, ld.desk_no)
ld.save()
mail_admins(subject=ld.error_msg, message=ld.error_msg)
else:
cli = cli[0]
desk = cli.desks.filter(desk_no=ld.desk_no, enabled=True)
if desk.count() != 1:
ld.processed = True
ld.error_msg = 'No desk object found. Stopp processing! {}, {}'.format(ld.client_id, ld.desk_no)
ld.save()
mail_admins(subject=ld.error_msg, message=ld.error_msg)
desk = desk[0]
ac = desk.accounting_set.order_by('time_from').reverse()
if ld.on_off:
acc = None
if ac.count() > 0 and ac[0].time_to is None:
mail_admins(subject='Accounting passt nicht',
message='Vorheriges Accounting nicht abgeschlossen: Desk_id {}, Accounting_id {}'
.format(desk.id, ac[0].id))
acc = ac[0]
if acc is None:
acc = Accounting(
desk=desk,
time_from=ld.tst,
)
acc.save()
ld.delete()
else:
acc = ac[0]
acc.time_to = ld.tst
acc.prize = utils.get_prize_for(
start=acc.time_from,
end=ld.tst,
pph=desk.prize
)
acc.save()
ld.delete()