You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

207 lines
7.9 KiB

import arrow
from datetime import datetime, timedelta, date
from django.conf import settings
from django.db import models
from django.urls import reverse_lazy
from django.utils.functional import cached_property
from django.utils.timezone import now
from project.mixins import BaseModel, DeactivatedMixin
from apps.content.models import ImageObject
from apps.payment import models as payment_models
class SchoolSchedule(models.Model):
WEEKDAY_SHORT_NAMES = ('пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс')
WEEKDAY_CHOICES = (
(1, 'понедельник'),
(2, 'вторник'),
(3, 'среда'),
(4, 'четверг'),
(5, 'пятница'),
(6, 'суббота'),
(7, 'воскресенье'),
)
weekday = models.PositiveSmallIntegerField(
'День недели', choices=WEEKDAY_CHOICES,
)
title = models.CharField('Заголовок', default='', max_length=100, db_index=True)
short_description = models.CharField(
'Короткое описание', default='', max_length=100, db_index=True
)
description = models.TextField('Описание')
materials = models.TextField('Материалы')
age = models.PositiveSmallIntegerField('Возраст', default=0)
month_price = models.DecimalField('Цена', max_digits=8, decimal_places=2, default=0)
day_discount = models.DecimalField(
'Скидка, в валюте', max_digits=8, decimal_places=2, default=0
)
start_at = models.TimeField('Начало урока', null=True)
cover = models.ForeignKey(
ImageObject,
related_name='schoolschedule_cover',
verbose_name='Обложка дня',
on_delete=models.SET_NULL,
null=True,
blank=True,
)
trial_lesson = models.URLField(default='', blank=True)
is_camp = models.BooleanField(default=False)
class Meta:
ordering = ('weekday',)
verbose_name = 'Расписание'
verbose_name_plural = 'Расписания'
unique_together = (('weekday', 'is_camp'),)
def __str__(self):
return dict(self.WEEKDAY_CHOICES).get(self.weekday, '')
def is_online(self):
end_at = datetime.combine(now().today(), self.start_at) + timedelta(hours=1)
return self.start_at <= now().time() and end_at.time() >= now().time() and self.weekday == now().isoweekday()
@cached_property
def current_live_lesson(self):
september2018 = date(2018, 9, 1)
date_start = max(september2018, now().date())
live_lesson = LiveLesson.objects.filter(
date__week_day=self.weekday % 7 + 1,
date__range=[date_start, date_start + timedelta(days=6)],
deactivated_at__isnull=True,
is_camp=False,
).first()
return live_lesson
@cached_property
def previous_live_lesson(self):
now_time = now()
live_lesson = LiveLesson.objects.filter(
date__week_day=self.weekday % 7 + 1,
date__range=[(now_time - timedelta(days=8)).date(), (now_time - timedelta(days=1)).date()],
deactivated_at__isnull=True,
is_camp=False,
).first()
return live_lesson
@cached_property
def current_camp_lesson(self):
date_start = now().date()
live_lesson = LiveLesson.objects.filter(
date__week_day=self.weekday % 7 + 1,
date__range=[date_start, date_start + timedelta(days=6)],
deactivated_at__isnull=True,
is_camp=True,
).first()
return live_lesson
@cached_property
def previous_camp_lesson(self):
now_time = now()
live_lesson = LiveLesson.objects.filter(
date__week_day=self.weekday % 7 + 1,
date__range=[(now_time - timedelta(days=8)).date(), (now_time - timedelta(days=1)).date()],
deactivated_at__isnull=True,
is_camp=True,
).first()
return live_lesson
@property
def start_at_humanize(self):
return arrow.get(datetime.combine(datetime.today(), self.start_at), settings.TIME_ZONE).humanize(locale='ru') if self.start_at else None
class SchoolScheduleImage(models.Model):
schoolschedule = models.ForeignKey(
SchoolSchedule,
on_delete=models.CASCADE,
verbose_name='День занятия',
related_name='schoolschedule_images',
)
img = models.ForeignKey(
ImageObject,
related_name='schoolschedule_images',
verbose_name='Объект изображения',
on_delete=models.SET_NULL,
null=True,
blank=True,
)
created_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'Изображение работ'
verbose_name_plural = 'Изображения работ'
ordering = ('-created_at',)
class LiveLesson(BaseModel, DeactivatedMixin):
title = models.CharField('Название урока', max_length=100, default='', blank=True)
short_description = models.TextField('Краткое описание урока', default='', blank=True)
stream = models.URLField('Ссылка на VIMEO', default='', blank=True)
date = models.DateField(default=now, unique=True)
materials = models.TextField('Материалы', blank=True, default='')
cover = models.ForeignKey(
ImageObject,
related_name='livelesson_covers',
verbose_name='Обложка урока школы',
on_delete=models.SET_NULL,
null=True,
blank=True,
)
is_camp = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
update_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'Урок онлайн школы'
verbose_name_plural = 'Уроки онлайн школы'
ordering = ('-date', 'title',)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
if not self.id and LiveLesson.objects.filter(date=self.date).exists():
self.date = (datetime.combine(self.date, now().time()) + timedelta(days=1)).date()
super().save(*args, **kwargs)
@property
def url(self):
return self.get_absolute_url()
def get_absolute_url(self):
return (reverse_lazy('school:camp-lesson-detail', kwargs={'lesson_date': self.date.strftime('%d-%m-%y')})
if self.is_camp
else reverse_lazy('school:lesson-detail', kwargs={'lesson_date': self.date.strftime('%d-%m-%y')}))
def stream_index(self):
return self.stream.split('/')[-1]
@cached_property
def school_schedule(self):
try:
return SchoolSchedule.objects.get(weekday=self.date.isoweekday(), is_camp=self.is_camp)
except SchoolSchedule.DoesNotExist:
return None
@property
def is_online(self):
# если урок открыт, он сегодняшний и прошло не больше часа с момента старта - значит онлайн
if self.is_opened and self.school_schedule:
today = now().date()
end_at = datetime.combine(today, self.school_schedule.start_at) + timedelta(hours=1)
return self.date == today and end_at.time() >= now().time()
return False
@property
def is_opened(self):
# если есть заголовок и дата меньше сегодняшней (прошлый урок) или сегодняшняя и время показа урока уже пришло
# тогда урок считается открытым к просмотру
today = now().date()
return self.title and (self.date < today or (self.date == today and self.school_schedule
and self.school_schedule.start_at <= now().time()))