2017-06-22 16:36:08 +02:00
|
|
|
from datetime import timedelta
|
|
|
|
|
2017-06-21 07:08:28 +02:00
|
|
|
from django.utils import timezone
|
|
|
|
|
|
|
|
from ..decorators import kfet_is_team
|
|
|
|
from ..utils import CachedMixin
|
|
|
|
|
|
|
|
|
|
|
|
class OpenKfet(CachedMixin, object):
|
|
|
|
"""Manage "open" status of a place.
|
|
|
|
|
|
|
|
Stores raw data (e.g. sent by raspberry), and user-set values
|
|
|
|
(as force_close).
|
2017-06-21 23:31:27 +02:00
|
|
|
Setting differents `cache_prefix` allows different places management.
|
2017-06-21 07:08:28 +02:00
|
|
|
Current state persists through cache.
|
|
|
|
|
|
|
|
"""
|
2017-06-22 16:36:08 +02:00
|
|
|
# status is unknown after this duration
|
|
|
|
time_unknown = timedelta(minutes=15)
|
|
|
|
|
|
|
|
# status
|
|
|
|
OPENED = 'opened'
|
|
|
|
CLOSED = 'closed'
|
|
|
|
UNKNOWN = 'unknown'
|
|
|
|
# admin status
|
|
|
|
FAKE_CLOSED = 'fake_closed'
|
|
|
|
|
|
|
|
# cached attributes config
|
2017-06-21 07:08:28 +02:00
|
|
|
cached = {
|
|
|
|
'_raw_open': False,
|
|
|
|
'_last_update': None,
|
|
|
|
'force_close': False,
|
|
|
|
}
|
|
|
|
cache_prefix = 'kfetopen'
|
|
|
|
|
|
|
|
@property
|
|
|
|
def raw_open(self):
|
|
|
|
"""Defined as property to update `last_update` on `raw_open` update."""
|
|
|
|
return self._raw_open
|
|
|
|
|
|
|
|
@raw_open.setter
|
|
|
|
def raw_open(self, value):
|
|
|
|
self._last_update = timezone.now()
|
|
|
|
self._raw_open = value
|
|
|
|
|
|
|
|
@property
|
|
|
|
def last_update(self):
|
|
|
|
"""Prevent `last_update` to be set."""
|
|
|
|
return self._last_update
|
|
|
|
|
|
|
|
@property
|
|
|
|
def is_open(self):
|
|
|
|
"""Take into account force_close."""
|
|
|
|
return False if self.force_close else self.raw_open
|
|
|
|
|
2017-06-22 16:36:08 +02:00
|
|
|
def status(self):
|
|
|
|
if (self.last_update is None or
|
|
|
|
timezone.now() - self.last_update >= self.time_unknown):
|
|
|
|
return self.UNKNOWN
|
|
|
|
return self.OPENED if self.is_open else self.CLOSED
|
|
|
|
|
|
|
|
def admin_status(self, status=None):
|
|
|
|
if status is None:
|
|
|
|
status = self.status()
|
|
|
|
if status == self.CLOSED and self.raw_open:
|
|
|
|
return self.FAKE_CLOSED
|
|
|
|
return status
|
|
|
|
|
2017-06-21 07:08:28 +02:00
|
|
|
def _export(self):
|
|
|
|
"""Export internal state.
|
|
|
|
|
|
|
|
Used by WS initialization and updates.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
(tuple): (base, team)
|
|
|
|
- team for team users.
|
|
|
|
- base for others.
|
|
|
|
|
|
|
|
"""
|
2017-06-22 16:36:08 +02:00
|
|
|
status = self.status()
|
2017-06-21 07:08:28 +02:00
|
|
|
base = {
|
2017-06-22 16:36:08 +02:00
|
|
|
'status': status,
|
2017-06-21 07:08:28 +02:00
|
|
|
}
|
|
|
|
restrict = {
|
2017-06-22 16:36:08 +02:00
|
|
|
'admin_status': self.admin_status(status),
|
2017-06-21 07:08:28 +02:00
|
|
|
'force_close': self.force_close,
|
|
|
|
}
|
2018-01-10 17:25:07 +01:00
|
|
|
return base, dict(base, **restrict)
|
2017-06-21 07:08:28 +02:00
|
|
|
|
2017-06-22 16:36:08 +02:00
|
|
|
def export(self, user):
|
|
|
|
"""Export internal state for a given user.
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
Returns:
|
|
|
|
(dict): Internal state. Only variables visible for the user are
|
2017-06-22 16:36:08 +02:00
|
|
|
exported, according to its permissions.
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
"""
|
|
|
|
base, team = self._export()
|
2017-06-22 16:36:08 +02:00
|
|
|
return team if kfet_is_team(user) else base
|
2017-06-21 07:08:28 +02:00
|
|
|
|
|
|
|
def send_ws(self):
|
|
|
|
"""Send internal state to websocket channels."""
|
|
|
|
from .consumers import OpenKfetConsumer
|
|
|
|
base, team = self._export()
|
|
|
|
OpenKfetConsumer.group_send('kfet.open.base', base)
|
|
|
|
OpenKfetConsumer.group_send('kfet.open.team', team)
|
|
|
|
|
|
|
|
|
|
|
|
kfet_open = OpenKfet()
|